1
0
mirror of https://github.com/Zygo/bees.git synced 2025-05-17 21:35:45 +02:00

task: get rid of the separate Barrier and BarrierLock

Make one class Barrier which is copiable, so we don't have to
have users making shared Barrier all the time.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
This commit is contained in:
Zygo Blaxell 2022-11-15 16:24:25 -05:00
parent d345ea2b78
commit 7fdb87143c
3 changed files with 46 additions and 68 deletions

View File

@ -99,36 +99,26 @@ namespace crucible {
static void cancel(); static void cancel();
}; };
// Barrier executes waiting Tasks once the last BarrierLock
// is released. Multiple unique Tasks may be scheduled while
// BarrierLocks exist and all will be run() at once upon
// release. If no BarrierLocks exist, Tasks are executed
// immediately upon insertion.
class BarrierState; class BarrierState;
class BarrierLock { /// Barrier delays the execution of one or more Tasks.
shared_ptr<BarrierState> m_barrier_state; /// The Tasks are executed when the last shared reference to the
BarrierLock(shared_ptr<BarrierState> pbs); /// BarrierState is released. Copies of Barrier objects refer
friend class Barrier; /// to the same Barrier state.
public:
// Release this Lock immediately and permanently
void release();
};
class Barrier { class Barrier {
shared_ptr<BarrierState> m_barrier_state; shared_ptr<BarrierState> m_barrier_state;
Barrier(shared_ptr<BarrierState> pbs);
public: public:
Barrier(); Barrier();
// Prevent execution of tasks behind barrier until /// Schedule a task for execution when last Barrier is released.
// BarrierLock destructor or release() method is called.
BarrierLock lock();
// Schedule a task for execution when no Locks exist
void insert_task(Task t); void insert_task(Task t);
/// Release this reference to the barrier state.
/// Last released reference executes the task.
/// Barrier can only be released once, after which the
/// object can no longer be used.
void release();
}; };
// Exclusion provides exclusive access to a ExclusionLock. // Exclusion provides exclusive access to a ExclusionLock.

View File

@ -788,16 +788,6 @@ namespace crucible {
void insert_task(Task t); void insert_task(Task t);
}; };
Barrier::Barrier(shared_ptr<BarrierState> pbs) :
m_barrier_state(pbs)
{
}
Barrier::Barrier() :
m_barrier_state(make_shared<BarrierState>())
{
}
void void
BarrierState::release() BarrierState::release()
{ {
@ -813,17 +803,6 @@ namespace crucible {
release(); release();
} }
BarrierLock::BarrierLock(shared_ptr<BarrierState> pbs) :
m_barrier_state(pbs)
{
}
void
BarrierLock::release()
{
m_barrier_state.reset();
}
void void
BarrierState::insert_task(Task t) BarrierState::insert_task(Task t)
{ {
@ -831,16 +810,21 @@ namespace crucible {
m_tasks.insert(t); m_tasks.insert(t);
} }
Barrier::Barrier() :
m_barrier_state(make_shared<BarrierState>())
{
}
void void
Barrier::insert_task(Task t) Barrier::insert_task(Task t)
{ {
m_barrier_state->insert_task(t); m_barrier_state->insert_task(t);
} }
BarrierLock void
Barrier::lock() Barrier::release()
{ {
return BarrierLock(m_barrier_state); m_barrier_state.reset();
} }
class ExclusionState { class ExclusionState {

View File

@ -90,47 +90,51 @@ test_barrier(size_t count)
mutex mtx; mutex mtx;
condition_variable cv; condition_variable cv;
bool done_flag = false;
unique_lock<mutex> lock(mtx); unique_lock<mutex> lock(mtx);
auto b = make_shared<Barrier>(); Barrier b;
// Run several tasks in parallel // Run several tasks in parallel
for (size_t c = 0; c < count; ++c) { for (size_t c = 0; c < count; ++c) {
auto bl = b->lock();
ostringstream oss; ostringstream oss;
oss << "task #" << c; oss << "task #" << c;
auto b_hold = b;
Task t( Task t(
oss.str(), oss.str(),
[c, &task_done, &mtx, bl]() mutable { [c, &task_done, &mtx, b_hold]() mutable {
// cerr << "Task #" << c << endl; // ostringstream oss;
// oss << "Task #" << c << endl;
unique_lock<mutex> lock(mtx); unique_lock<mutex> lock(mtx);
// cerr << oss.str();
task_done.at(c) = true; task_done.at(c) = true;
bl.release(); b_hold.release();
} }
); );
t.run(); t.run();
} }
// Need completed to go out of local scope so it will release b
{
Task completed(
"Waiting for Barrier",
[&mtx, &cv, &done_flag]() {
unique_lock<mutex> lock(mtx);
// cerr << "Running cv notify" << endl;
done_flag = true;
cv.notify_all();
}
);
b.insert_task(completed);
}
// Get current status // Get current status
ostringstream oss; // TaskMaster::print_queue(cerr);
TaskMaster::print_queue(oss); // TaskMaster::print_workers(cerr);
TaskMaster::print_workers(oss);
bool done_flag = false; // Release our b
b.release();
Task completed(
"Waiting for Barrier",
[&mtx, &cv, &done_flag]() {
unique_lock<mutex> lock(mtx);
// cerr << "Running cv notify" << endl;
done_flag = true;
cv.notify_all();
}
);
b->insert_task(completed);
b.reset();
while (true) { while (true) {
size_t tasks_done = 0; size_t tasks_done = 0;
@ -139,7 +143,7 @@ test_barrier(size_t count)
++tasks_done; ++tasks_done;
} }
} }
// cerr << "Tasks done: " << tasks_done << " done_flag " << done_flag << endl; cerr << "Tasks done: " << tasks_done << " done_flag " << done_flag << endl;
if (tasks_done == count && done_flag) { if (tasks_done == count && done_flag) {
break; break;
} }