
#include <stdlib.h>

#include "mecha.h"

#include "threadpool.h"
#include "processor.h"
#include "request_dispatcher.h"

#include "request_handler_entry.h"

struct s_ThreadPool
{
    thrTtpool   *pool;
};


static ThreadPool *g_threadpool = NULL;
static pthread_rwlock_t g_threadpool_lock = PTHREAD_RWLOCK_INITIALIZER;

#undef CLEANUP_THREADPOOL

#ifdef CLEANUP_THREADPOOL
static void threadpool_cleanup (int sig, void *ptr);
#endif


ThreadPool *
threadpool_new()
{
    ThreadPool *threads = malloc (sizeof (ThreadPool));

    threads->pool = thrFinit (64, 64, 1);

#ifdef CLEANUP_THREADPOOL
#ifdef HAVE_ON_EXIT
    on_exit (threadpool_cleanup, threads);
#endif
#endif

    return (threads);
}

void
threadpool_destroy (void *ptr)
{
    ThreadPool *threads = (ThreadPool *) ptr;

    thrFdestroy (threads->pool, 0);

    free (threads);
}

#ifdef CLEANUP_THREADPOOL
static void
threadpool_cleanup (__attribute__ ((unused)) int sig, void *ptr)
{
    logFmsg (CONT_LOG_DEBUG, "threadpool: Cleaning up resources.");

    threadpool_destroy (ptr);
}
#endif

ThreadPool *
threadpool_getInstance()
{
    pthread_rwlock_rdlock (&g_threadpool_lock);

    if (g_threadpool == NULL)
    {
        pthread_rwlock_unlock (&g_threadpool_lock);
        pthread_rwlock_wrlock (&g_threadpool_lock);

        if (g_threadpool == NULL)
        {
            g_threadpool = threadpool_new();
        }
    }

    pthread_rwlock_unlock (&g_threadpool_lock);

    return (g_threadpool);
}

bool
threadpool_queueUserWorkItem (ThreadPool *pool, WorkItemDelegate delegate, void *context)
{
    if (thrFadd_work (pool->pool, delegate, context) == 1)
    {
        return (true);
    }
    else
    {
        return (false);
    }
}
