Goroutines in C

Our first example demonstrates the use of threads in C. Here’s the full source code:

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

void *f(void *arg) {
    const char *from = (const char *)arg;
    for (int i = 0; i < 3; i++) {
        printf("%s : %d\n", from, i);
    }
    return NULL;
}

void *anonymous_func(void *arg) {
    printf("%s\n", (const char *)arg);
    return NULL;
}

int main() {
    // Call the function directly
    f("direct");

    // Create a thread to run the function
    pthread_t thread1;
    pthread_create(&thread1, NULL, f, "thread");

    // Create a thread for an anonymous function
    pthread_t thread2;
    pthread_create(&thread2, NULL, anonymous_func, "going");

    // Wait for the threads to finish
    sleep(1);
    printf("done\n");

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    return 0;
}

In this C program, we’re using POSIX threads (pthreads) to create concurrent execution, which is similar to goroutines in concept.

Let’s break down the key parts:

  1. We define a function f that takes a string argument and prints it along with a counter.

  2. In the main function, we first call f directly with the argument “direct”.

  3. To run f concurrently, we create a new thread using pthread_create. This is similar to using the go keyword in the original example.

  4. We also create another thread for an anonymous function. In C, we can’t define anonymous functions inline like in some other languages, so we define a separate function anonymous_func and pass it to pthread_create.

  5. We use sleep(1) to wait for the threads to finish. In a more robust implementation, you’d use proper synchronization mechanisms.

  6. Finally, we use pthread_join to wait for the threads to complete before the program exits.

When we compile and run this program, we might see output like this:

$ gcc -o threads threads.c -lpthread
$ ./threads
direct : 0
direct : 1
direct : 2
thread : 0
going
thread : 1
thread : 2
done

The output may vary between runs due to the concurrent nature of the threads. The main thread’s output (“direct” and “done”) will always appear, but the order of the other outputs may change.

This example demonstrates basic thread creation and execution in C, which is conceptually similar to goroutines in concurrent programming.