Implementing barrier in Pthreads
According from my previous post, the most useful thing in parallel programming is barrier. Usually, barriers are available in Pthreads at least below 3 functions.
int pthread_barrier_destroy(pthread_barrier_t *barrier);
int pthread_barrier_init(pthread_barrier_t *barrier,
const pthread_barrierattr_t *attr, unsigned count);
int pthread_barrier_wait(pthread_barrier_t *barrier);
Unfortunately, above functions may be not available on some architecture, e.g., Cygwin. That's why I need to implement one.
The first part is to define some macros for compatibility with Pthreads.
#if defined(WITH_BARRIER) || defined(CYGWIN)
#define pthread_barrier_t barrier_t
#define pthread_barrier_attr_t barrier_attr_t
#define pthread_barrier_init(b,a,n) barrier_init(b,n)
#define pthread_barrier_destroy(b) barrier_destroy(b)
#define pthread_barrier_wait(b) barrier_wait(b)
#endif
Then follows by declarations of a structure named barrier_t
. We need to have at least a mutex
, a cond
and 2 integers to store the needed number and the number of called.
typedef struct {
int needed;
int called;
pthread_mutex_t mutex;
pthread_cond_t cond;
} barrier_t;
I follows the style of Pthreads (init
, destroy
and wait
) to make it very easy to adopt.
int barrier_init(barrier_t *barrier,int needed);
int barrier_destroy(barrier_t *barrier);
int barrier_wait(barrier_t *barrier);
In barrier_init()
, we don't have any special attributes so there are only 2 arguments here. All members of barrier_t
are initialized to make it usable.
int barrier_init(barrier_t *barrier,int needed)
{
barrier->needed = needed;
barrier->called = 0;
pthread_mutex_init(&barrier->mutex,NULL);
pthread_cond_init(&barrier->cond,NULL);
return 0;
}
Don't forget to run barrier_destroy()
to propagate to mutex
and cond
.
int barrier_destroy(barrier_t *barrier)
{
pthread_mutex_destroy(&barrier->mutex);
pthread_cond_destroy(&barrier->cond);
return 0;
}
Now we reach barrier_wait()
. The code is very simple. Whenever current thread obtains the lock, called
will be increased. If called
is not equal to needed
, this thread will wait. Otherwise, called
is equal to needed
. That means we have all threads reaching the barrier so just simply send broadcast to notify other waiting threads. That's all.
int barrier_wait(barrier_t *barrier)
{
pthread_mutex_lock(&barrier->mutex);
barrier->called++;
if (barrier->called == barrier->needed) {
barrier->called = 0;
pthread_cond_broadcast(&barrier->cond);
} else {
pthread_cond_wait(&barrier->cond,&barrier->mutex);
}
pthread_mutex_unlock(&barrier->mutex);
return 0;
}
Tags: pthreads, cygwin, barrier, parallel programming
- sugree's blog
- 16883 reads
Post new comment