2011-11-25 81 views
2

我不知道如何把這個問題放在這個論壇中,我想問什麼,並希望得到一些輸入。C++中的線程池設計

我正在爲我的項目編寫一個線程池。我有以下設計。

  1. 我保持線程std::vector<ThreadWrapper <threadFuncParam>* > m_vecThreads;

  2. 的載體和推動threds到列表m_vecThreads.push_back(pThreadWrapper);

  3. 當新的請求到來時我正在線程池如下

    if(!m_vecThreads.empty()) 
    { 
        ThreadWrapper <threadFuncParam>* pWrapper = m_vecThreads.back(); 
        m_vecThreads.pop_back(); 
        //... Awake threadd 
    } 
    
  4. 當線程工作完成後,它被推回到線程池。

趁現在gracefull關機我有設計優雅現在停止線程上面我面臨的問題,我如何能阻止線程在vector容器我從矢量坡平當請求服務,所以我失去了指針直到服務完成。 有沒有更好的我可以做到這一點或處理這種情況下,如地圖或其他標準C++支持的容器?

另一個問題是

在關閉過程中,我有一個場景線程在這裏做在我的情況下,來自這可能需要時間數據庫中讀取數據的過程,所以我不能等到它是完整的 ,我想送答覆客戶掛起的請求線程正在處理,我即將殺死該值是不好的。

謝謝!

+0

你有什麼沒有線程的載體而指針到線程的向量。你如何自己實例化線程,你用'new'手動執行嗎?考慮將線程包裝存儲在另一個容器中,例如'std :: vector >',並將這些線程的地址放入'm_vecThreads'中。 – leftaroundabout

+0

你的「另一個問題」應該作爲一個真正的其他問題被問及+你不清楚你的問題是什麼。 – stefaanv

回答

0

爲了解決你的第一個問題,把它推到另一個向量上,比如m_vecBusyThreads,當它完成時,把它拿下來(注意,你必須有一些機制來搜索完成的線程)。對於你的第二個問題,最乾淨的解決方案是加入每個線程,直到它「關閉」,任何其他方法可能最終產生一些不良副作用(尤其是如果它連接到數據庫等)。你有繁忙的容器,遍歷告訴每個關閉,然後遍歷每個免費的容器,關閉並加入每個線程。然後返回繁忙的容器並嘗試加入每個線程。這可能會給繁忙線程一點時間關閉乾淨。

boost :: threads支持這種中斷點的概念,其思想是你可以在任何這些點上中斷一個線程,但是有些調用是不可中斷的(通常是阻塞調用),你需要找到最好的方法以停止每種類型(例如套接字讀取可能會發送一個虛擬數據包等)

0

我已經在C中完成了,所以解決方案不是「C++」ish,但我使用了兩個數組:一個包含線程,另一個包含used/unused(〜布爾)的表示。

我會是這樣的:

pthread_t[INITIAL_SIZE] thread_pool; 
boolean[INITIAL_SIZE] threads_availability; 
int first_available = 0; 

pthread_t * get_thread() { 
    int ind = 0; 
    if (first_available<=INITIAL_SIZE) { 
     ind = first_available; 
     // find the next available spot 
     for (first_available; first_available < INITIAL_SIZE && threads_availability[first_available]; first_available++); 
     threads_availability[ind] = 0; 

     return thread_pool[ind]; 
    } 
} 

void put_thread(pthread_t* thethread) 
{ 
    int i = 0; 
    pthread_t *it = thread_pool; 
    while (!pthread_equals(it, thethread)) { 
     it++; 
     i++; 
    } 
    thread_availability[i] = 1; 
} 

請記住,這是僞代碼,這是不是最佳的。 但這是一個想法。

+0

雖然在將一個使用過的物品放入另一個容器中存在一些開銷,但對於較大的池,此解決方案可能會相當昂貴。 – stefaanv

1

如果您仍然需要訪問您從池中傳出的內容,則應將這些項目存儲在「已用」容器中。
然而,在那一刻,你分享你的指針,所以你應該使用的shared_ptr,並傳遞出的weak_ptr,所以線程也可以刪除,用戶沒有懸空指針

的最佳cointainer使用的項目將是一個集合,因此返回的線程可以很容易地找到並移除。

0

這不是您的問題的直接答案,因爲其他人已經回答了您的原始問題。

我只是想說你可以看看boost :: asio和/或boost :: thread。 我可能會去boost :: asio,因爲它擁有基於定時器和whatnot進行異步操作所需的一切。你可以使用shared_ptr和boost :: enable_shared_from_this來讓你的「工作」完成並在他們完成工作時自動銷燬。

例子:

boost::shared_ptr<async_job> aj(new async_job(
    io_, boost::bind(&my_job::handle_completion, shared_from_this(), _1, _2))); 

此代碼將在一個線程池執行您的自定義async_job(io_是提高:: ASIO :: io_service對象)。當async_job完成並調用handle_completion時,您的'my_job'實例將自動銷燬。或者,如果您在handle_completion中再次使用shared_from_this(),則可以讓它生存。

HTH, 亞歷