예제 #1
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");
	}
}
예제 #2
0
파일: tpool.c 프로젝트: soitun/xunsearch
/**
 * 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");
    }
}
예제 #3
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;
}