Monday, December 14, 2009

Barrier mechanism

While we make threads and make it work, sometime we want to make them stop at a certain point of work flow. Barrier can be used to make them wait till the other threads end their jobs. Here is an example. 5th thread will sleep 5 seconds and the other threads will wait with pthread_barrier_wait().

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

#define THREADNUM 5

pthread_barrier_t barrier;

struct thread_ctx {
    pthread_t tid;
    int idx;
} thr_ctx[THREADNUM];

void *start_thread(void *);
void clean_thread();
void exit_w_err(const char *);

int main()
{
    int i;

    pthread_barrier_init(&barrier, NULL, THREADNUM);

    for(i = 0; i < THREADNUM; i++) {
        thr_ctx[i].idx = i;
        if (pthread_create(&thr_ctx[i].tid, NULL,
            start_thread, (void *)&thr_ctx[i])) {
            exit_w_err("thread_create");
        }
    }
    clean_thread();
}

void *start_thread(void *in_ctx)
{
    int res;
    struct thread_ctx *ctx;

    ctx = (struct thread_ctx *)in_ctx;

    /*
     * thread will wait with barrier
     */
    if (ctx->idx == THREADNUM - 1) {
        sleep(5);
        printf("thread (%d) arrived\n", ctx->idx);
    }
    else 
        printf("thread (%d) started to wait\n", ctx->idx);

    if ((res = pthread_barrier_wait(&barrier)) == EINVAL)
    {
        printf("\t errno : %d\n", res);
        return NULL;
    }

    return in_ctx;
}

void clean_thread(void)
{
    int i;
    void *res; // dummy pointer.

    for (i = 0; i < THREADNUM; i++) {
        pthread_join(thr_ctx[i].tid, &res);
    }

    return;
}

void exit_w_err(const char *msg)
{
    fprintf(stderr, "[ERROR] %s\n", msg);
    exit(0);
}

No comments:

Post a Comment