@@ -150,15 +150,23 @@ class parallel {
150
150
operator +=(_Fx&& fx) {
151
151
using RetType = typename std::remove_cv<decltype (fx ())>::type;
152
152
153
+ auto block = m_block;
154
+ if (!block)
155
+ return ;
156
+
153
157
// Increment remain jobs. This is decremented by calls to "Pop"
154
- (std::lock_guard<std::mutex>)m_block->m_lock , ++m_block->m_outstandingCount ;
158
+ (std::lock_guard<std::mutex>)block->m_lock , ++block->m_outstandingCount ;
159
+
160
+ block->dq += [this , fx] {
161
+ auto block = m_block;
162
+ if (!block)
163
+ return ;
155
164
156
- m_block->dq += [this , fx] {
157
165
auto result = std::make_shared<RetType>(fx ());
158
166
159
- std::lock_guard<std::mutex>{m_block ->m_lock },
160
- m_block ->m_queue [auto_id_t <RetType>{}].emplace_back (std::move (result));
161
- m_block ->m_queueUpdated .notify_all ();
167
+ std::lock_guard<std::mutex>{block ->m_lock },
168
+ block ->m_queue [auto_id_t <RetType>{}].emplace_back (std::move (result));
169
+ block ->m_queueUpdated .notify_all ();
162
170
};
163
171
}
164
172
@@ -168,48 +176,68 @@ class parallel {
168
176
std::is_same<void , typename std::result_of<_Fx()>::type>::value
169
177
>::type
170
178
operator +=(_Fx&& fx) {
179
+ auto block = m_block;
180
+ if (!block)
181
+ return ;
182
+
171
183
// Increment remain jobs. This is decremented by calls to "Pop"
172
- (std::lock_guard<std::mutex>)m_block->m_lock , ++m_block->m_outstandingCount ;
184
+ (std::lock_guard<std::mutex>)block->m_lock , ++block->m_outstandingCount ;
185
+
186
+ block->dq += [this , fx] {
187
+ auto block = m_block;
188
+ if (!block)
189
+ return ;
173
190
174
- m_block->dq += [this , fx] {
175
191
fx ();
176
192
177
- std::lock_guard<std::mutex>{m_block ->m_lock },
178
- m_block ->m_nVoidEntries ++;
179
- m_block ->m_queueUpdated .notify_all ();
193
+ std::lock_guard<std::mutex>{block ->m_lock },
194
+ block ->m_nVoidEntries ++;
195
+ block ->m_queueUpdated .notify_all ();
180
196
};
181
197
}
182
198
183
199
// Discard the most recent result. Blocks until the next result arives.
184
200
template <typename T>
185
201
void Pop (void ) {
186
- std::unique_lock<std::mutex> lk (m_block->m_lock );
187
- if (!m_block->m_outstandingCount )
202
+ auto block = m_block;
203
+ if (!block)
204
+ return ;
205
+
206
+ std::unique_lock<std::mutex> lk (block->m_lock );
207
+ if (!block->m_outstandingCount )
188
208
throw std::out_of_range (" No outstanding jobs" );
189
209
190
210
if (std::is_same<void , T>::value) {
191
- m_block ->m_queueUpdated .wait (lk, [this ] { return m_block->m_nVoidEntries != 0 ; });
192
- m_block ->m_nVoidEntries --;
211
+ block ->m_queueUpdated .wait (lk, [this ] { auto block = m_block; return block ? block ->m_nVoidEntries != 0 : true ; });
212
+ block ->m_nVoidEntries --;
193
213
} else {
194
- auto & qu = m_block ->m_queue [auto_id_t <T>{}];
195
- m_block ->m_queueUpdated .wait (lk, [&qu] { return !qu.empty (); });
214
+ auto & qu = block ->m_queue [auto_id_t <T>{}];
215
+ block ->m_queueUpdated .wait (lk, [&qu] { return !qu.empty (); });
196
216
qu.pop_front ();
197
217
}
198
218
199
- --m_block ->m_outstandingCount ;
219
+ --block ->m_outstandingCount ;
200
220
}
201
221
202
222
// Get the most result from the most recent job. Blocks until a result arrives
203
223
// if there isn't one already available
204
224
template <typename T>
205
225
T Top (void ) {
206
- std::unique_lock<std::mutex> lk (m_block->m_lock );
226
+ auto block = m_block;
227
+ if (!block)
228
+ return T{};
229
+
230
+ std::unique_lock<std::mutex> lk (block->m_lock );
207
231
208
- if (m_block->m_queue [auto_id_t <T>{}].empty ())
209
- m_block->m_queueUpdated .wait (lk, [this ]{
210
- return !m_block->m_queue [auto_id_t <T>{}].empty ();
232
+ if (block->m_queue [auto_id_t <T>{}].empty ())
233
+ block->m_queueUpdated .wait (lk, [this ]{
234
+ auto block = m_block;
235
+ if (!block)
236
+ return true ;
237
+
238
+ return !block->m_queue [auto_id_t <T>{}].empty ();
211
239
});
212
- return *static_cast <T*>(m_block ->m_queue [auto_id_t <T>{}].front ().ptr ());
240
+ return *static_cast <T*>(block ->m_queue [auto_id_t <T>{}].front ().ptr ());
213
241
}
214
242
215
243
// Get a collection containing all entries of the specified type
@@ -225,19 +253,30 @@ class parallel {
225
253
// / If a stop call has been made, this method will also block until all owned threads have quit
226
254
// / </remarks>
227
255
void barrier (void ) {
228
- std::unique_lock<std::mutex> lk (m_block->m_lock );
229
- m_block->m_queueUpdated .wait (lk, [this ] {
230
- size_t totalReady = m_block->m_nVoidEntries ;
231
- for (auto & entry : m_block->m_queue )
256
+ auto block = m_block;
257
+ if (!block)
258
+ return ;
259
+
260
+ std::unique_lock<std::mutex> lk (block->m_lock );
261
+ block->m_queueUpdated .wait (lk, [this ] {
262
+ auto block = m_block;
263
+ if (!block)
264
+ return true ;
265
+ size_t totalReady = block->m_nVoidEntries ;
266
+ for (auto & entry : block->m_queue )
232
267
totalReady += entry.second .size ();
233
- return m_block ->m_outstandingCount == totalReady;
268
+ return block ->m_outstandingCount == totalReady;
234
269
});
235
270
}
236
271
237
272
// Get an iterator to the begining of out queue of job results
238
273
template <typename T>
239
274
parallel_iterator<T> begin (void ) {
240
- return { *this , m_block->m_outstandingCount };
275
+ auto block = m_block;
276
+ if (!block)
277
+ return { *this , 0 };
278
+
279
+ return { *this , block->m_outstandingCount };
241
280
}
242
281
243
282
// Iterator representing no jobs results remaining
0 commit comments