GNU Astronomy Utilities



12.3.2.1 Implementation of pthread_barrier

One optional feature of the POSIX Threads standard is the pthread_barrier concept. It is a very useful high-level construct that allows for independent threads to “wait” behind a “barrier” for the rest after they finish. Barriers can thus greatly simplify the code in a multi-threaded program, so they are heavily used in Gnuastro. However, since it is an optional feature in the POSIX standard, some operating systems do not include it. So to make Gnuastro portable, we have written our own implementation of those pthread_barrier functions.

At ./configure time, Gnuastro will check if pthread_barrier constructs are available on your system or not. If pthread_barrier is not available, our internal implementation will be compiled into the Gnuastro library and the definitions and declarations below will be usable in your code with #include <gnuastro/threads.h>.

Type: pthread_barrierattr_t

Type to specify the attributes of a POSIX threads barrier.

Type: pthread_barrier_t

Structure defining the POSIX threads barrier.

Function:
int
pthread_barrier_init (pthread_barrier_t *b, pthread_barrierattr_t *attr, unsigned int limit)

Initialize the barrier b, with the attributes attr and total limit (a number of) threads that must wait behind it. This function must be called before spinning off threads.

Function:
int
pthread_barrier_wait (pthread_barrier_t *b)

This function is called within each thread, just before it is ready to return. Once a thread’s function hits this, it will “wait” until all the other functions are also finished.

Function:
int
pthread_barrier_destroy (pthread_barrier_t *b)

Destroy all the information in the barrier structure. This should be called by the function that spun-off the threads after all the threads have finished.

Destroy a barrier before re-using it: It is very important to destroy the barrier before (possibly) reusing it. This destroy function not only destroys the internal structures, it also waits (in 1 microsecond intervals, so you will not notice!) until all the threads do not need the barrier structure any more. If you immediately start spinning off new threads with a not-destroyed barrier, then the internal structure of the remaining threads will get mixed with the new ones and you will get very strange and apparently random errors that are extremely hard to debug.