Build a Minimal C Thread Pool on Linux – Full Code Walkthrough

This article presents a compact C thread‑pool implementation for Linux using POSIX pthreads, explains the core data structures and functions, shows how to create, enqueue tasks, and destroy the pool, and includes a runnable demo with annotated source code.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Build a Minimal C Thread Pool on Linux – Full Code Walkthrough

Overview

Provides a minimal POSIX thread‑pool implementation in C (~100 lines). The pool supports dynamic task‑queue growth, graceful shutdown, and demonstrates concurrent execution.

Key Data Structures

typedef struct Task {
    void (*function)(void *arg);
    void *arg;
} Task;

typedef struct ThreadPool {
    pthread_t *threads;          /* worker threads */
    Task *taskQueue;              /* circular queue */
    int taskQueueSize;            /* number of slots currently used */
    int taskQueueCapacity;        /* allocated capacity */
    int head;                     /* index of next task to fetch */
    int tail;                     /* index for next insertion */
    int count;                    /* number of pending tasks */
    pthread_mutex_t lock;         /* protects queue */
    pthread_cond_t cond;          /* signals new tasks */
    int stop;                     /* shutdown flag */
} ThreadPool;

Worker Thread Function

void *worker(void *arg) {
    ThreadPool *pool = (ThreadPool *)arg;
    while (1) {
        Task task;
        pthread_mutex_lock(&pool->lock);
        while (pool->count == 0 && !pool->stop) {
            pthread_cond_wait(&pool->cond, &pool->lock);
        }
        if (pool->stop) {
            pthread_mutex_unlock(&pool->lock);
            break;
        }
        task = pool->taskQueue[pool->head];
        pool->head = (pool->head + 1) % pool->taskQueueCapacity;
        pool->count--;
        pthread_mutex_unlock(&pool->lock);
        task.function(task.arg);
    }
    return NULL;
}

Creating a Thread Pool

ThreadPool *threadPoolCreate(int numThreads) {
    ThreadPool *pool = malloc(sizeof(ThreadPool));
    pool->taskQueueCapacity = 16;
    pool->taskQueue = malloc(sizeof(Task) * pool->taskQueueCapacity);
    pool->taskQueueSize = 0;
    pool->head = pool->tail = pool->count = 0;
    pool->stop = 0;
    pool->threads = malloc(sizeof(pthread_t) * numThreads);
    pthread_mutex_init(&pool->lock, NULL);
    pthread_cond_init(&pool->cond, NULL);
    for (int i = 0; i < numThreads; ++i) {
        pthread_create(&pool->threads[i], NULL, worker, pool);
    }
    return pool;
}

Enqueueing a Task

void threadPoolEnqueue(ThreadPool *pool,
                       void (*function)(void *), void *arg) {
    pthread_mutex_lock(&pool->lock);
    if (pool->count == pool->taskQueueCapacity) {
        pool->taskQueueCapacity *= 2;
        pool->taskQueue = realloc(pool->taskQueue,
                                  sizeof(Task) * pool->taskQueueCapacity);
    }
    pool->taskQueue[pool->tail].function = function;
    pool->taskQueue[pool->tail].arg = arg;
    pool->tail = (pool->tail + 1) % pool->taskQueueCapacity;
    pool->count++;
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->lock);
}

Destroying the Pool

void threadPoolDestroy(ThreadPool *pool) {
    pthread_mutex_lock(&pool->lock);
    pool->stop = 1;
    pthread_cond_broadcast(&pool->cond);
    pthread_mutex_unlock(&pool->lock);
    for (int i = 0; i < pool->taskQueueSize; ++i) {
        pthread_join(pool->threads[i], NULL);
    }
    free(pool->taskQueue);
    free(pool->threads);
    free(pool);
}

Example Usage

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

void exampleTask(void *arg) {
    int id = *(int *)arg;
    printf("Running task %d
", id);
    sleep(1);
}

int main(void) {
    ThreadPool *pool = threadPoolCreate(4);
    for (int i = 0; i < 10; ++i) {
        int *id = malloc(sizeof(int));
        *id = i;
        threadPoolEnqueue(pool, exampleTask, id);
    }
    sleep(5);               /* allow workers to finish */
    threadPoolDestroy(pool);
    return 0;
}

Execution Result

The program prints “Running task X” for each enqueued task, demonstrating that multiple threads process tasks concurrently and that the pool cleans up correctly.

Execution result
Execution result
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Linuxthread poolpthreads
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.