/** * 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"); } }
/** * 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"); } }
/** * 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; }