#include <stdio.h> /* printf(), puts() */
#include <stdlib.h> /* exit() */
#include <unistd.h> /* sleep() */
#include <pthread.h> /* threads, doi */
__attribute__((noreturn))
static void usage (char *myself) {
printf("Usage: %s [threads]\n", myself);
puts("threads must be between 1 and 32.");
exit(-1);
}
pthread_mutex_t bufferlock;
char *buffer;
static void write_buffer () {
pthread_mutex_lock(&bufferlock);
/* write buffer to shared filehandle */
pthread_mutex_unlock(&bufferlock);
}
#define tprintf(x, ...) { \
printf("[%d] " x, *(unsigned *)thread_id, __VA_ARGS__); \
fflush(stdout); \
}
#define tputs(x) { \
printf("[%d] " x "\n", *(unsigned *)thread_id); \
fflush(stdout); \
}
static void *run_thread (void *thread_id) {
tprintf("sleeping %u seconds\n", *(unsigned *)thread_id);
sleep(*(unsigned *)thread_id);
tputs("calling write_buffer()");
write_buffer();
tputs("exiting.");
free(thread_id);
return NULL;
}
static inline unsigned *copy (unsigned x) {
unsigned *copy = malloc(sizeof(unsigned));
*copy = x;
return copy;
}
static inline void create_threads (pthread_t *thread_table, unsigned threads) {
for (unsigned i = 1; i < threads; i++)
pthread_create(thread_table + i, NULL, &run_thread, copy(i));
run_thread(copy(0));
}
static inline void wait_for_threads (pthread_t *thread_table, unsigned threads) {
for (unsigned i = 1; i < threads; i++)
pthread_join(thread_table[i], NULL);
}
int main (int argc, char **argv) {
if (argc < 2) usage(argv[0]);
unsigned threads = atoi(argv[1]);
if (32 < threads || 0 >= threads) usage(argv[0]);
printf("running %d concurrent threads\n", threads);
fflush(stdout);
pthread_mutex_init(&bufferlock, NULL);
pthread_t *thread_table = malloc(threads * sizeof(pthread_t));
create_threads(thread_table, threads);
wait_for_threads(thread_table, threads);
pthread_mutex_destroy(&bufferlock);
return 0;
}