簡體   English   中英

Linux下的AutoResetEvent的C ++等價物是什么?

[英]What is the C++ equivalent for AutoResetEvent under Linux?

MSDN中AutoResetEvent的說明

我正在嘗試將在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的文檔,條件變量和自動重置事件不一樣,並且行為不一樣。

我很確定你在尋找條件變量。 對於另一個SO問題的接受答案: C#中的條件變量 - 似乎證實了這一點。

有關POSIX線程中條件變量的詳細信息,請參閱本教程

您可以使用POSIX互斥鎖和條件變量輕松地重新實現Win32 API事件對象。

但是上面的一些評論讓我說明了這一點:

條件變量 Event對象不相似 條件變量與事件根本不同,因為它沒有內存或狀態,在某種意義上說,如果在調用pthread_cond_signalpthread_cond_broadcast時沒有任何人在條件變量處被阻塞,則不會發生任何事情,特別是如果線程后來通過pthread_cond_wait阻塞它阻塞。

我嘗試繪制一個快速自動重置事件實現:

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_;
};

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的等待/通知機制,但需要互斥鎖才能工作。

條件變量等同於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(),則會出現死鎖,因為如果沒有人在等待它並且條件變量的狀態仍然是“未設置”,則信號會丟失。

對此要非常小心。

我知道派對可能有點晚了,我沒有關於性能差異的信息,但是使用組合pthread_kill和sigwait可能是一個可行的替代方案,如下所示:

在適當的情況下聲明以下內容:

int sigin;
sigset_t sigset;

以下列方式初始化以前的變量:

sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &sigset, null);

在等待線程中,調用sigwait:

sigwait(&sigset, &sigin);

然后,在應該喚醒等待線程的線程上,您可以這樣做:

pthread_kill(p_handle, SIGUSR1);

其中p_handle是您要取消阻止的線程的句柄。

此示例阻止等待線程,直到交付SIGUSR1。 由於使用了pthread_kill,信號只到達該特定線程。

好吧,可能性最像是一個互斥體 - 你有一些呼叫者要使用共享資源,但只允許一個。在互斥鎖的情況下,調用者會嘗試獲取互斥鎖(例如phtread_mutex_lock),做他們的事情,然后釋放(pthread_mutex_unlock),以便其他一些調用者可以進入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM