|
39 | 39 |
|
40 | 40 | namespace Gecode { namespace Search { namespace Par { |
41 | 41 |
|
| 42 | + template<class Collect> |
| 43 | + forceinline |
| 44 | + Slave<Collect>::Completion::Completion(void) { |
| 45 | + // A slave has not been submitted yet. This initial signal lets the |
| 46 | + // first submission use the same consume-before-reuse handshake as all |
| 47 | + // subsequent submissions. |
| 48 | + done.signal(); |
| 49 | + } |
| 50 | + |
| 51 | + template<class Collect> |
| 52 | + forceinline void |
| 53 | + Slave<Collect>::Completion::terminated(void) { |
| 54 | + done.signal(); |
| 55 | + } |
| 56 | + |
| 57 | + template<class Collect> |
| 58 | + forceinline void |
| 59 | + Slave<Collect>::Completion::wait(void) { |
| 60 | + done.wait(); |
| 61 | + } |
| 62 | + |
42 | 63 |
|
43 | 64 | forceinline |
44 | 65 | CollectAll::CollectAll(void) |
@@ -142,6 +163,16 @@ namespace Gecode { namespace Search { namespace Par { |
142 | 163 | return slave->stopped(); |
143 | 164 | } |
144 | 165 | template<class Collect> |
| 166 | + forceinline Support::Terminator* |
| 167 | + Slave<Collect>::terminator(void) const { |
| 168 | + return const_cast<Completion*>(&completion); |
| 169 | + } |
| 170 | + template<class Collect> |
| 171 | + forceinline void |
| 172 | + Slave<Collect>::wait(void) { |
| 173 | + completion.wait(); |
| 174 | + } |
| 175 | + template<class Collect> |
145 | 176 | forceinline void |
146 | 177 | Slave<Collect>::constrain(const Space& b) { |
147 | 178 | slave->constrain(b); |
@@ -225,8 +256,12 @@ namespace Gecode { namespace Search { namespace Par { |
225 | 256 | if (n_active > 0) { |
226 | 257 | // Run all active slaves |
227 | 258 | n_busy = n_active; |
228 | | - for (unsigned int i=0U; i<n_active; i++) |
| 259 | + for (unsigned int i=0U; i<n_active; i++) { |
| 260 | + // Consume the previous completion before reusing this slave. The |
| 261 | + // initial signal handles the first submission. |
| 262 | + slaves[i]->wait(); |
229 | 263 | Support::Thread::run(slaves[i]); |
| 264 | + } |
230 | 265 | m.release(); |
231 | 266 | // Wait for all slaves to become idle |
232 | 267 | idle.wait(); |
@@ -286,6 +321,11 @@ namespace Gecode { namespace Search { namespace Par { |
286 | 321 |
|
287 | 322 | template<class Collect> |
288 | 323 | PBS<Collect>::~PBS(void) { |
| 324 | + // A report can make n_busy zero before Slave::run and Thread::Run::exec |
| 325 | + // have returned. Wait for the completion handshake before deleting the |
| 326 | + // PBS-owned slaves. |
| 327 | + for (unsigned int i=0U; i<n_slaves; i++) |
| 328 | + slaves[i]->wait(); |
289 | 329 | assert(n_busy == 0); |
290 | 330 | for (unsigned int i=0U; i<n_slaves; i++) |
291 | 331 | delete slaves[i]; |
|
0 commit comments