Last active
March 15, 2020 14:20
-
-
Save pedrominicz/382039ec888e7b4ba399f55b0475ef75 to your computer and use it in GitHub Desktop.
Strict alternation in C.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
#include <unistd.h> | |
#include <stdarg.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
// This program illustrates the use of strict alternation to synchronize | |
// threads. Two new threads are created and alternate writing to the standard | |
// output. | |
// This function is taken from `http://git.suckless.org/dwm/file/util.c.html`. | |
// | |
// Print the error message and `perror` if the message ends in `':'`. Assumes | |
// `fmt` is not `NULL`. | |
void die(const char* fmt, ...) { | |
va_list ap; | |
va_start(ap, fmt); | |
vfprintf(stderr, fmt, ap); | |
va_end(ap); | |
// Following Unix convention (see `man perror`), first check if the string is | |
// not empty. | |
if(fmt[0] && fmt[strlen(fmt) - 1] == ':') { | |
fputc(' ', stderr); | |
perror(NULL); | |
} else { | |
fputc('\n', stderr); | |
} | |
exit(0); | |
} | |
// This variable is accessible from both threads. Each thread only execute | |
// their critical section when its their turn and signal to eachother that | |
// their turn is over by modifying the flag. | |
int turn = 0; | |
void* f0(void* arg) { | |
while(1) { | |
// Wait until its this thread's turn. | |
while(turn != 0); | |
puts("hello"); | |
// Signal to the other thread that its their turn. | |
turn = 1; | |
sleep(1); | |
} | |
} | |
void* f1(void* arg) { | |
while(1) { | |
while(turn != 1); | |
puts("world"); | |
turn = 0; | |
sleep(1); | |
} | |
} | |
int main(void) { | |
// A POSIX thread has two main components: an object of type `pthread_t` | |
// which represents the thread and a function pointer of type | |
// `void* (*)(void*)` which will be the entry point of the thread. | |
pthread_t t0, t1; | |
// Creates new threads. The second argument is a pointer to a | |
// `pthread_attr_t`, if `NULL` the thread is created with default attributes. | |
// The last argument is the argument that is given to the thread's entry | |
// point function, unused in this example. | |
if(pthread_create(&t0, NULL, f0, NULL)) die("unable to create thread"); | |
if(pthread_create(&t1, NULL, f1, NULL)) die("unable to create thread"); | |
// Yes, I could have just created one extra thread. | |
while(1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment