2011-06-11 40 views
2

我想編寫一個線程,從一個無限大小的任務容器中運行任務。條件變量的替代品(在Windows XP上的C/C + +)

雖然任務列表爲空,但嘗試獲取任務的線程應該被阻止。

來自Linux我想使用條件變量,它將在添加任務時發送信號,並在列表爲空時等待。

我發現CONDITION_VARIABLE只能在Windows Vista中使用,所以這是沒有問題的。 由於無限制的限制,信號量也有問題。

是否有任何適當的結構?

謝謝

+0

你不需要無限計數一個信號量來做到這一點,你只需要信號隊列的轉移爲空或不和互斥/臨界區保護數據結構 – nos 2011-06-11 14:14:03

+0

與linux不同,Windows不支持無限大容器。它也沒有足夠大的數據類型來計算無限數量的項目。你將不得不解決更實際的問題。 – 2011-06-11 17:12:01

回答

1

你爲什麼說信號量有問題? Linux/Windows都有最大數量的信號量,可以被逼真地描述爲「無限」。

在Windows上使用James的建議 - 它會正常工作。在裏面。零計數的信號量。將任務添加到您的大型(線程安全)容器中,然後發出信號。在線程中,等待信號量,然後從容器獲取任務並處理它。如果您願意,您可以將信號量實例傳遞給多個線程 - 這也可以正常工作。

RGDS, 馬丁

+0

我想將是最好的解決方案,我想要真正的無限制,而不僅僅是「真正的」。使用這個解決方案,我不得不改變設計一點,以防止嵌套的風險。使用條件變量我可以避免... – lkanab 2011-06-12 17:10:26

+0

'真正的無限制'是不現實的。我不能想象任何系統,32位,64位或1024位,其中信號最大計數可能小於集合中任務的數量。比如,你正在尋找4.2 GigaTasks。 – 2011-06-12 20:03:25

0

WaitForSingleObject和CreateSemaphore?

+1

或者如果你有多個合作伙伴,請看WaitForMultipleObjectSex。 – 2011-06-11 14:07:22

+0

我承諾,要使用WaitFormMultipleObjectSex,我必須處於可警戒狀態,但我已經有太多的啤酒:( – 2011-06-11 14:11:38

+0

@JohnZwinck hehe ...你改變了大寫的目的...沒有你嗎? – chacham15 2013-02-17 07:07:12

1

聽起來像是你想要一個Win32內核事件。見CreateEvent

0

感謝所有, 這就是我的結論是:

void ThreadPool::ThreadStartPoint(ThreadPool* tp) 
{ 
    while (1) 
    {  
     WaitForSingleObject(tp->m_taskCountSemaphore,INFINITE); // while (num of tasks==0) block; decreament num of tasks 

     BaseTask* current_task = 0; 

     // get top priority task 
     EnterCriticalSection (&tp->m_mutex); 
     { 
      current_task = tp->m_tasksQue.top(); 
      tp->m_tasksQue.pop(); 
     } 
     LeaveCriticalSection (&tp->m_mutex); 

     current_task->operator()(); // this is not critical section 
     current_task->PostExec(); 
    } 
} 

void ThreadPool::AddTask(BaseTask& _task) 
{ 
    EnterCriticalSection (&m_mutex); 
    { 
     m_tasksQue.push(&_task); 
     _task.PrepareTask(m_mutex); 
    } 
    LeaveCriticalSection (&m_mutex); 

    if (!ReleaseSemaphore(m_taskCountSemaphore, 
          1, // increament num of tasks by 1 
          NULL // don't store previuos num of tasks value 
         )) 
    {//if failed 
     throw ("semaphore release failed"); 
    } 
}