<commit_before>#include <stdlib.h>     /* malloc(), free() */
#include <pthread.h>    /* pthread_*() */
#include "thpool.h"

/**
 * Describes a task - Also a singly linked list element
 */
typedef struct _task_t {
    void (*func)(void *);
    void *arg;
    struct _task_t *next;
} task_t;

/**
 * Describes the job queue
 */
typedef struct _task_queue_t {
    task_t *head;
    task_t *tail;
    pthread_mutex_t queue_mutex;
} task_queue_t;

/**
 * Thread pool structure
 *
 * NOTE: The thpool.h header typedefs _thpool_t to thpool_t
 */
struct _thpool_t {
    int size;                       /* Size of the thread pool */
    int shutdown;                   /* If 1 then then pool should terminate */
    pthread_t *threads;             /* Thread IDs of all threads */
    task_queue_t queue;             /* Job Queue */
    pthread_mutex_t pool_mutex;     /* Thread pool mutex */
    pthread_cond_t  pool_cond;      /* Thread pool condition variable */
};

/**
 * Is the task queue empty?
 * @param  queue The task queue on which the question is being asked
 * @return       0 if not empty, 1 if empty
 */
static int task_queue_empty(task_queue_t *queue) {
    return queue->head == NULL;
}

/**
 * Add an entry onto the task queue
 * @param queue Queue
 * @param task  Task
 */
static void task_queue_add(task_queue_t *queue, task_t *task) {
    if (task_queue_empty(queue)) {
        queue->head = task;
        queue->tail = task;
    } else {
        queue->tail->next = task;
        queue->tail = task;
    }
    task->next = NULL;
}

/**
 * Pull the first task from the queue
 * @param  queue Queue
 * @return       Task if avaiable, else NULL
 */
static task_t *task_queue_pull(task_queue_t *queue) {
    task_t *cur = queue->head;
    if (queue->head == queue->tail) {
        queue->head = queue->tail = NULL;
    } else {
        queue->head = cur->next;
    }
    return cur;
}

/**
 * Thread pool thread function
 * @param  arg The thread pool handler
 * @return     NULL
 */
static void *thpool_thread(void *arg) {
    task_t *task;
    thpool_t *pool = (thpool_t *) arg;
    for (;;) {
        /* Wait on the condition variable till work comes or asked to kill */
        pthread_mutex_lock(&pool->pool_mutex);
        while (task_queue_empty(&pool->queue) && !pool->shutdown) {
            pthread_cond_wait(&pool->pool_cond, &pool->pool_mutex);
        }

        /* Check for exit conditions */
        if (pool->shutdown) {
            break;
        }

        /* Grab available task */
        task = task_queue_pull(&pool->queue);

        /* Unlock */
        pthread_mutex_unlock(&pool->pool_mutex);

        /* Work if present */
        if (task) {
            (*(task->func))(task->arg); /* NOTE: User has to free the arg! */
        }

        /* Destroy the task */
        free(task);
    }
    pool->size--;<commit_msg>Fixed typo that can cause a crash<commit_after>#include <stdlib.h>     /* malloc(), free() */
#include <pthread.h>    /* pthread_*() */
#include "thpool.h"

/**
 * Describes a task - Also a singly linked list element
 */
typedef struct _task_t {
    void (*func)(void *);
    void *arg;
    struct _task_t *next;
} task_t;

/**
 * Describes the job queue
 */
typedef struct _task_queue_t {
    task_t *head;
    task_t *tail;
    pthread_mutex_t queue_mutex;
} task_queue_t;

/**
 * Thread pool structure
 *
 * NOTE: The thpool.h header typedefs _thpool_t to thpool_t
 */
struct _thpool_t {
    int size;                       /* Size of the thread pool */
    int shutdown;                   /* If 1 then then pool should terminate */
    pthread_t *threads;             /* Thread IDs of all threads */
    task_queue_t queue;             /* Job Queue */
    pthread_mutex_t pool_mutex;     /* Thread pool mutex */
    pthread_cond_t  pool_cond;      /* Thread pool condition variable */
};

/**
 * Is the task queue empty?
 * @param  queue The task queue on which the question is being asked
 * @return       0 if not empty, 1 if empty
 */
static int task_queue_empty(task_queue_t *queue) {
    return queue->head == NULL;
}

/**
 * Add an entry onto the task queue
 * @param queue Queue
 * @param task  Task
 */
static void task_queue_add(task_queue_t *queue, task_t *task) {
    if (task_queue_empty(queue)) {
        queue->head = task;
        queue->tail = task;
    } else {
        queue->tail->next = task;
        queue->tail = task;
    }
    task->next = NULL;
}

/**
 * Pull the first task from the queue
 * @param  queue Queue
 * @return       Task if avaiable, else NULL
 */
static task_t *task_queue_pull(task_queue_t *queue) {
    task_t *cur = queue->head;
    if (queue->head == queue->tail) {
        queue->head = queue->tail = NULL;
    } else {
        queue->head = cur->next;
    }
    return cur;
}

/**
 * Thread pool thread function
 * @param  arg The thread pool handler
 * @return     NULL
 */
static void * thpool_thread(void *arg) {
    task_t *task;
    thpool_t *pool = (thpool_t *) arg;
    for (;;) {
        /* Wait on the condition variable till work comes or asked to kill */
        pthread_mutex_lock(&pool->pool_mutex);
        while (task_queue_empty(&pool->queue) && !pool->shutdown) {
            pthread_cond_wait(&pool->pool_cond, &pool->pool_mutex);
        }

        /* Check for exit conditions */
        if (pool->shutdown) {
            break;
        }

        /* Grab available task */
        task = task_queue_pull(&pool->queue);

        /* Unlock */
        pthread_mutex_unlock(&pool->pool_mutex);

        /* Work if present */
        if (task) {
            (*(task->func))(task->arg); /* NOTE: User has to free the arg! */
        }

        /* Destroy the task */
        free(task);
    }
    pool->size--;
{'fraction_non_alphanumeric': 0.1256763833129691, 'fraction_numerical': 0.0010473031942747426, 'mean_word_length': 2.1518151815181517, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '270865', 'n_tokens_mistral': 1836, 'n_tokens_neox': 1797, 'n_words': 535}