Example #1
0
/**
 * Add spare threads (called by main thread)
 * @return added threads number
 */
static int tpool_add_thread(tpool_t *tp, int num)
{
    TP_LOCK();
    if (tp->cur_spare > 0)
        num = 0;
    else if (num > (tp->max_total - tp->cur_total))
        num = tp->max_total - tp->cur_total;
    TP_UNLOCK();

    // create new threads
    if (num > 0)
    {
        int i, j = 0;

        // find deactived threads & create them
        for (i = 0; num > 0 && i < tp->max_total; i++)
        {
            if (tp->threads[i].status & TPOOL_THREAD_ACTIVED)
                continue;
            if (pthread_create(&tp->threads[i].tid, NULL, tpool_thread_start, &tp->threads[i]) != 0)
                break;
            tp->threads[i].status |= TPOOL_THREAD_ACTIVED;

            j++;
            num--;
            debug_printf("Thread[%d] was created (TID:%p)\n", i, tp->threads[i].tid);
        }

        // save new number
        TP_LOCK();
        tp->cur_total += j;
        tp->cur_spare += j;
        TP_UNLOCK();

        debug_printf("Thread pool number status (TOTAL:%d, SPARE:%d)\n", tp->cur_total, tp->cur_spare);
        return j;
    }

    // none of threads created
    return 0;
}
Example #2
0
/**
 * Cancel all idle thread & notify working thread quit after finishing job
 */
void tpool_do_cancel(tpool_t *tp, int wait)
{
	if (!tp || !(tp->status & TPOOL_STATUS_INITED))
		return;

	debug_printf("send cancel signal to all threads");
	tp->status |= TPOOL_STATUS_CANCELED;
	pthread_cond_broadcast(&tp->cond);

	if (wait == 1)
	{
		debug_printf("waiting for the end of all threads ...");
		TP_LOCK();
		while (tp->cur_total > 0)
			TP_WAIT();
		TP_UNLOCK();
		debug_printf("ok, all threads exited");
	}
}
Example #3
0
/**
 * Cancel all idle thread & notify working thread quit after finishing job
 */
void tpool_do_cancel(tpool_t *tp, int wait)
{
    if (!tp || !(tp->status & TPOOL_STATUS_INITED))
        return;

    debug_printf("Send cancel signal to all threads\n");
    tp->status |= TPOOL_STATUS_CANCELED;
    pthread_cond_broadcast(&tp->cond);

    if (wait == 1)
    {
        debug_printf("Waiting for all threads to end...\n");
        TP_LOCK();
        while (tp->cur_total > 0)
            TP_WAIT();
        TP_UNLOCK();
        debug_printf("OK, all work threads exited\n");
    }
}
Example #4
0
/**
 * Submit task to thread pool
 */
void tpool_exec(tpool_t *tp, tpool_func_t func, tpool_func_t cancel, void *arg)
{
	struct tpool_task *task;

	task = (struct tpool_task *) malloc(sizeof(struct tpool_task));
	if (task == NULL)
	{
		debug_printf("failed to allocate memory for new task (SIZE:%d)", (int) sizeof(struct tpool_task));
		return;
	}

	memset(task, 0, sizeof(struct tpool_task));
	task->task_func = func;
	task->cancel_func = cancel;
	task->arg = arg;

	// save to task list
	TP_LOCK();
	if (tp->task_list == NULL)
		tp->task_list = task;
	else
	{
		struct tpool_task *tail = tp->task_list;

		while (tail->next != NULL)
			tail = tail->next;
		tail->next = task;
	}
	TP_UNLOCK();
	debug_printf("add new task to thread pool (SPARE:%d, TOTAL:%d)", tp->cur_spare, tp->cur_total);

	// check spare threads
	if (tp->cur_spare == 0)
	{
		debug_printf("try to add some new threads (NUM:%d)", tp->min_spare);
		tpool_add_thread(tp, tp->min_spare);
	}

	// notify
	pthread_cond_signal(&tp->cond);
}
Example #5
0
/**
 * Cleanup function called when the thread was canceld during task execution
 * @param arg struct tpool_thread
 */
static void tpool_thread_cleanup(void *arg)
{
	struct tpool_thread *me = (struct tpool_thread *) arg;
	tpool_t *tp = me->tp;

	debug_printf("thread[%d] is canceled, run cleanup function (TID:%p, TOTAL:%d)",
		me->index, me->tid, tp->cur_total - 1);

	// call cancel handler of task
	if (me->task->cancel_func != NULL)
		(*me->task->cancel_func)(me->task->arg);

	// free task
	free(me->task);
	me->status = TPOOL_THREAD_NONE;

	TP_LOCK();
	tp->cur_total--;
	if (me->tp->cur_total == 0)
		pthread_cond_signal(&tp->cond);
	TP_UNLOCK();
}
Example #6
0
/**
 * Thread start point
 */
static void *tpool_thread_start(void *arg)
{
	struct tpool_thread *me = (struct tpool_thread *) arg;
	tpool_t *tp = me->tp;

	// init the thread
	tpool_thread_init(me);

	// loop to execute task
	while (1)
	{
		// waiting for task
		TP_LOCK();
		tp->cur_spare++;
		me->status ^= TPOOL_THREAD_BUSY;
		while ((me->task = tpool_get_task(tp)) == NULL && !TP_CANCELED())
			TP_WAIT();
		me->status |= TPOOL_THREAD_BUSY;
		tp->cur_spare--;
		TP_UNLOCK();

		// empty task (cancled)
		if (me->task == NULL)
		{
			TP_LOCK();
			me->status = TPOOL_THREAD_NONE;
			tp->cur_total--;
			TP_UNLOCK();

			debug_printf("thread[%d] get empty task(NULL), forced to cancel (TID:%p, CALLS:%d, TOTAL:%d)",
				me->index, me->tid, me->calls, tp->cur_total);

			break;
		}

		// task accepted
		debug_printf("thread[%d] accept new task (TID:%p, FUNC:%p, ARG:%p)",
			me->index, me->tid, me->task->task_func, me->task->arg);

		time(&me->task->begin);
		me->calls++;
		me->status |= TPOOL_THREAD_TASK;

		// call task function with cleanup function & cancelstate
		pthread_cleanup_push(tpool_thread_cleanup, me);
		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
		(*me->task->task_func)(me->task->arg);
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
		pthread_cleanup_pop(0);

		me->status ^= TPOOL_THREAD_TASK;
		free(me->task);
		debug_printf("thread[%d] finished the task (TID:%p, CALLS:%d)", me->index, me->tid, me->calls);

		// check the number of spare threads
		if (tp->cur_spare >= tp->max_spare)
		{
			TP_LOCK();
			me->status = TPOOL_THREAD_NONE;
			tp->cur_total--;
			TP_UNLOCK();

			debug_printf("thread[%d] suicided due to too many spare threads (TID:%p, SPARE:%d, TOTAL:%d)",
				me->index, me->tid, tp->cur_spare, tp->cur_total);
			break;
		}
	}

	// notify the thread that is waiting for canceling
	if (tp->cur_total == 0)
		pthread_cond_signal(&tp->cond);

	return NULL;
}