@@ -37,8 +37,8 @@ class queue_impl {
37
37
async_handler AsyncHandler, QueueOrder Order,
38
38
const property_list &PropList)
39
39
: 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) {
42
42
if (!m_HostQueue) {
43
43
m_CommandQueue = createQueue (Order);
44
44
}
@@ -47,7 +47,7 @@ class queue_impl {
47
47
queue_impl (cl_command_queue CLQueue, const context &SyclContext,
48
48
const async_handler &AsyncHandler)
49
49
: m_Context(SyclContext), m_AsyncHandler(AsyncHandler),
50
- m_OpenCLInterop( true ), m_HostQueue( false ) {
50
+ m_HostQueue( false ), m_OpenCLInterop( true ) {
51
51
52
52
m_CommandQueue = pi::cast<RT::PiQueue>(CLQueue);
53
53
@@ -94,7 +94,10 @@ class queue_impl {
94
94
try {
95
95
Event = submit_impl (cgf, self);
96
96
} 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
+ }
98
101
Event = second_queue->submit (cgf, second_queue);
99
102
}
100
103
return Event;
@@ -105,13 +108,14 @@ class queue_impl {
105
108
try {
106
109
Event = submit_impl (cgf, self);
107
110
} catch (...) {
111
+ std::lock_guard<mutex_class> guard (m_Mutex);
108
112
m_Exceptions.PushBack (std::current_exception ());
109
113
}
110
114
return Event;
111
115
}
112
116
113
117
void wait () {
114
- // TODO: Make thread safe.
118
+ std::lock_guard<mutex_class> guard (m_Mutex);
115
119
for (auto &evnt : m_Events)
116
120
evnt.wait ();
117
121
m_Events.clear ();
@@ -125,9 +129,18 @@ class queue_impl {
125
129
}
126
130
127
131
void throw_asynchronous () {
132
+ std::unique_lock<mutex_class> lock (m_Mutex);
133
+
128
134
if (m_AsyncHandler && m_Exceptions.size ()) {
129
135
exception_list Exceptions;
136
+
130
137
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
+
131
144
m_AsyncHandler (std::move (Exceptions));
132
145
}
133
146
}
@@ -162,6 +175,8 @@ class queue_impl {
162
175
163
176
// Warning. Returned reference will be invalid if queue_impl was destroyed.
164
177
RT::PiQueue &getExclusiveQueueHandleRef () {
178
+ std::lock_guard<mutex_class> guard (m_Mutex);
179
+
165
180
// To achive parallelism for FPGA with in order execution model with
166
181
// possibility of two kernels to share data with each other we shall
167
182
// create a queue for every kernel enqueued.
@@ -184,9 +199,15 @@ class queue_impl {
184
199
return m_CommandQueue;
185
200
}
186
201
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
+ }
190
211
}
191
212
192
213
return getExclusiveQueueHandleRef ();
@@ -210,17 +231,22 @@ class queue_impl {
210
231
handler Handler (std::move (self), m_HostQueue);
211
232
cgf (Handler);
212
233
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
+ }
215
238
return Event;
216
239
}
217
240
241
+ // Protects all the fields that can be changed by class' methods
242
+ mutex_class m_Mutex;
243
+
218
244
device m_Device;
219
- context m_Context;
245
+ const context m_Context;
220
246
vector_class<event> m_Events;
221
247
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;
224
250
225
251
RT::PiQueue m_CommandQueue = nullptr ;
226
252
@@ -229,8 +255,8 @@ class queue_impl {
229
255
// Iterator through m_Queues.
230
256
size_t m_QueueNumber = 0 ;
231
257
232
- bool m_OpenCLInterop = false ;
233
- bool m_HostQueue = false ;
258
+ const bool m_HostQueue = false ;
259
+ const bool m_OpenCLInterop = false ;
234
260
// Assume OOO support by default.
235
261
bool m_SupportOOO = true ;
236
262
};
0 commit comments