/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the LICENSE file, which can be found at the root of the source code       *
 * distribution tree, or in https://www.hdfgroup.org/licenses.               *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

typedef struct H5TS_pool_task_t {
    H5TS_thread_start_func_t func; 
    void                    *ctx;  
    struct H5TS_pool_task_t *next; 
} H5TS_pool_task_t;

struct H5TS_pool_t {
    
    H5TS_semaphore_t sem;

    
    H5TS_mutex_t      queue_mutex; 
    bool              shutdown;    
    H5TS_pool_task_t *head, *tail; 

    
    unsigned       num_threads; 
    H5TS_thread_t *threads;     
};

static inline herr_t
H5TS_pool_add_task(H5TS_pool_t *pool, H5TS_thread_start_func_t func, void *ctx)
{
    H5TS_pool_task_t *task             = NULL;  
    bool              have_queue_mutex = false; 
    herr_t            ret_value        = SUCCEED;

    
    if (H5_UNLIKELY(NULL == pool || NULL == func))
        return FAIL;

    
    if (H5_UNLIKELY(NULL == (task = (H5TS_pool_task_t *)malloc(sizeof(H5TS_pool_task_t)))))
        return FAIL;
    task->func = func;
    task->ctx  = ctx;
    task->next = NULL;

    
    if (H5_UNLIKELY(H5TS_mutex_lock(&pool->queue_mutex) < 0)) {
        ret_value = FAIL;
        goto done;
    }
    have_queue_mutex = true;

    
    if (H5_UNLIKELY(pool->shutdown)) {
        ret_value = FAIL;
        goto done;
    }

    
    if (NULL != pool->tail) {
        pool->tail->next = task;
        pool->tail       = task;
    }
    else
        pool->head = pool->tail = task;

    
    task = NULL;

    
    if (H5_UNLIKELY(H5TS_mutex_unlock(&pool->queue_mutex) < 0)) {
        ret_value = FAIL;
        goto done;
    }
    have_queue_mutex = false;

    
    if (H5_UNLIKELY(H5TS_semaphore_signal(&pool->sem) < 0))
        ret_value = FAIL;

done:
    
    if (H5_UNLIKELY(ret_value < 0)) {
        
        
        if (H5_UNLIKELY(have_queue_mutex))
            H5TS_mutex_unlock(&pool->queue_mutex);
        if (task)
            free(task);
    }

    return (ret_value);
} 
