Skip to content

Commit 5f66740

Browse files
author
Mikael Zayenz Lagerkvist
committed
search: preserve PBS runnable completion lifetime
1 parent 80ce269 commit 5f66740

3 files changed

Lines changed: 62 additions & 5 deletions

File tree

gecode/search/par/pbs.hh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ namespace Gecode { namespace Search { namespace Par {
7171
template<class Collect>
7272
class GECODE_SEARCH_EXPORT Slave : public Support::Runnable {
7373
protected:
74+
/// Completion event for the current run
75+
class Completion : public Support::Terminator {
76+
protected:
77+
/// The completion event
78+
Support::Event done;
79+
public:
80+
/// Initialize as completed
81+
Completion(void);
82+
/// Signal completion
83+
virtual void terminated(void);
84+
/// Wait for completion and consume the signal
85+
void wait(void);
86+
} completion;
7487
/// The master engine
7588
PBS<Collect>* master;
7689
/// The slave engine
@@ -84,6 +97,10 @@ namespace Gecode { namespace Search { namespace Par {
8497
Statistics statistics(void) const;
8598
/// Check whether slave has been stopped
8699
bool stopped(void) const;
100+
/// Return the completion terminator
101+
virtual Support::Terminator* terminator(void) const;
102+
/// Wait for the slave to complete its current run
103+
void wait(void);
87104
/// Constrain with better solution \a b
88105
void constrain(const Space& b);
89106
/// Perform one run

gecode/search/par/pbs.hpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,27 @@
3939

4040
namespace Gecode { namespace Search { namespace Par {
4141

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+
4263

4364
forceinline
4465
CollectAll::CollectAll(void)
@@ -142,6 +163,16 @@ namespace Gecode { namespace Search { namespace Par {
142163
return slave->stopped();
143164
}
144165
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>
145176
forceinline void
146177
Slave<Collect>::constrain(const Space& b) {
147178
slave->constrain(b);
@@ -225,8 +256,12 @@ namespace Gecode { namespace Search { namespace Par {
225256
if (n_active > 0) {
226257
// Run all active slaves
227258
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();
229263
Support::Thread::run(slaves[i]);
264+
}
230265
m.release();
231266
// Wait for all slaves to become idle
232267
idle.wait();
@@ -286,6 +321,11 @@ namespace Gecode { namespace Search { namespace Par {
286321

287322
template<class Collect>
288323
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();
289329
assert(n_busy == 0);
290330
for (unsigned int i=0U; i<n_slaves; i++)
291331
delete slaves[i];

gecode/support/thread/thread.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ namespace Gecode { namespace Support {
5858
GECODE_ASSUME(r != nullptr);
5959
Runnable* e = r.exchange(nullptr);
6060
assert(e != nullptr);
61-
const bool delete_after_run = e->todelete();
62-
Terminator* t = delete_after_run ? e->terminator() : nullptr;
6361
e->run();
62+
const bool delete_after_run = e->todelete();
63+
Terminator* t = e->terminator();
6464
if (delete_after_run) {
6565
delete e;
66-
if (t)
67-
t->terminated();
6866
}
67+
if (t)
68+
t->terminated();
6969
}
7070
// Put into idle stack
7171
Thread::m()->acquire();

0 commit comments

Comments
 (0)