/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // process single task bool CTaskProcessor::ProcessTask(CTask& stTask) { TCHAR strTaskName[100]; try { _tcscpy(strTaskName, stTask.TaskName()); return stTask.Process(); } catch (_com_error& e) { AddLog(LOG_ERROR, _T("ATL Exception while processing task: Source=%s; Description=%s"), (LPCTSTR) e.Source(), (PCTSTR) e.Description()); } catch (...) { AddLog(LOG_ERROR, _T("Unhandled exception while processing task %s"), strTaskName); } try { // give it another chance return stTask.OnException(); } catch(_com_error& e) { AddLog(LOG_ERROR, _T("Second ATL exception while processing task: Source=%s; Description=%s"), (LPCTSTR) e.Source(), (PCTSTR) e.Description()); } catch (...) { AddLog(LOG_ERROR, _T("Second unhandled exception while processing task %s"), strTaskName); } return true; // delete this buggy task! }
void CKernel::Start(void) { if (m_dwMagic != CKERNEL_MAGIC) { kprintf("[e] Error! My constructor wasn't called properly.\n"); return; } kprintf("wat\n"); m_Logger = new CLogger(); Alentours::CPCIManager::Initialize(); CKernelML4 *ML4 = new CKernelML4(); CTask *KernelTask = new CTask(*ML4); CScheduler::AddTask(KernelTask); kprintf("[i] Kernel task has PID %i.\n", KernelTask->GetPID()); ML4->Apply(); KernelTask->UseStack([](CTask *Task) { kprintf("[i] Switched to Tier1 stack\n"); // After enabling, only CScheduler::* calls are allowed for API CScheduler::Enable(); kprintf("[i] Enabled scheduler.\n"); g_Kernel.SpawnThreads(); CScheduler::Exit(); }); }
//resets the contents of the message list based upon the currently viewed task void CBackEndDialog::ResetMessageList() { //we need to fill the message list up with the message associated with the //newly selected task //flush existing messages EmptyMessageList(); CTask* pTask = GetViewedTask(); if(pTask) { //now fill up the message list with all of our messages CTaskMessage* pCurrMsg = pTask->GetMessageHead(); while(pCurrMsg) { if(ShouldShowMessage(pCurrMsg, m_eMsgFilter)) { //add this string and a pointer to the orinignal message AddMessageToList(pCurrMsg); } pCurrMsg = pCurrMsg->GetNext(); } } RedrawMessageList(); }
void CMole::AppendHuntTask(const CFVec2& _kvrTargetPosition) { // Remove all hunt tasks before this while (m_Tasks.top().GetType() == CTask::TYPE_HUNT) { m_Tasks.pop(); } CTask tHunt; tHunt.Initialise(CTask::TYPE_HUNT); int iTargetNode = s_pSharedPath->GenerateNodeId(s_pSharedPath->GetNode(_kvrTargetPosition)); std::vector<int> aNodeIdsPath; bool bPathFound = s_pSharedPath->FindPath(m_vPosition, iTargetNode, aNodeIdsPath); if (bPathFound) { tHunt.SetTargetNodeId(iTargetNode); tHunt.SetNodeIdsPath(aNodeIdsPath); m_Tasks.push(tHunt); } else { // Cannot reach target assert(false); } }
void CTSGetIp::Handle(void* Buffer, int Size) { //解包 CReGetUserIpPacket opPacket; opPacket.Unpack(Buffer, Size); int count = opPacket.UserList.size(); int TaskId = opPacket.nTaskId; int SeqNumber = opPacket.Header.nSeqNumber; Tracker.Back(SeqNumber); //消包 CTask *Task; for(int i = 0; i < count; i++) { if(! TaskPool.GetTask(TaskId,Task)) break; int UserIp = opPacket.UserList.at(i).nUserIp; int TcpPort = opPacket.UserList.at(i).wTcpPort; string FileCode = opPacket.strHashValue; Task->SetCode(FileCode); CResource *Resource = new CResource(IpToString(UserIp), TcpPort); CResourcePool* ResourcePool = Task->GetResourcePool(); ResourcePool->AddResource(Resource); } }
bool CTabCtrl::Register(void) { CString strClassName; WNDCLASS wcClass; // Get application object. CTask* pApp = CTask::This(); ASSERT(pApp); // Get the class name for the resource file. strClassName.LoadRsc(IDS_TABCTRL_WND); // Fill in class structure. wcClass.style = CS_HREDRAW | CS_VREDRAW; wcClass.lpfnWndProc = DefWindowProc; wcClass.cbClsExtra = 0; wcClass.cbWndExtra = 0; wcClass.hInstance = pApp->Module()->Handle(); wcClass.hIcon = NULL; wcClass.hCursor = pApp->Module()->LoadStdCursor(IDC_ARROW); wcClass.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); wcClass.lpszMenuName = NULL; wcClass.lpszClassName = strClassName; // Register. return ::RegisterClass(&wcClass); }
SGVector<index_t>* CTaskTree::get_tasks_indices() const { CList* blocks = new CList(true); collect_leaf_tasks_recursive(m_root_task, blocks); SG_DEBUG("Collected %d leaf blocks\n", blocks->get_num_elements()); //check_blocks_list(blocks); //SGVector<index_t> ind(blocks->get_num_elements()+1); int t_i = 0; //ind[0] = 0; // SGVector<index_t>* tasks_indices = SG_MALLOC(SGVector<index_t>, blocks->get_num_elements()); CTask* iterator = (CTask*)blocks->get_first_element(); do { new (&tasks_indices[t_i]) SGVector<index_t>(); tasks_indices[t_i] = iterator->get_indices(); //REQUIRE(iterator->is_contiguous(),"Task is not contiguous"); //ind[t_i+1] = iterator->get_indices()[iterator->get_indices().vlen-1] + 1; //SG_DEBUG("Block = [%d,%d]\n", iterator->get_min_index(), iterator->get_max_index()); SG_UNREF(iterator); t_i++; } while ((iterator = (CTask*)blocks->get_next_element()) != NULL); SG_UNREF(blocks); return tasks_indices; }
void* CThreadPool::ThreadFunc(void * threadData) { pthread_t tid = pthread_self(); while(1) { pthread_mutex_lock(&m_pthreadMutex); pthread_cond_wait(&m_pthreadCond,&m_pthreadMutex); cout << "tid:" << tid << " run" << endl; //get task vector<CTask*>* taskList = (vector<CTask*>*)threadData; vector<CTask*>::iterator iter = taskList->begin(); while(iter != taskList->end()) { MoveToBusy(tid); break; } CTask* task = *iter; taskList->erase(iter); pthread_mutex_unlock(&m_pthreadMutex); cout << "idel thread number:" << CThreadPool::m_vecIdleThread.size() << endl; cout << "busy thread number:" << CThreadPool::m_vecBusyThread.size() << endl; //cout << "task to be run:" << taskList->size() << endl; task->Run(); //cout << "CThread::thread work" << endl; cout << "tid:" << tid << " idle" << endl; } return (void*)0; }
void collect_tree_tasks_recursive(CTask* subtree_root_block, vector<task_tree_node_t>* tree_nodes, int low) { int32_t lower = low; CList* sub_blocks = subtree_root_block->get_subtasks(); if (sub_blocks->get_num_elements()>0) { CTask* iterator = (CTask*)sub_blocks->get_first_element(); do { if (iterator->get_num_subtasks()>0) { int32_t n_leaves = count_leaf_tasks_recursive(iterator); //SG_SDEBUG("Block [%d %d] has %d leaf childs \n",iterator->get_min_index(), iterator->get_max_index(), n_leaves); tree_nodes->push_back(task_tree_node_t(lower,lower+n_leaves-1,iterator->get_weight())); collect_tree_tasks_recursive(iterator, tree_nodes, lower); lower = lower + n_leaves; } else lower++; SG_UNREF(iterator); } while ((iterator = (CTask*)sub_blocks->get_next_element()) != NULL); } SG_UNREF(sub_blocks); }
//------------------------------------------------------------------------ // 쓰레드 실행 // Task를 실행시킨다. //------------------------------------------------------------------------ void CThread::Run() { while (RUN == m_State) { //1. 태스크 처리 EnterTaskSync(); { TaskItor it = m_Tasks.begin(); while (m_Tasks.end() != it) { CTask *pTask = *it; if (CTask::RR_END == pTask->Run()) { // 태스크 제거 it = m_Tasks.erase(it); delete pTask; } else { ++it; } } } LeaveTaskSync(); //2. 메세지 처리 DispatchMessage(); Sleep(1); } // 남았을지도 모를 메세지를 마지막으로 처리한다. DispatchMessage(); }
SGVector<index_t> CTaskTree::get_SLEP_ind() { CList* tasks = new CList(true); collect_leaf_tasks_recursive(m_root_task, tasks); SG_DEBUG("Collected %d leaf tasks\n", tasks->get_num_elements()); check_task_list(tasks); SGVector<index_t> ind(tasks->get_num_elements()+1); int t_i = 0; ind[0] = 0; CTask* iterator = (CTask*)tasks->get_first_element(); do { ind[t_i+1] = iterator->get_max_index(); SG_DEBUG("Task = [%d,%d]\n", iterator->get_min_index(), iterator->get_max_index()); SG_UNREF(iterator); t_i++; } while ((iterator = (CTask*)tasks->get_next_element()) != NULL); SG_UNREF(tasks); return ind; }
//--------------------------------------------------------------------------- // @function: // CAutoTaskProxy::PropagateError // // @doc: // Propagate the error from sub task to current task // //--------------------------------------------------------------------------- void CAutoTaskProxy::PropagateError ( CTask *ptskSub ) { GPOS_ASSERT(m_fPropagateError); // sub-task must be in error status and have a pending exception GPOS_ASSERT(ITask::EtsError == ptskSub->Ets() && ptskSub->FPendingExc()); CTask *ptskCur = CTask::PtskSelf(); // current task must have no pending error GPOS_ASSERT(NULL != ptskCur && !ptskCur->FPendingExc()); IErrorContext *perrctxtCur = ptskCur->Perrctxt(); // copy necessary error info for propagation perrctxtCur->CopyPropErrCtxt(ptskSub->Perrctxt()); // reset error of sub task ptskSub->Perrctxt()->Reset(); // propagate the error CException::Reraise(perrctxtCur->Exc(), true /*fPropagate*/); }
bool CTaskList::LoadTasks() { CINIFile* pTasksIni = new CINIFile(cTasksFile); CTask* pTask = NULL; CDateTime dtNow = DTNow(); int iSections = pTasksIni->GetSectionsCount(); for (int t = 0; t < iSections; t++) { CString sSect = pTasksIni->GetNextSection(); if (sSect.Empty()) continue; pTask = new CTask(); m_aTasks.Add(pTask); // Получим указатель на структуру, содержащую данные задачи PTaskInfo pTaskInfo = pTask->GetPTaskInfo(); // Заполним данные задачи из INI файла pTaskInfo->sName = sSect; pTaskInfo->sSrcFolder = pTasksIni->GetString(sSect.C(), TEXT("Source folder")); pTaskInfo->sDestFolder = pTasksIni->GetString(sSect.C(), TEXT("Dest folder")); pTaskInfo->sDestGenName = pTasksIni->GetString(sSect.C(), TEXT("Generate name")); pTaskInfo->sIncludeMask = pTasksIni->GetString(sSect.C(), TEXT("Incl mask")); pTaskInfo->sExcludeMask = pTasksIni->GetString(sSect.C(), TEXT("Excl mask")); pTaskInfo->bSubFolders = pTasksIni->GetBool(sSect.C(), TEXT("Subfolders")); pTaskInfo->bScheduled = pTasksIni->GetBool(sSect.C(), TEXT("Scheduled")); pTaskInfo->sSchedule = pTasksIni->GetString(sSect.C(), TEXT("Schedule")); pTaskInfo->bDoArchive = pTasksIni->GetBool(sSect.C(), TEXT("Do archive")); pTaskInfo->bArchCompress = pTasksIni->GetNumeric<BYTE>(sSect.C(), TEXT("Compress level")); pTaskInfo->bArchSFX = pTasksIni->GetBool(sSect.C(), TEXT("SFX")); pTaskInfo->bArchDelFiles = pTasksIni->GetBool(sSect.C(), TEXT("Del files")); pTaskInfo->bArchLock = pTasksIni->GetBool(sSect.C(), TEXT("Lock")); pTaskInfo->sArchTaskCmd = pTasksIni->GetString(sSect.C(), TEXT("Archiver cmd")); pTaskInfo->i64FinishedBytes = pTasksIni->GetNumeric<__int64>(sSect.C(), TEXT("Finished bytes")); // "Распакуем" строку последнего запуска в CDateTime CDateTime dtLastRun; dtLastRun.UnpackFromString(pTasksIni->GetString(sSect.C(), TEXT("Last run"), TEXT("00000000000000"))); pTask->SetLastRun(dtLastRun); // построим дерево расписания для задачи pTask->BuildScheduleTree(); // и подсчитаем время след. запуска pTask->CalcNextRun(dtNow); } delete pTasksIni; return true; }
void CTaskScheduler::scheduler_thread() { _is_scheduled = true; while (!_job_tasks.empty()) { // create task std::list<CTask*> wait_task_queue; std::list<openflow::task_info*>* task_list = _job_tasks.front(); for (std::list<openflow::task_info*>::iterator iter = task_list->begin() ; iter != task_list->end();++iter) { openflow::task_info* task_info = *iter; CTask *task = new CTask(task_info); wait_task_queue.push_back(task); delete *iter; } // schedule task while (!wait_task_queue.empty()) { boost::this_thread::sleep(boost::posix_time::milliseconds(500)); std::list<CTask*>::iterator it = wait_task_queue.begin(); CTask *task = *it; if (task->start()) { _run_task_queue[task->get_uuid()] = task; wait_task_queue.erase(it++); } else { ++it; } } // check is task finished while (!_run_task_queue.empty()) { boost::this_thread::sleep(boost::posix_time::milliseconds(500)); { boost::mutex::scoped_lock lock(_mutex); std::map<std::string, CTask*>::iterator it = _run_task_queue.begin(); CTask *task = it->second; if (task->is_finished()) { LOG(INFO) << "task finished: "; // @todo update db state _run_task_queue.erase(it++); delete task; } else { ++it; } } } _job_tasks.pop_front(); } _is_finished = true; }
void CClientPad::DoPulse ( CClientPed * pPed ) { CPlayerPed * pGamePlayer = pPed->GetGamePlayer (); if ( pGamePlayer ) { bool bIsDead = false, bInVehicle = false; CTask * pTask = pPed->GetTaskManager ()->GetTask ( TASK_PRIORITY_EVENT_RESPONSE_NONTEMP ); if ( pTask && pTask->GetTaskType () == TASK_SIMPLE_DEAD ) bIsDead = true; if ( pGamePlayer->GetVehicle () ) bInVehicle = true; CControllerState cs; memset ( &cs, 0, sizeof ( CControllerState ) ); if ( !bIsDead ) { if ( !bInVehicle ) { cs.ButtonCircle = ( m_bStates [ 0 ] ) ? 255 : 0; // Fire cs.LeftStickY = ( ( m_bStates [ 3 ] && m_bStates [ 4 ] ) || ( !m_bStates [ 3 ] && !m_bStates [ 4 ] ) ) ? 0 : ( m_bStates [ 3 ] ) ? -128 : 128; cs.LeftStickX = ( ( m_bStates [ 5 ] && m_bStates [ 6 ] ) || ( !m_bStates [ 5 ] && !m_bStates [ 6 ] ) ) ? 0 : ( m_bStates [ 5 ] ) ? -128 : 128; cs.ButtonSquare = ( m_bStates [ 11 ] ) ? 255 : 0; // Jump cs.ButtonCross = ( m_bStates [ 12 ] ) ? 255 : 0; // Sprint cs.ShockButtonR = ( m_bStates [ 13 ] ) ? 255 : 0; // Look Behind cs.ShockButtonL = ( m_bStates [ 14 ] ) ? 255 : 0; // Crouch cs.LeftShoulder1 = ( m_bStates [ 15 ] ) ? 255 : 0; // Action cs.m_bPedWalk = ( m_bStates [ 16 ] ) ? 255 : 0; // Walk cs.RightShoulder1 = ( m_bStates [ 39 ] ) ? 255 : 0; // Aim Weapon } else { cs.ButtonCircle = ( m_bStates [ 17 ] ) ? 255 : 0; // Fire cs.LeftShoulder1 = ( m_bStates [ 18 ] ) ? 255 : 0; // Secondary Fire cs.LeftStickX = ( ( m_bStates [ 19 ] && m_bStates [ 20 ] ) || ( !m_bStates [ 19 ] && !m_bStates [ 20 ] ) ) ? 0 : ( m_bStates [ 19 ] ) ? -128 : 128; cs.LeftStickY = ( ( m_bStates [ 21 ] && m_bStates [ 22 ] ) || ( !m_bStates [ 21 ] && !m_bStates [ 22 ] ) ) ? 0 : ( m_bStates [ 21 ] ) ? -128 : 128; cs.ButtonCross = ( m_bStates [ 23 ] ) ? 255 : 0; // Accelerate cs.ButtonSquare = ( m_bStates [ 24 ] ) ? 255 : 0; // Reverse cs.ShockButtonL = ( m_bStates [ 28 ] ) ? 255 : 0; // Horn cs.RightShoulder1 = ( m_bStates [ 30 ] ) ? 255 : 0; // Handbrake cs.LeftShoulder2 = ( m_bStates [ 31 ] || m_bStates [ 33 ] ) ? 255 : 0; // Look Left cs.RightShoulder2 = ( m_bStates [ 32 ] || m_bStates [ 33 ] ) ? 255 : 0; // Look Right cs.RightStickX = ( ( m_bStates [ 35 ] && m_bStates [ 36 ] ) || ( !m_bStates [ 35 ] && !m_bStates [ 36 ] ) ) ? 0 : ( m_bStates [ 35 ] ) ? 128 : -128; cs.RightStickY = ( ( m_bStates [ 37 ] && m_bStates [ 38 ] ) || ( !m_bStates [ 37 ] && !m_bStates [ 38 ] ) ) ? 0 : ( m_bStates [ 37 ] ) ? 128 : -128; } } pPed->SetControllerState ( cs ); } }
void CMole::AppendExploreTask() { CTask tExplore; tExplore.Initialise(CTask::TYPE_EXPLORE); m_Tasks.push(tExplore); }
void CMole::AppendSnoozeTask(float _fTime) { CTask tSleep; tSleep.Initialise(CTask::TYPE_SNOOZE); tSleep.SetSnoozeTimeLeft(_fTime); m_Tasks.push(tSleep); }
void CMole::AppendStuckTask(float _fTime) { CTask tStuck; tStuck.Initialise(CTask::TYPE_STUCK); tStuck.SetStuckTimeLeft(_fTime); m_Tasks.push(tStuck); }
CTask* CTaskList::AddTask(PTaskInfo TaskInfo) { // Создадим новый объект-задачу CTask* pTask = new CTask(); m_aTasks.Add(pTask); // Присвоим переданную информацию о задаче только что созданному объекту *(pTask->GetPTaskInfo()) = *TaskInfo; return pTask; }
void CMenu::LoadRsc(uint iID) { ASSERT(m_hMenu == NULL); // Get application object. CTask* pApp = CTask::This(); ASSERT(pApp); // Load the resource. m_hMenu = pApp->Module()->LoadMenu(iID); }
int CCollector::InitWebPage() { CTask* task = m_tasks.GetFirstTask(); string url = task->GetUrl(); m_webPageMgr.CreateWebPage(url); task->CreateJob(JOB_STATUS_CRAWL); return 0; }
void CAccel::LoadRsc(uint iID) { ASSERT(m_hAccel == NULL); // Get application object. CTask* pApp = CTask::This(); ASSERT(pApp); // Load the resource. m_hAccel = pApp->Module()->LoadAccel(iID); }
void CMole::ProcessSnooze(float _fTimeDelta, CTask& _rTask) { _rTask.DecrementSnoozeTime(_fTimeDelta); // Check sleep is over if (_rTask.GetSnoozeTimeLeft() < 0.0f) { m_Tasks.pop(); } }
//--------------------------------------------------------------------------- // @function: // CAutoTaskProxy::EresFindFinished // // @doc: // Find finished task // //--------------------------------------------------------------------------- GPOS_RESULT CAutoTaskProxy::EresFindFinished ( CTask **pptsk ) { *pptsk = NULL; #ifdef GPOS_DEBUG // check if there is any task scheduled BOOL fScheduled = false; // check if all tasks have been reported as finished BOOL fReportedAll = true; #endif // GPOS_DEBUG // iterate task list for (CTask *ptsk = m_list.PtFirst(); NULL != ptsk; ptsk = m_list.PtNext(ptsk)) { #ifdef GPOS_DEBUG // check if task has been scheduled if (ptsk->FScheduled()) { fScheduled = true; } #endif // GPOS_DEBUG // check if task has been reported as finished if (!ptsk->FReported()) { #ifdef GPOS_DEBUG fReportedAll = false; #endif // GPOS_DEBUG // check if task is finished if (ptsk->FFinished()) { // mark task as reported ptsk->SetReported(); *pptsk = ptsk; return GPOS_OK; } } } GPOS_ASSERT(fScheduled && "No task scheduled yet"); GPOS_ASSERT(!fReportedAll && "All tasks have been reported as finished"); return GPOS_NOT_FOUND; }
void CTask::TaskEntry (void *pParam) { CTask *pThis = (CTask *) pParam; assert (pThis != 0); pThis->Run (); pThis->m_State = TaskStateTerminated; CScheduler::Get ()->Yield (); assert (0); }
IZ_BOOL CGestureDetector::IsCancel( threadmodel::CTimerTask* task, void* data) { IZ_ASSERT(task != IZ_NULL); IZ_ASSERT(data != IZ_NULL); TYPE type = *(TYPE*)data; CTask* gestureTask = reinterpret_cast<CTask*>(task); return (gestureTask->GetGestureType() == type); }
//--------------------------------------------------------------------------- // @function: // CAutoTaskProxyTest::EresUnittest_Cancel // // @doc: // Cancel and destroy tasks while queued/executing // //--------------------------------------------------------------------------- GPOS_RESULT CAutoTaskProxyTest::EresUnittest_Destroy() { const ULONG culTskCnt = 90; CAutoMemoryPool amp; IMemoryPool *mp = amp.Pmp(); CWorkerPoolManager *pwpm = CWorkerPoolManager::WorkerPoolManager(); // scope for ATP { CAutoTaskProxy atp(mp, pwpm); CTask *rgPtsk[culTskCnt]; ULLONG rgRes[culTskCnt]; CTask *ptsk = NULL; atp.SetPropagateError(false /* fPropagateError */); for (ULONG i = 0; i < culTskCnt / 3; i++) { GPOS_CHECK_ABORT; // create 3 tasks rgPtsk[3*i] = atp.Create(CAutoTaskProxyTest::PvUnittest_Short, &rgRes[3*i]); rgPtsk[3*i + 1] = atp.Create(CAutoTaskProxyTest::PvUnittest_Long, &rgRes[3*i + 1]); rgPtsk[3*i + 2] = atp.Create(CAutoTaskProxyTest::PvUnittest_Infinite, &rgRes[3*i + 2]); atp.Schedule(rgPtsk[3*i]); atp.Schedule(rgPtsk[3*i + 1]); atp.Schedule(rgPtsk[3*i + 2]); // cancel one task atp.Cancel(rgPtsk[3*i + 2]); // destroy completed tasks while (0 < atp.TaskCount() && GPOS_OK == atp.TimedWaitAny(&ptsk, 0)) { GPOS_ASSERT(CTask::EtsCompleted == ptsk->GetStatus() || ptsk->IsCanceled()); atp.Destroy(ptsk); } } // ATP cancels running task } return GPOS_OK; }
SGVector<index_t>* CTaskGroup::get_tasks_indices() const { int32_t n_tasks = m_tasks->get_num_elements(); SG_DEBUG("Number of tasks = %d\n", n_tasks); SGVector<index_t>* tasks_indices = SG_MALLOC(SGVector<index_t>, n_tasks); for (int32_t i=0; i<n_tasks; i++) { CTask* task = (CTask*)m_tasks->get_element(i); tasks_indices[i] = task->get_indices(); SG_UNREF(task); } return tasks_indices; }
/** * * OnTask * called when a thread is tasked using the Event * member function * **/ BOOL CThread::OnTask( LPVOID lpvData /*data passed from thread*/ ) { CTask *pTask = (CTask *)lpvData; pTask->SetTaskStatus(TaskStatusBeingProcessed); BOOL bReturn = pTask->Task(); pTask->SetTaskStatus(TaskStatusCompleted); return bReturn; }
void CPoolThread::run() { while (isRun()) { if (_threadPool->getTaskCount() == 0) { wait(); //wait } //wakeup, then do work if (isRun()) { CTask* task = _threadPool->popTask(); if (task) { task->doWork(); } //TODO: how to destroy task object } } }