xref: /aosp_15_r20/external/armnn/profiling/client/src/SendThread.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #include "SendThread.hpp"
7*89c4ff92SAndroid Build Coastguard Worker #include "ProfilingUtils.hpp"
8*89c4ff92SAndroid Build Coastguard Worker 
9*89c4ff92SAndroid Build Coastguard Worker #include <common/include/NumericCast.hpp>
10*89c4ff92SAndroid Build Coastguard Worker #include <common/include/ProfilingException.hpp>
11*89c4ff92SAndroid Build Coastguard Worker 
12*89c4ff92SAndroid Build Coastguard Worker #if defined(ARMNN_DISABLE_THREADS)
13*89c4ff92SAndroid Build Coastguard Worker #include <common/include/IgnoreUnused.hpp>
14*89c4ff92SAndroid Build Coastguard Worker #endif
15*89c4ff92SAndroid Build Coastguard Worker 
16*89c4ff92SAndroid Build Coastguard Worker #include <cstring>
17*89c4ff92SAndroid Build Coastguard Worker 
18*89c4ff92SAndroid Build Coastguard Worker namespace arm
19*89c4ff92SAndroid Build Coastguard Worker {
20*89c4ff92SAndroid Build Coastguard Worker 
21*89c4ff92SAndroid Build Coastguard Worker namespace pipe
22*89c4ff92SAndroid Build Coastguard Worker {
23*89c4ff92SAndroid Build Coastguard Worker 
SendThread(ProfilingStateMachine & profilingStateMachine,IBufferManager & buffer,ISendCounterPacket & sendCounterPacket,int timeout)24*89c4ff92SAndroid Build Coastguard Worker SendThread::SendThread(ProfilingStateMachine& profilingStateMachine,
25*89c4ff92SAndroid Build Coastguard Worker                        IBufferManager& buffer,
26*89c4ff92SAndroid Build Coastguard Worker                        ISendCounterPacket& sendCounterPacket,
27*89c4ff92SAndroid Build Coastguard Worker                        int timeout)
28*89c4ff92SAndroid Build Coastguard Worker     : m_StateMachine(profilingStateMachine)
29*89c4ff92SAndroid Build Coastguard Worker     , m_BufferManager(buffer)
30*89c4ff92SAndroid Build Coastguard Worker     , m_SendCounterPacket(sendCounterPacket)
31*89c4ff92SAndroid Build Coastguard Worker     , m_Timeout(timeout)
32*89c4ff92SAndroid Build Coastguard Worker     , m_IsRunning(false)
33*89c4ff92SAndroid Build Coastguard Worker     , m_KeepRunning(false)
34*89c4ff92SAndroid Build Coastguard Worker     , m_SendThreadException(nullptr)
35*89c4ff92SAndroid Build Coastguard Worker {
36*89c4ff92SAndroid Build Coastguard Worker     m_BufferManager.SetConsumer(this);
37*89c4ff92SAndroid Build Coastguard Worker }
38*89c4ff92SAndroid Build Coastguard Worker 
SetReadyToRead()39*89c4ff92SAndroid Build Coastguard Worker void SendThread::SetReadyToRead()
40*89c4ff92SAndroid Build Coastguard Worker {
41*89c4ff92SAndroid Build Coastguard Worker     // We need to wait for the send thread to release its mutex
42*89c4ff92SAndroid Build Coastguard Worker     {
43*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
44*89c4ff92SAndroid Build Coastguard Worker         std::lock_guard<std::mutex> lck(m_WaitMutex);
45*89c4ff92SAndroid Build Coastguard Worker #endif
46*89c4ff92SAndroid Build Coastguard Worker         m_ReadyToRead = true;
47*89c4ff92SAndroid Build Coastguard Worker     }
48*89c4ff92SAndroid Build Coastguard Worker     // Signal the send thread that there's something to read in the buffer
49*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
50*89c4ff92SAndroid Build Coastguard Worker     m_WaitCondition.notify_one();
51*89c4ff92SAndroid Build Coastguard Worker #endif
52*89c4ff92SAndroid Build Coastguard Worker }
53*89c4ff92SAndroid Build Coastguard Worker 
Start(IProfilingConnection & profilingConnection)54*89c4ff92SAndroid Build Coastguard Worker void SendThread::Start(IProfilingConnection& profilingConnection)
55*89c4ff92SAndroid Build Coastguard Worker {
56*89c4ff92SAndroid Build Coastguard Worker     // Check if the send thread is already running
57*89c4ff92SAndroid Build Coastguard Worker     if (m_IsRunning.load())
58*89c4ff92SAndroid Build Coastguard Worker     {
59*89c4ff92SAndroid Build Coastguard Worker         // The send thread is already running
60*89c4ff92SAndroid Build Coastguard Worker         return;
61*89c4ff92SAndroid Build Coastguard Worker     }
62*89c4ff92SAndroid Build Coastguard Worker 
63*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
64*89c4ff92SAndroid Build Coastguard Worker     if (m_SendThread.joinable())
65*89c4ff92SAndroid Build Coastguard Worker     {
66*89c4ff92SAndroid Build Coastguard Worker         m_SendThread.join();
67*89c4ff92SAndroid Build Coastguard Worker     }
68*89c4ff92SAndroid Build Coastguard Worker #endif
69*89c4ff92SAndroid Build Coastguard Worker 
70*89c4ff92SAndroid Build Coastguard Worker     // Mark the send thread as running
71*89c4ff92SAndroid Build Coastguard Worker     m_IsRunning.store(true);
72*89c4ff92SAndroid Build Coastguard Worker 
73*89c4ff92SAndroid Build Coastguard Worker     // Keep the send procedure going until the send thread is signalled to stop
74*89c4ff92SAndroid Build Coastguard Worker     m_KeepRunning.store(true);
75*89c4ff92SAndroid Build Coastguard Worker 
76*89c4ff92SAndroid Build Coastguard Worker     // Make sure the send thread will not flush the buffer until signaled to do so
77*89c4ff92SAndroid Build Coastguard Worker     // no need for a mutex as the send thread can not be running at this point
78*89c4ff92SAndroid Build Coastguard Worker     m_ReadyToRead = false;
79*89c4ff92SAndroid Build Coastguard Worker 
80*89c4ff92SAndroid Build Coastguard Worker     m_PacketSent = false;
81*89c4ff92SAndroid Build Coastguard Worker 
82*89c4ff92SAndroid Build Coastguard Worker     // Start the send thread
83*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
84*89c4ff92SAndroid Build Coastguard Worker     m_SendThread = std::thread(&SendThread::Send, this, std::ref(profilingConnection));
85*89c4ff92SAndroid Build Coastguard Worker #else
86*89c4ff92SAndroid Build Coastguard Worker     IgnoreUnused(profilingConnection);
87*89c4ff92SAndroid Build Coastguard Worker #endif
88*89c4ff92SAndroid Build Coastguard Worker }
89*89c4ff92SAndroid Build Coastguard Worker 
Stop(bool rethrowSendThreadExceptions)90*89c4ff92SAndroid Build Coastguard Worker void SendThread::Stop(bool rethrowSendThreadExceptions)
91*89c4ff92SAndroid Build Coastguard Worker {
92*89c4ff92SAndroid Build Coastguard Worker     // Signal the send thread to stop
93*89c4ff92SAndroid Build Coastguard Worker     m_KeepRunning.store(false);
94*89c4ff92SAndroid Build Coastguard Worker 
95*89c4ff92SAndroid Build Coastguard Worker     // Check that the send thread is running
96*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
97*89c4ff92SAndroid Build Coastguard Worker     if (m_SendThread.joinable())
98*89c4ff92SAndroid Build Coastguard Worker     {
99*89c4ff92SAndroid Build Coastguard Worker         // Kick the send thread out of the wait condition
100*89c4ff92SAndroid Build Coastguard Worker         SetReadyToRead();
101*89c4ff92SAndroid Build Coastguard Worker         // Wait for the send thread to complete operations
102*89c4ff92SAndroid Build Coastguard Worker         m_SendThread.join();
103*89c4ff92SAndroid Build Coastguard Worker     }
104*89c4ff92SAndroid Build Coastguard Worker #endif
105*89c4ff92SAndroid Build Coastguard Worker 
106*89c4ff92SAndroid Build Coastguard Worker     // Check if the send thread exception has to be rethrown
107*89c4ff92SAndroid Build Coastguard Worker     if (!rethrowSendThreadExceptions)
108*89c4ff92SAndroid Build Coastguard Worker     {
109*89c4ff92SAndroid Build Coastguard Worker         // No need to rethrow the send thread exception, return immediately
110*89c4ff92SAndroid Build Coastguard Worker         return;
111*89c4ff92SAndroid Build Coastguard Worker     }
112*89c4ff92SAndroid Build Coastguard Worker 
113*89c4ff92SAndroid Build Coastguard Worker     // Check if there's an exception to rethrow
114*89c4ff92SAndroid Build Coastguard Worker     if (m_SendThreadException)
115*89c4ff92SAndroid Build Coastguard Worker     {
116*89c4ff92SAndroid Build Coastguard Worker         // Rethrow the send thread exception
117*89c4ff92SAndroid Build Coastguard Worker         std::rethrow_exception(m_SendThreadException);
118*89c4ff92SAndroid Build Coastguard Worker 
119*89c4ff92SAndroid Build Coastguard Worker         // Nullify the exception as it has been rethrown
120*89c4ff92SAndroid Build Coastguard Worker         m_SendThreadException = nullptr;
121*89c4ff92SAndroid Build Coastguard Worker     }
122*89c4ff92SAndroid Build Coastguard Worker }
123*89c4ff92SAndroid Build Coastguard Worker 
Send(IProfilingConnection & profilingConnection)124*89c4ff92SAndroid Build Coastguard Worker void SendThread::Send(IProfilingConnection& profilingConnection)
125*89c4ff92SAndroid Build Coastguard Worker {
126*89c4ff92SAndroid Build Coastguard Worker     // Run once and keep the sending procedure looping until the thread is signalled to stop
127*89c4ff92SAndroid Build Coastguard Worker     do
128*89c4ff92SAndroid Build Coastguard Worker     {
129*89c4ff92SAndroid Build Coastguard Worker         // Check the current state of the profiling service
130*89c4ff92SAndroid Build Coastguard Worker         ProfilingState currentState = m_StateMachine.GetCurrentState();
131*89c4ff92SAndroid Build Coastguard Worker         switch (currentState)
132*89c4ff92SAndroid Build Coastguard Worker         {
133*89c4ff92SAndroid Build Coastguard Worker         case ProfilingState::Uninitialised:
134*89c4ff92SAndroid Build Coastguard Worker         case ProfilingState::NotConnected:
135*89c4ff92SAndroid Build Coastguard Worker 
136*89c4ff92SAndroid Build Coastguard Worker             // The send thread cannot be running when the profiling service is uninitialized or not connected,
137*89c4ff92SAndroid Build Coastguard Worker             // stop the thread immediately
138*89c4ff92SAndroid Build Coastguard Worker             m_KeepRunning.store(false);
139*89c4ff92SAndroid Build Coastguard Worker             m_IsRunning.store(false);
140*89c4ff92SAndroid Build Coastguard Worker 
141*89c4ff92SAndroid Build Coastguard Worker             // An exception should be thrown here, save it to be rethrown later from the main thread so that
142*89c4ff92SAndroid Build Coastguard Worker             // it can be caught by the consumer
143*89c4ff92SAndroid Build Coastguard Worker             m_SendThreadException =
144*89c4ff92SAndroid Build Coastguard Worker                 std::make_exception_ptr(arm::pipe::ProfilingException(
145*89c4ff92SAndroid Build Coastguard Worker                 "The send thread should not be running with the profiling service not yet initialized or connected"));
146*89c4ff92SAndroid Build Coastguard Worker 
147*89c4ff92SAndroid Build Coastguard Worker             return;
148*89c4ff92SAndroid Build Coastguard Worker         case ProfilingState::WaitingForAck:
149*89c4ff92SAndroid Build Coastguard Worker 
150*89c4ff92SAndroid Build Coastguard Worker             // Send out a StreamMetadata packet and wait for the profiling connection to be acknowledged.
151*89c4ff92SAndroid Build Coastguard Worker             // When a ConnectionAcknowledged packet is received, the profiling service state will be automatically
152*89c4ff92SAndroid Build Coastguard Worker             // updated by the command handler
153*89c4ff92SAndroid Build Coastguard Worker 
154*89c4ff92SAndroid Build Coastguard Worker             // Prepare a StreamMetadata packet and write it to the Counter Stream buffer
155*89c4ff92SAndroid Build Coastguard Worker             m_SendCounterPacket.SendStreamMetaDataPacket();
156*89c4ff92SAndroid Build Coastguard Worker 
157*89c4ff92SAndroid Build Coastguard Worker              // Flush the buffer manually to send the packet
158*89c4ff92SAndroid Build Coastguard Worker             FlushBuffer(profilingConnection);
159*89c4ff92SAndroid Build Coastguard Worker 
160*89c4ff92SAndroid Build Coastguard Worker             // Wait for a connection ack from the remote server. We should expect a response within timeout value.
161*89c4ff92SAndroid Build Coastguard Worker             // If not, drop back to the start of the loop and detect somebody closing the thread. Then send the
162*89c4ff92SAndroid Build Coastguard Worker             // StreamMetadata again.
163*89c4ff92SAndroid Build Coastguard Worker 
164*89c4ff92SAndroid Build Coastguard Worker             // Wait condition lock scope - Begin
165*89c4ff92SAndroid Build Coastguard Worker             {
166*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
167*89c4ff92SAndroid Build Coastguard Worker                 std::unique_lock<std::mutex> lock(m_WaitMutex);
168*89c4ff92SAndroid Build Coastguard Worker 
169*89c4ff92SAndroid Build Coastguard Worker                 bool timeout = m_WaitCondition.wait_for(lock,
170*89c4ff92SAndroid Build Coastguard Worker                                                         std::chrono::milliseconds(std::max(m_Timeout, 1000)),
171*89c4ff92SAndroid Build Coastguard Worker                                                         [&]{ return m_ReadyToRead; });
172*89c4ff92SAndroid Build Coastguard Worker                 // If we get notified we need to flush the buffer again
173*89c4ff92SAndroid Build Coastguard Worker                 if (timeout)
174*89c4ff92SAndroid Build Coastguard Worker                 {
175*89c4ff92SAndroid Build Coastguard Worker                     // Otherwise if we just timed out don't flush the buffer
176*89c4ff92SAndroid Build Coastguard Worker                     continue;
177*89c4ff92SAndroid Build Coastguard Worker                 }
178*89c4ff92SAndroid Build Coastguard Worker #endif
179*89c4ff92SAndroid Build Coastguard Worker                 //reset condition variable predicate for next use
180*89c4ff92SAndroid Build Coastguard Worker                 m_ReadyToRead = false;
181*89c4ff92SAndroid Build Coastguard Worker             }
182*89c4ff92SAndroid Build Coastguard Worker             // Wait condition lock scope - End
183*89c4ff92SAndroid Build Coastguard Worker             break;
184*89c4ff92SAndroid Build Coastguard Worker         case ProfilingState::Active:
185*89c4ff92SAndroid Build Coastguard Worker         default:
186*89c4ff92SAndroid Build Coastguard Worker             // Wait condition lock scope - Begin
187*89c4ff92SAndroid Build Coastguard Worker             {
188*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
189*89c4ff92SAndroid Build Coastguard Worker                 std::unique_lock<std::mutex> lock(m_WaitMutex);
190*89c4ff92SAndroid Build Coastguard Worker #endif
191*89c4ff92SAndroid Build Coastguard Worker                 // Normal working state for the send thread
192*89c4ff92SAndroid Build Coastguard Worker                 // Check if the send thread is required to enforce a timeout wait policy
193*89c4ff92SAndroid Build Coastguard Worker                 if (m_Timeout < 0)
194*89c4ff92SAndroid Build Coastguard Worker                 {
195*89c4ff92SAndroid Build Coastguard Worker                     // Wait indefinitely until notified that something to read has become available in the buffer
196*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
197*89c4ff92SAndroid Build Coastguard Worker                     m_WaitCondition.wait(lock, [&] { return m_ReadyToRead; });
198*89c4ff92SAndroid Build Coastguard Worker #endif
199*89c4ff92SAndroid Build Coastguard Worker                 }
200*89c4ff92SAndroid Build Coastguard Worker                 else
201*89c4ff92SAndroid Build Coastguard Worker                 {
202*89c4ff92SAndroid Build Coastguard Worker                     // Wait until the thread is notified of something to read from the buffer,
203*89c4ff92SAndroid Build Coastguard Worker                     // or check anyway after the specified number of milliseconds
204*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
205*89c4ff92SAndroid Build Coastguard Worker                     m_WaitCondition.wait_for(lock, std::chrono::milliseconds(m_Timeout), [&] { return m_ReadyToRead; });
206*89c4ff92SAndroid Build Coastguard Worker #endif
207*89c4ff92SAndroid Build Coastguard Worker                 }
208*89c4ff92SAndroid Build Coastguard Worker 
209*89c4ff92SAndroid Build Coastguard Worker                 //reset condition variable predicate for next use
210*89c4ff92SAndroid Build Coastguard Worker                 m_ReadyToRead = false;
211*89c4ff92SAndroid Build Coastguard Worker             }
212*89c4ff92SAndroid Build Coastguard Worker             // Wait condition lock scope - End
213*89c4ff92SAndroid Build Coastguard Worker             break;
214*89c4ff92SAndroid Build Coastguard Worker         }
215*89c4ff92SAndroid Build Coastguard Worker 
216*89c4ff92SAndroid Build Coastguard Worker         // Send all the available packets in the buffer
217*89c4ff92SAndroid Build Coastguard Worker         FlushBuffer(profilingConnection);
218*89c4ff92SAndroid Build Coastguard Worker     } while (m_KeepRunning.load());
219*89c4ff92SAndroid Build Coastguard Worker 
220*89c4ff92SAndroid Build Coastguard Worker     // Ensure that all readable data got written to the profiling connection before the thread is stopped
221*89c4ff92SAndroid Build Coastguard Worker     // (do not notify any watcher in this case, as this is just to wrap up things before shutting down the send thread)
222*89c4ff92SAndroid Build Coastguard Worker     FlushBuffer(profilingConnection, false);
223*89c4ff92SAndroid Build Coastguard Worker 
224*89c4ff92SAndroid Build Coastguard Worker     // Mark the send thread as not running
225*89c4ff92SAndroid Build Coastguard Worker     m_IsRunning.store(false);
226*89c4ff92SAndroid Build Coastguard Worker }
227*89c4ff92SAndroid Build Coastguard Worker 
FlushBuffer(IProfilingConnection & profilingConnection,bool notifyWatchers)228*89c4ff92SAndroid Build Coastguard Worker void SendThread::FlushBuffer(IProfilingConnection& profilingConnection, bool notifyWatchers)
229*89c4ff92SAndroid Build Coastguard Worker {
230*89c4ff92SAndroid Build Coastguard Worker     // Get the first available readable buffer
231*89c4ff92SAndroid Build Coastguard Worker     IPacketBufferPtr packetBuffer = m_BufferManager.GetReadableBuffer();
232*89c4ff92SAndroid Build Coastguard Worker 
233*89c4ff92SAndroid Build Coastguard Worker     // Initialize the flag that indicates whether at least a packet has been sent
234*89c4ff92SAndroid Build Coastguard Worker     bool packetsSent = false;
235*89c4ff92SAndroid Build Coastguard Worker 
236*89c4ff92SAndroid Build Coastguard Worker     while (packetBuffer != nullptr)
237*89c4ff92SAndroid Build Coastguard Worker     {
238*89c4ff92SAndroid Build Coastguard Worker         // Get the data to send from the buffer
239*89c4ff92SAndroid Build Coastguard Worker         const unsigned char* readBuffer = packetBuffer->GetReadableData();
240*89c4ff92SAndroid Build Coastguard Worker         unsigned int readBufferSize = packetBuffer->GetSize();
241*89c4ff92SAndroid Build Coastguard Worker 
242*89c4ff92SAndroid Build Coastguard Worker         if (readBuffer == nullptr || readBufferSize == 0)
243*89c4ff92SAndroid Build Coastguard Worker         {
244*89c4ff92SAndroid Build Coastguard Worker             // Nothing to send, get the next available readable buffer and continue
245*89c4ff92SAndroid Build Coastguard Worker             m_BufferManager.MarkRead(packetBuffer);
246*89c4ff92SAndroid Build Coastguard Worker             packetBuffer = m_BufferManager.GetReadableBuffer();
247*89c4ff92SAndroid Build Coastguard Worker 
248*89c4ff92SAndroid Build Coastguard Worker             continue;
249*89c4ff92SAndroid Build Coastguard Worker         }
250*89c4ff92SAndroid Build Coastguard Worker 
251*89c4ff92SAndroid Build Coastguard Worker         // Check that the profiling connection is open, silently drop the data and continue if it's closed
252*89c4ff92SAndroid Build Coastguard Worker         if (profilingConnection.IsOpen())
253*89c4ff92SAndroid Build Coastguard Worker         {
254*89c4ff92SAndroid Build Coastguard Worker             // Write a packet to the profiling connection. Silently ignore any write error and continue
255*89c4ff92SAndroid Build Coastguard Worker             profilingConnection.WritePacket(readBuffer, arm::pipe::numeric_cast<uint32_t>(readBufferSize));
256*89c4ff92SAndroid Build Coastguard Worker 
257*89c4ff92SAndroid Build Coastguard Worker             // Set the flag that indicates whether at least a packet has been sent
258*89c4ff92SAndroid Build Coastguard Worker             packetsSent = true;
259*89c4ff92SAndroid Build Coastguard Worker         }
260*89c4ff92SAndroid Build Coastguard Worker 
261*89c4ff92SAndroid Build Coastguard Worker         // Mark the packet buffer as read
262*89c4ff92SAndroid Build Coastguard Worker         m_BufferManager.MarkRead(packetBuffer);
263*89c4ff92SAndroid Build Coastguard Worker 
264*89c4ff92SAndroid Build Coastguard Worker         // Get the next available readable buffer
265*89c4ff92SAndroid Build Coastguard Worker         packetBuffer = m_BufferManager.GetReadableBuffer();
266*89c4ff92SAndroid Build Coastguard Worker     }
267*89c4ff92SAndroid Build Coastguard Worker     // Check whether at least a packet has been sent
268*89c4ff92SAndroid Build Coastguard Worker     if (packetsSent && notifyWatchers)
269*89c4ff92SAndroid Build Coastguard Worker     {
270*89c4ff92SAndroid Build Coastguard Worker         // Wait for the parent thread to release its mutex if necessary
271*89c4ff92SAndroid Build Coastguard Worker         {
272*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
273*89c4ff92SAndroid Build Coastguard Worker             std::lock_guard<std::mutex> lck(m_PacketSentWaitMutex);
274*89c4ff92SAndroid Build Coastguard Worker #endif
275*89c4ff92SAndroid Build Coastguard Worker             m_PacketSent = true;
276*89c4ff92SAndroid Build Coastguard Worker         }
277*89c4ff92SAndroid Build Coastguard Worker         // Notify to any watcher that something has been sent
278*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
279*89c4ff92SAndroid Build Coastguard Worker         m_PacketSentWaitCondition.notify_one();
280*89c4ff92SAndroid Build Coastguard Worker #endif
281*89c4ff92SAndroid Build Coastguard Worker     }
282*89c4ff92SAndroid Build Coastguard Worker }
283*89c4ff92SAndroid Build Coastguard Worker 
WaitForPacketSent(uint32_t timeout=1000)284*89c4ff92SAndroid Build Coastguard Worker bool SendThread::WaitForPacketSent(uint32_t timeout = 1000)
285*89c4ff92SAndroid Build Coastguard Worker {
286*89c4ff92SAndroid Build Coastguard Worker #if !defined(ARMNN_DISABLE_THREADS)
287*89c4ff92SAndroid Build Coastguard Worker     std::unique_lock<std::mutex> lock(m_PacketSentWaitMutex);
288*89c4ff92SAndroid Build Coastguard Worker     // Blocks until notified that at least a packet has been sent or until timeout expires.
289*89c4ff92SAndroid Build Coastguard Worker     bool timedOut = m_PacketSentWaitCondition.wait_for(lock,
290*89c4ff92SAndroid Build Coastguard Worker                                                        std::chrono::milliseconds(timeout),
291*89c4ff92SAndroid Build Coastguard Worker                                                        [&] { return m_PacketSent; });
292*89c4ff92SAndroid Build Coastguard Worker     m_PacketSent = false;
293*89c4ff92SAndroid Build Coastguard Worker 
294*89c4ff92SAndroid Build Coastguard Worker     return timedOut;
295*89c4ff92SAndroid Build Coastguard Worker #else
296*89c4ff92SAndroid Build Coastguard Worker     IgnoreUnused(timeout);
297*89c4ff92SAndroid Build Coastguard Worker     return false;
298*89c4ff92SAndroid Build Coastguard Worker #endif
299*89c4ff92SAndroid Build Coastguard Worker }
300*89c4ff92SAndroid Build Coastguard Worker 
301*89c4ff92SAndroid Build Coastguard Worker } // namespace pipe
302*89c4ff92SAndroid Build Coastguard Worker 
303*89c4ff92SAndroid Build Coastguard Worker } // namespace arm
304