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

#ifdef _WIN32
#   include <windows.h>
#else
#   include <unistd.h>
#endif

static
void SleepMs(unsigned ms)
{
#ifdef _WIN32
    Sleep(ms);
#else
    usleep( 1000 * ms );
#endif
}

struct WorkData
{
    char label[64];
    pthread_barrier_t *barrier;
    pthread_t thrd;
};

static
void* ThrdFunc(struct WorkData *data)
{
    static const unsigned spendtimes[] =
    {
        200,
        400,
        800,
        1200,
        1600,
        2000,
    };

    static const unsigned spendtimes_num =
        sizeof(spendtimes) / sizeof(spendtimes[0]);

    for(int i = 0; i < 4; ++i)
    {
        pthread_barrier_wait(data->barrier);

        printf("%s: Start working\n", data->label);
        SleepMs(spendtimes[ rand() % spendtimes_num ]);
        printf("%s: Done working\n", data->label);
    }

    return NULL;
}

int main(int argc, char *argv[])
{
    // 為了讓每一次測試的效果一致，這裡故意使用定值來初始化亂數種子。
    srand(0);

    static const int thrd_num = 4;
    struct WorkData thrd_data[thrd_num];

    pthread_barrier_t barrier;
    pthread_barrier_init(&barrier, NULL, thrd_num);

    for(int i = 0; i < thrd_num; ++i)
    {
        struct WorkData *data = &thrd_data[i];

        snprintf(data->label, sizeof(data->label), "Thread-%d", i);
        data->barrier = &barrier;
        pthread_create(&data->thrd, NULL, (void*(*)(void*)) ThrdFunc, data);
    }

    for(int i = 0; i < thrd_num; ++i)
        pthread_join(thrd_data[i].thrd, NULL);

    pthread_barrier_destroy(&barrier);

    return 0;
}
