simplify barrier to use only a mutex and condition variable

This commit is contained in:
Chris Copeland 2023-07-25 02:05:03 -07:00
parent 9ec841143d
commit 14b16f01b6
Signed by: chrisnc
GPG Key ID: 14550DA72485DF30
3 changed files with 18 additions and 23 deletions

View File

@ -8,7 +8,7 @@ namespace rt
class barrier
{
public:
constexpr barrier(int count) : b(RT_BARRIER_INIT(b, count))
constexpr barrier(unsigned int count) : b(RT_BARRIER_INIT(b, count))
{
}

View File

@ -3,7 +3,6 @@
#include <rt/cond.h>
#include <rt/mutex.h>
#include <rt/sem.h>
#include <stdbool.h>
@ -13,7 +12,7 @@ extern "C" {
struct rt_barrier;
void rt_barrier_init(struct rt_barrier *barrier, int count);
void rt_barrier_init(struct rt_barrier *barrier, unsigned int count);
/*
* Blocks until count threads have called it, at which point it returns
@ -24,17 +23,15 @@ bool rt_barrier_wait(struct rt_barrier *barrier);
struct rt_barrier
{
struct rt_sem sem;
struct rt_mutex mutex;
struct rt_cond cond;
int level, threshold;
unsigned int level, threshold, generation;
};
#define RT_BARRIER_INIT(name, count) \
{ \
.sem = RT_SEM_INIT(name.sem, count), \
.mutex = RT_MUTEX_INIT(name.mutex), .cond = RT_COND_INIT(name.cond), \
.level = 0, .threshold = (count), \
.level = 0, .threshold = (count), .generation = 0, \
}
#define RT_BARRIER(name, count) \

View File

@ -1,35 +1,33 @@
#include <rt/barrier.h>
void rt_barrier_init(struct rt_barrier *barrier, int count)
void rt_barrier_init(struct rt_barrier *barrier, unsigned int count)
{
barrier->level = 0;
barrier->threshold = count;
rt_sem_init(&barrier->sem, count);
rt_mutex_init(&barrier->mutex);
rt_cond_init(&barrier->cond);
barrier->level = 0;
barrier->threshold = count;
barrier->generation = 0;
}
bool rt_barrier_wait(struct rt_barrier *barrier)
{
rt_sem_wait(&barrier->sem);
rt_mutex_lock(&barrier->mutex);
const unsigned int generation = barrier->generation;
++barrier->level;
if (barrier->level == barrier->threshold)
const bool is_leader = barrier->level == barrier->threshold;
if (is_leader)
{
barrier->level = 0;
++barrier->generation;
rt_cond_broadcast(&barrier->cond);
}
else
{
rt_cond_wait(&barrier->cond, &barrier->mutex);
}
--barrier->level;
const bool complete = barrier->level == 0;
if (complete)
{
rt_sem_post_n(&barrier->sem, barrier->threshold);
while (generation == barrier->generation)
{
rt_cond_wait(&barrier->cond, &barrier->mutex);
}
}
rt_mutex_unlock(&barrier->mutex);
return complete;
return is_leader;
}