/* Collection of code snippets by Arne Vajhøj */
/* (from articles on eksperten.dk / vajhoej.dk written sometime between 2004 and now) */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <unistd.h>
#include <pthread.h>

#define MAX_STR_LEN 8192

struct data {
    char s[MAX_STR_LEN];
};

static pthread_mutex_t mtx;

void *run(void *p)
{
    struct data *d;
    char s[MAX_STR_LEN];
    d = p;
    pthread_mutex_lock(&mtx);
    strcpy(s, d->s);
    usleep(1);
    strcpy(d->s, s);
    strcat(d->s, "X");
    pthread_mutex_unlock(&mtx);
    return NULL;
}

void test(int njobs, int nthreads)
{
    struct data d;
    pthread_t *t;
    int i, j;
    void *p;
    pthread_mutex_init(&mtx, NULL);
    /* setup data */
    strcpy(d.s, "");
    /* process with shared data */
    for(i = 0; i < njobs / nthreads; i++)
    {
        /* create and start threads */
        t = malloc(nthreads * sizeof(pthread_t));
        for(j = 0; j < nthreads; j++)
        {
            pthread_create(&t[j], NULL, run, &d);
        }
        /* wait for threads to complete */
        for(j = 0; j < nthreads; j++)
        {
            pthread_join(t[j], &p);
        }
        free(t);
    }
    printf("%d threads : expected = %d, actual = %d\n", nthreads, njobs, (int)strlen(d.s));
    pthread_mutex_destroy(&mtx);
}

int main()
{
    test(2560, 1);
    test(2560, 2);
    test(2560, 4);
    test(2560, 8);
    test(2560, 16);
    test(2560, 32);
    test(2560, 64);
    return 0;
}
