static apr_status_t thread_pool_construct()

in misc/apr_thread_pool.c [87:177]


static apr_status_t thread_pool_construct(apr_thread_pool_t **tp,
                                          apr_size_t init_threads,
                                          apr_size_t max_threads,
                                          apr_pool_t *pool)
{
    apr_status_t rv;
    apr_thread_pool_t *me;

    me = *tp = apr_pcalloc(pool, sizeof(apr_thread_pool_t));
    me->thd_max = max_threads;
    me->idle_max = init_threads;
    me->threshold = init_threads / 2;

    /* This pool will be used by different threads. As we cannot ensure that
     * our caller won't use the pool without acquiring the mutex, we must
     * create a new sub pool.
     */
    rv = apr_pool_create(&me->pool, pool);
    if (APR_SUCCESS != rv) {
        return rv;
    }
    /* Create the mutex on the parent pool such that it's always alive from
     * apr_thread_pool_{push,schedule,top}() callers.
     */
    rv = apr_thread_mutex_create(&me->lock, APR_THREAD_MUTEX_NESTED, pool);
    if (APR_SUCCESS != rv) {
        return rv;
    }
    rv = apr_thread_cond_create(&me->more_work, me->pool);
    if (APR_SUCCESS != rv) {
        apr_thread_mutex_destroy(me->lock);
        return rv;
    }
    rv = apr_thread_cond_create(&me->work_done, me->pool);
    if (APR_SUCCESS != rv) {
        apr_thread_cond_destroy(me->more_work);
        apr_thread_mutex_destroy(me->lock);
        return rv;
    }
    rv = apr_thread_cond_create(&me->all_done, me->pool);
    if (APR_SUCCESS != rv) {
        apr_thread_cond_destroy(me->work_done);
        apr_thread_cond_destroy(me->more_work);
        apr_thread_mutex_destroy(me->lock);
        return rv;
    }
    me->tasks = apr_palloc(me->pool, sizeof(*me->tasks));
    if (!me->tasks) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->tasks, apr_thread_pool_task, link);
    me->scheduled_tasks = apr_palloc(me->pool, sizeof(*me->scheduled_tasks));
    if (!me->scheduled_tasks) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->scheduled_tasks, apr_thread_pool_task, link);
    me->recycled_tasks = apr_palloc(me->pool, sizeof(*me->recycled_tasks));
    if (!me->recycled_tasks) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->recycled_tasks, apr_thread_pool_task, link);
    me->busy_thds = apr_palloc(me->pool, sizeof(*me->busy_thds));
    if (!me->busy_thds) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->busy_thds, apr_thread_list_elt, link);
    me->idle_thds = apr_palloc(me->pool, sizeof(*me->idle_thds));
    if (!me->idle_thds) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->idle_thds, apr_thread_list_elt, link);
    me->dead_thds = apr_palloc(me->pool, sizeof(*me->dead_thds));
    if (!me->dead_thds) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->dead_thds, apr_thread_list_elt, link);
    me->recycled_thds = apr_palloc(me->pool, sizeof(*me->recycled_thds));
    if (!me->recycled_thds) {
        goto CATCH_ENOMEM;
    }
    APR_RING_INIT(me->recycled_thds, apr_thread_list_elt, link);
    goto FINAL_EXIT;
  CATCH_ENOMEM:
    rv = APR_ENOMEM;
    apr_thread_cond_destroy(me->all_done);
    apr_thread_cond_destroy(me->work_done);
    apr_thread_cond_destroy(me->more_work);
    apr_thread_mutex_destroy(me->lock);
  FINAL_EXIT:
    return rv;
}