C++ Barriers(Multithreading) Introduction














































C++ Barriers(Multithreading) Introduction



Introduction

  • As one of the synchronization methods, a barrier tells a group of threads or processes must stop at the barrier and cannot proceed until all other threads/processes reach this barrier.
  • Unlike std::latch, barriers are reusable: once the arriving threads are unblocked from a barrier phase's synchronization point, the same barrier can be reused.

Member functions

 constructor                       constructs a barrier
 destructor                         destroys the barrier
 operator=[deleted]            barrier is not assignable
 arrive                                arrives at barrier and decrements the expected count
 wait                                   blocks at the phase synchronization point until its phase completion step is run
 arrive_and_wait                arrives at barrier and decrements the expected count by one, then blocks until current                                                     phase completes
 arrive_and_drop               decrements both the initial expected count for subsequent phases and the expected count                                               for current phase by one.

Constants

max[static]                          the maximum value of expected count supported by the implementation

We can create a barrier by calling pthread_barrier_init(). It initializes the barrier and it takes three parameters:

  1. A pointer to the barrier to be initialized.
  2. To determine whether the barrier is private or can be shared, it takes an optional attributes structure.
  3. We need feed the number of threads that need to reach the barrier before any threads are released.
Each thread calls pthread_barrier_wait() when it reaches the barrier, and the call will return when the number of threads has reached the barrier.

A Sample Code

#include <pthread.h>
#include <stdio.h>

pthread_barrier_t b;

void print(void* p)
{
    int id = (int)p;
    printf("before  barrier %d\n", id);
    pthread_barrier_wait(&b;);
    printf("after  barrier %d\n", id);
}

int main()
{
    int num_of_Thread = 4;
    int i;
    pthread_t thread[num_of_Thread];
    pthread_barrier_init(&b;, 0, num_of_Thread);

    for(i = 0; i < num_of_Thread; i++)
        pthread_create(&thread;[i], 0, print, (void*)i);

    for(i = 0; i < num_of_Thread; i++)
        pthread_join(thread[i], 0);

    pthread_barrier_destroy(&b;);
    return 0;
}

The code above shows how the before aquiring the lock just check for queue count barrier force the threads to wait until all the threads have been created.

OUTPUT

before  barrier 3
before  barrier 2
before  barrier 1
before  barrier 0
after  barrier 0
after  barrier 3

after  barrier 2
after  barrier 1

If we did not set the barrier, the output would have been::


before  barrier 3
after  barrier 3
before  barrier 2
after  barrier 2
before  barrier 1
after  barrier 1
before  barrier 0
after  barrier 0


Comments