@@ -37,8 +37,8 @@ class queue_impl {
3737 async_handler AsyncHandler, QueueOrder Order,
3838 const property_list &PropList)
3939 : m_Device(SyclDevice), m_Context(Context), m_AsyncHandler(AsyncHandler),
40- m_PropList (PropList), m_HostQueue(m_Device.is_host()) {
41- m_OpenCLInterop = !m_HostQueue;
40+ m_PropList (PropList), m_HostQueue(m_Device.is_host()),
41+ m_OpenCLInterop( !m_HostQueue) {
4242 if (!m_HostQueue) {
4343 m_CommandQueue = createQueue (Order);
4444 }
@@ -47,7 +47,7 @@ class queue_impl {
4747 queue_impl (cl_command_queue CLQueue, const context &SyclContext,
4848 const async_handler &AsyncHandler)
4949 : m_Context(SyclContext), m_AsyncHandler(AsyncHandler),
50- m_OpenCLInterop( true ), m_HostQueue( false ) {
50+ m_HostQueue( false ), m_OpenCLInterop( true ) {
5151
5252 m_CommandQueue = pi::cast<RT::PiQueue>(CLQueue);
5353
@@ -94,7 +94,10 @@ class queue_impl {
9494 try {
9595 Event = submit_impl (cgf, self);
9696 } catch (...) {
97- m_Exceptions.PushBack (std::current_exception ());
97+ {
98+ std::lock_guard<mutex_class> guard (m_Mutex);
99+ m_Exceptions.PushBack (std::current_exception ());
100+ }
98101 Event = second_queue->submit (cgf, second_queue);
99102 }
100103 return Event;
@@ -105,13 +108,14 @@ class queue_impl {
105108 try {
106109 Event = submit_impl (cgf, self);
107110 } catch (...) {
111+ std::lock_guard<mutex_class> guard (m_Mutex);
108112 m_Exceptions.PushBack (std::current_exception ());
109113 }
110114 return Event;
111115 }
112116
113117 void wait () {
114- // TODO: Make thread safe.
118+ std::lock_guard<mutex_class> guard (m_Mutex);
115119 for (auto &evnt : m_Events)
116120 evnt.wait ();
117121 m_Events.clear ();
@@ -125,9 +129,18 @@ class queue_impl {
125129 }
126130
127131 void throw_asynchronous () {
132+ std::unique_lock<mutex_class> lock (m_Mutex);
133+
128134 if (m_AsyncHandler && m_Exceptions.size ()) {
129135 exception_list Exceptions;
136+
130137 std::swap (m_Exceptions, Exceptions);
138+
139+ // Unlock the mutex before calling user-provided handler to avoid
140+ // potential deadlock if the same queue is somehow referenced in the
141+ // handler.
142+ lock.unlock ();
143+
131144 m_AsyncHandler (std::move (Exceptions));
132145 }
133146 }
@@ -162,6 +175,8 @@ class queue_impl {
162175
163176 // Warning. Returned reference will be invalid if queue_impl was destroyed.
164177 RT::PiQueue &getExclusiveQueueHandleRef () {
178+ std::lock_guard<mutex_class> guard (m_Mutex);
179+
165180 // To achive parallelism for FPGA with in order execution model with
166181 // possibility of two kernels to share data with each other we shall
167182 // create a queue for every kernel enqueued.
@@ -184,9 +199,15 @@ class queue_impl {
184199 return m_CommandQueue;
185200 }
186201
187- if (m_Queues.empty ()) {
188- m_Queues.push_back (m_CommandQueue);
189- return m_CommandQueue;
202+ {
203+ // Reduce the scope since this mutex is also
204+ // locked inside of getExclusiveQueueHandleRef()
205+ std::lock_guard<mutex_class> guard (m_Mutex);
206+
207+ if (m_Queues.empty ()) {
208+ m_Queues.push_back (m_CommandQueue);
209+ return m_CommandQueue;
210+ }
190211 }
191212
192213 return getExclusiveQueueHandleRef ();
@@ -210,17 +231,22 @@ class queue_impl {
210231 handler Handler (std::move (self), m_HostQueue);
211232 cgf (Handler);
212233 event Event = Handler.finalize ();
213- // TODO: Make thread safe.
214- m_Events.push_back (Event);
234+ {
235+ std::lock_guard<mutex_class> guard (m_Mutex);
236+ m_Events.push_back (Event);
237+ }
215238 return Event;
216239 }
217240
241+ // Protects all the fields that can be changed by class' methods
242+ mutex_class m_Mutex;
243+
218244 device m_Device;
219- context m_Context;
245+ const context m_Context;
220246 vector_class<event> m_Events;
221247 exception_list m_Exceptions;
222- async_handler m_AsyncHandler;
223- property_list m_PropList;
248+ const async_handler m_AsyncHandler;
249+ const property_list m_PropList;
224250
225251 RT::PiQueue m_CommandQueue = nullptr ;
226252
@@ -229,8 +255,8 @@ class queue_impl {
229255 // Iterator through m_Queues.
230256 size_t m_QueueNumber = 0 ;
231257
232- bool m_OpenCLInterop = false ;
233- bool m_HostQueue = false ;
258+ const bool m_HostQueue = false ;
259+ const bool m_OpenCLInterop = false ;
234260 // Assume OOO support by default.
235261 bool m_SupportOOO = true ;
236262};
0 commit comments