The description of AutoResetEvent in MSDNLinux下AutoResetEvent的C++等價物是什麼?
我試圖將在C#中實現的線程池移植到Linux下的C++。我不知道我應該使用哪些功能與「AutoResetEvent」具有相似的行爲。
The description of AutoResetEvent in MSDNLinux下AutoResetEvent的C++等價物是什麼?
我試圖將在C#中實現的線程池移植到Linux下的C++。我不知道我應該使用哪些功能與「AutoResetEvent」具有相似的行爲。
的的AutoResetEvent是最類似於一個二進制信號。說「條件變量」的人本身並沒有錯,但條件變量在相似的情況下使用,而不是類似的對象。您可以實現條件變量之上的(未命名)的AutoResetEvent:
#include <pthread.h>
#include <stdio.h>
class AutoResetEvent
{
public:
explicit AutoResetEvent(bool initial = false);
~AutoResetEvent();
void Set();
void Reset();
bool WaitOne();
private:
AutoResetEvent(const AutoResetEvent&);
AutoResetEvent& operator=(const AutoResetEvent&); // non-copyable
bool flag_;
pthread_mutex_t protect_;
pthread_cond_t signal_;
};
AutoResetEvent::AutoResetEvent(bool initial)
: flag_(initial)
{
pthread_mutex_init(&protect_, NULL);
pthread_cond_init(&signal_, NULL);
}
void AutoResetEvent::Set()
{
pthread_mutex_lock(&protect_);
flag_ = true;
pthread_mutex_unlock(&protect_);
pthread_cond_signal(&signal_);
}
void AutoResetEvent::Reset()
{
pthread_mutex_lock(&protect_);
flag_ = false;
pthread_mutex_unlock(&protect_);
}
bool AutoResetEvent::WaitOne()
{
pthread_mutex_lock(&protect_);
while(!flag_) // prevent spurious wakeups from doing harm
pthread_cond_wait(&signal_, &protect_);
flag_ = false; // waiting resets the flag
pthread_mutex_unlock(&protect_);
return true;
}
AutoResetEvent::~AutoResetEvent()
{
pthread_mutex_destroy(&protect_);
pthread_cond_destroy(&signal_);
}
AutoResetEvent event;
void *otherthread(void *)
{
event.WaitOne();
printf("Hello from other thread!\n");
return NULL;
}
int main()
{
pthread_t h;
pthread_create(&h, NULL, &otherthread, NULL);
printf("Hello from the first thread\n");
event.Set();
pthread_join(h, NULL);
return 0;
}
但是,如果你需要一個名爲自動復位的事件,你可能會想看看信號燈,並可能有一個稍微困難的時候翻譯你的代碼。無論哪種方式,我會仔細看看你的平臺上的pthreads的文檔,條件變量和自動重置事件是不一樣的,並且行爲不一樣。
好吧,它最像是一個互斥體 - 你有一些調用者用於共享資源,但只允許一個調用。在互斥體情況下,調用者會嘗試獲取互斥體(例如phtread_mutex_lock) ,做好自己的事情,然後鬆開(調用pthread_mutex_unlock),以便其他一些來電者就可以得到。
我敢肯定你要找的條件變量。對其他SO問題的接受答案:Condition variables in C# - 似乎證實了這一點。
參見例如有關POSIX線程中條件變量的詳細信息,請參閱this tutorial。
微軟喜歡將「庫」,「平臺」和「語言」之間的差異模糊爲一個強迫你「購買微軟」的大混亂。事實上,.Net中的「AutoResetEvent」類是Win32中的「Event」原語的封裝,類似於PThread中的「條件變量」。學習Linux的PThreads。除了Linux之外,PThread還可以用於其他平臺上,除了C++之外,還可以與其他語言(C,Python等)一起使用。 – paulsm4
只是想知道,使用boost:線程庫實現它會更容易嗎? – derekhh
@derekhh:我不知道「更容易」,條件變量是一個相當簡單的構造,但是如果你已經使用boost :: thread(IMO是一個非常好的選擇),通過一切手段使用它的條件變量它將適合您的代碼的其餘部分:http://www.boost.org/doc/libs/1_47_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref –
您可以輕鬆地重新實現使用POSIX互斥和條件變量的Win32 API的事件對象。
但是一些評論上面讓我說明這一點:
條件變量是沒有類似一個事件對象。條件變量是根本從事件,因爲它沒有記憶或狀態,在這個意義上,如果沒有人擋在當時調用條件變量pthread_cond_signal
或pthread_cond_broadcast
什麼都不會發生,特別是不同的如果一個線程後來通過pthread_cond_wait
來阻止它將阻止塊。
I'l嘗試繪製一個快速的自動重置事件的實現:
class event
{
public:
event(): signalled_ (false) {}
void signal()
{
std::unique_lock<std::mutex> lock(mutex_);
signalled_ = true;
cond_.notify_one();
}
void wait()
{
std::unique_lock<std::mutex> lock(mutex_);
while (!signalled_)
cond_.wait (lock);
signalled_ = false;
}
protected:
std::mutex mutex_;
std::condition_variable cond_;
bool signalled_;
};
條件變量不的AutoResetEvent的等價物。他們相當於顯示器。所不同的是關鍵的,並且如果不正確使用會導致死鎖:
在C#程序想象兩個線程A和B. A調用WaitOne()和B調用Set()。如果B在A到達對WaitOne()的調用之前執行Set(),則沒有問題,因爲Set()發送給AutoResetEvent()的信號是持久的,並且它將保持設置狀態直到執行WaitOne()。
現在,在C,想像兩個線程C和D. C調用wait()的,d調用notify()。如果C在D調用notify()時已經在等待一切正常。如果C在D調用notify()之前沒有設法達到wait(),那麼會發生死鎖,因爲如果沒有人等待它,並且條件變量的狀態仍「未設置」,則信號丟失。
請注意這一點。
從Boost的主題/條件文檔的例子是非常相似的正常的ManualResetEvent和的AutoResetEvent用法: http://www.boost.org/doc/libs/1_53_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref
(我做了清晰一些小的修改)
boost::condition_variable cond;
boost::mutex mut;
bool data_ready;
void wait_for_data_to_process()
{
boost::unique_lock<boost::mutex> lock(mut);
while(!data_ready)
{
cond.wait(lock);
}
}
void prepare_data_for_processing()
{
{ //scope for lock_guard
boost::lock_guard<boost::mutex> lock(mut);
data_ready=true;
}
cond.notify_one();
}
注意條件提供AutoResetEvent和ManualResetEvent的等待/通知機制,但需要互斥體才能工作。
不,它根本不像一個互斥體。這更像是一個條件變量。 – Gabe