2009-12-15 130 views
9

我知道,我知道,我的消息的標題可能看起來具有挑釁性,因爲 boost :: mutex有意義地不公開鎖定/解鎖(爲了避免死亡鎖)。boost :: mutex /如何測試一個互斥鎖是否被鎖定

但是這些方面的boost文檔很短(至少可以這麼說),所以我在問以下用例是否有人能幫助我。

假設你有一個類Foo,其中有:
- 析構函數,需要一些時間來完成
- 一個由獨特的線程調用的方法,但破壞過程中不應該叫

class Foo 
{ 
public: 

    virtual ~Foo() 
    { 
    //Time consuming operations here 
    } 


    //Method called by a timer belonging to a distinct class 
    void OnTimer() 
    { 
    //Other time consuming stuff. Should not be called during destruction ! 
    } 


}; 

我嘗試(沒有成功),以實現基於增強版本::互斥

//boost::mutex implementation 
class Foo 
{ 
public: 
    Foo() 
    { 
    } 

    virtual ~Foo() 
    { 
    { 
     boost::mutex::scoped_lock lock(mDisposingMutex); 
     //Time consuming operations here 
    } 
    } 


    //Method called by a timer belonging to a distinct class 
    void OnTimer() 
    { 
    { 
     //Imaginary code here: mutex::locked() method is private !!! 
     if (! mDisposingMutex.locked()) 
     return; 
    }  
    //Other time consuming stuff. Should not be called during destruction ! 
    } 

private: 
    boost::mutex mDisposingMutex; 
}; 

我完全錯了嗎?任何人都可以告訴我,這應該怎麼做與boost :: mutex?

謝謝!

+0

爲什麼被破壞你的對象,而另一個線程仍然有一個指針指向它? – 2009-12-15 01:38:28

+0

不直接回答問題,你可以取消註冊引發'OnTimer()'調用作爲你的析構函數的第一步嗎?誠然,呼叫仍然可以通過「同時」異步進行,但尚不清楚爲什麼此對象正在遭受破壞仍然是這些回調的目標。 – seh 2009-12-15 01:40:30

+0

@Anon:同意,這是一種代碼味道。儘管如此,我仍然對這個答案感興趣。 @ Seh:您的評論基於相同的代碼氣味。但是,我不能直接取消它,而不會破壞封裝。 – 2009-12-15 01:44:58

回答

5

如果您還承諾在析構函數體使用Lockable::lock(),你可以有你的OnTimer()功能使用Lockable::try_lock(),並繼續僅當函數返回true。如果OnTimer()首先啓動,但它仍然沒有解決析構函數運行,完成和釋放互斥鎖,然後OnTimer()啓動併成功地獲取互斥體的問題,將有OnTimer()擱置析構函數。

這樣的一個序列可能在未定義的行爲領域,但是這種詛咒不會阻止它發生。除了互斥體之外,使用狀態標記- 類似於我在上面的註釋中描述的 - 可以讓您檢測到後一種情況,並停止執行除標記之外的任何操作。然而,在某些時候,這只是將創可貼置於創可貼之上。

2

互斥:: try_lock()

+0

如果您是鎖定互斥鎖的人,則返回false。 – 2015-11-04 15:20:47

4

@ Seh:我完全同意這是一種代碼異味,我應該(也將會)糾正根本原因。

但是,爲了幫助任何遇到與我一樣的問題的人(即與boost文檔打架),我試圖實現您的建議。 現在下面的代碼編譯正確(儘管代碼味道是現在非常強)

#include <boost/thread/mutex.hpp> 

//boost::mutex implementation 
class Foo 
{ 
public: 
    Foo() : 
    mIsDisposing(false) 
    { 
    } 

    virtual ~Foo() 
    { 
    { 
     boost::try_mutex::scoped_try_lock lock(mDisposingMutex); 
     if (! lock.locked()) 
     { 
     //Die by horrible death, or wait before trying again... 
     } 
     else 
     { 
     mIsDisposing = true; 
     } 
     //Time consuming operations here 
    } 

    } 


    //Method called by a timer belonging to a distinct class 
    void OnTimer() 
    { 
    { 
     boost::try_mutex::scoped_try_lock lock(mDisposingMutex); 
     if (! lock.locked() || mIsDisposing) 
     { 
     return;  
     } 
    }  
    //Other time consuming stuff. Should not be called during destruction ! 
    } 

private: 
    boost::try_mutex mDisposingMutex; 
    bool mIsDisposing; 
};