2013-06-03 64 views
3

我重寫了使用WinAPI進行線程化以使用新的標準線程庫的代碼。在C++ 11線程中等效的WAIT_ABANDONED

我想知道什麼是C++ 11中的等效方式,以注意互斥體被遺棄或丟失。

以下代碼必須將初始化過程「外包」到創建的線程,但在完成並知道初始化結果之前不應返回。

bool Foo::Example() 
{ 
    m_thread = std::thread(&Foo::ThreadProc, this); 

    // wait for event before waiting for mutex 
    WaitForSingleObject(m_hEvent, INFINITE); 
    ResetEvent(m_hEvent); 

    // the thread aquired the mutex. now wait until it is released or abandoned 
    DWORD ret = WaitForSingleObject(m_hMutex, INFINITE); 
    ReleaseMutex(m_hMutex); 

    // check the result 
    if (ret == WAIT_ABANDONED) 
     return false; 
    return true; 
} 
void Foo::ThreadProc() 
{ 
    // aquire mutex and signal that it's done 
    WaitForSingleObject(m_hMutex, INFINITE); 
    SetEvent(m_hEvent); 

    // ... initialization (required to be in this thread) 

    if (initializationfailure) 
     return; // failure. mutex is abandoned 

    // success. mutex is unlocked 
    ReleaseMutex(m_hMutex); 

    // ... do the work 
} 

什麼是WAIT_ABANDONED檢查的替代?我沒有在std :: mutex中找到任何東西。它甚至說The behavior is undefined if the mutex is not unlocked before being destroyed, i.e. some thread still owns it.有沒有相當的?任何在std線程庫接近這個?

我還提出了改進代碼的建議。對於這樣一個簡單的任務似乎太多同步。

+2

在**標準**中沒有相應的內容(從引用的措詞中應該很清楚)。也就是說,你無法做到這一點。某種特定的實現可能會提供對這個特性的支持,*某種方式*,但是最終的程序會在「未定義行爲」的土地上,一旦你有什麼事情發生。 –

+3

有意使用WAIT_ABANDONED是一個很糟糕的錯誤,它應該始終保留以指示代碼中嚴重的線程錯誤。如果你使用std :: mutex的Microsoft實現,那麼你會得到完全不同的東西,它不使用操作系統互斥。它建立在ConcRT庫的頂部。它從頭開始重新實現同步原語。當std :: mutex對象被刪除並且仍然持有一個鎖時,你會得到一個斷言。只有在調試版本中,發佈版本中的無提示失敗。 –

回答

7

沒有等價物。您可以使用RAII解鎖互斥鎖,並避免首先放棄互斥鎖,然後您無需對其進行測試。

你可以使用,而不是等待一個事件,並使用一個互斥體,這使得它遠遠超過易出錯的顯式同步簡單的未來:

bool Foo::Example() 
{ 
    std::promise<bool> p; 
    auto res = p.get_future(); 
    m_thread = std::thread(&Foo::ThreadProc, this, std::ref(p)); 
    return res.get(); 
} 
void Foo::ThreadProc(std::promise<bool>& p) 
{ 
    // ... initialization (required to be in this thread) 

    if (initializationfailure) 
    { 
     p.set_value(false); // failure. 
     return; 
    } 

    p.set_value(true); 

    // IMPORTANT: p is a dangling reference now! 

    // ... do the work 
} 

主線程將被阻塞,直到承諾的兌現,然後根據初始化是否工作返回true或false。

你可以通過使ThreadProc(std::promise<bool> p)避免懸空引用,然後把它作爲std::move(p)而不是std::ref(p),但我不認爲std::thread在Visual C++支持的舉動,只是類型的完美轉發。

+0

謝謝。這並不能真正解決問題。我需要等待初始化,但同時信號成功或失敗。 – typ1232

+2

@ typ1232,我添加了一個替代方案,比依靠廢棄的互斥體更簡單 –

+5

@ typ1232:如果您需要表示成功或失敗,則只需使用額外的變量即可。你應該*不*使用被遺棄的而不是被遺棄的來傳達程序狀態。 「WAIT_ABANDONED」狀態是一個「哦,糟糕的是,一些事情變得非常糟糕,*可怕*錯誤,現在更好的是儘快救助」標誌,而不是在正常的程序操作中應該發生的事情。 –