跨平台等同于Windows事件

Fir*_*cer 23 c++ windows multithreading boost cross-platform

我正在尝试将一些Windows代码移植到Linux,理想情况是通过独立于平台的库(例如boost),但是我不知道如何移植这些事件代码.

代码位涉及两个线程(让我们称之为A和B).A想要做只有B可以做的事情,所以它向B发送消息,然后等待B说出它完成了.在Windows中,这看起来像:

void foo();//thread a calls this
void bar(HANDLE evt);

void foo()
{
    HANDLE evt = CreateEvent(0,FALSE,FALSE,0);
    bCall(boost::bind(&bar, evt));
    WaitForSingleObject(evt,INFINITE);
    CloseHandle(evt);
}
void bar(HANDLE evt)
{
    doSomething();
    SetEvent(evt);
}
Run Code Online (Sandbox Code Playgroud)

我查看了boost :: thread库,但它似乎没有任何东西可以做到这一点,我可以看到的关闭是boost :: condition_variable,但看起来这意味着与一个互斥量一起使用,但事实并非如此这里.

def*_*ode 15

所有这些答案都太复杂了,对人们来说并不是那么难.

namespace porting
{
   class Event;
   typedef Event* Event_handle;
   static const unsigned k_INFINITE = 0xFFFFFFFF;

   class Event
   {
      friend Event_handle CreateEvent( void );
      friend void CloseHandle( Event_handle evt );
      friend void SetEvent( Event_handle evt );
      friend void WaitForSingleObject( Event_handle evt, unsigned timeout );

      Event( void ) : m_bool(false) { }

      bool m_bool;
      boost::mutex m_mutex;
      boost::condition m_condition;
   };

   Event_handle CreateEvent( void )
   { return new Event; }

   void CloseHandle( Event_handle evt )
   { delete evt; }

   void SetEvent( Event_handle evt )
   {
      evt->m_bool = true;
      evt->m_cond.notify_all();
   }

   void WaitForSingleObject( Event_handle evt, unsigned timeout )
   {
      boost::scoped_lock lock( evt->m_mutex );
      if( timeout == k_INFINITE )
      {
         while( !evt->m_bool )
         {
            evt->m_cond.wait( lock );
         }
      }
      else
      {
         //slightly more complex code for timeouts
      }
   }

}// porting

void foo()
{
   porting::Event_handle evt = porting::CreateEvent();
   bCall( boost::bind(&bar, evt ) );
   porting::WaitForSingleObject( evt, porting::k_INFINITE );
   porting::CloseHandle(evt);
}

void bar( porting::Event_handle evt )
{
   doSomething();
   porting::SetEvent(evt);
}
Run Code Online (Sandbox Code Playgroud)

由于我不熟悉语义WaitForSingleObject(如果两个线程同时调用它会发生什么,如果同一个线程调用它两次会发生什么),可能需要做更多工作才能完全正常工作.但是,解决方案看起来非常像这样.


Ala*_*lan 10

我认为一个好的,跨平台的win32事件等同于boost :: condition,所以你的代码看起来像这样:

void foo()
{
    boost::mutex mtxWait; 
    boost::condition cndSignal;

    bCall(boost::bind(&bar, mtxWait, cndSignal));

    boost::mutex::scoped_lock mtxWaitLock(mtxWait);
    cndSignal.wait(mtxWait); // you could also use cndSignal.timed_wait() here
}

void bar(boost::mutex& mtxWait, boost::condition& cndSignal)
{
    doSomething();
    cndSignal.notify_one();
}
Run Code Online (Sandbox Code Playgroud)

  • 这有两个主要问题: 1. 启动工作线程和在条件中调用 wait 之间存在竞争条件。如果线程启动得非常快,则可以在等待和主线程挂起之前调用notify_one。2. 使用堆栈变量可能会导致崩溃,因为从 foo() 退出会释放条件,并且它可能仍在 notify_one 调用中使用。所提出的屏障解决方案实际上更安全——即使它可能被认为是矫枉过正。 (2认同)

小智 8

你可以使用一个承诺和未来,来自boost线程:

#include <boost\thread.hpp>

boost::promise<bool> prom;

void foo()
{
    auto future = prom.get_future();
    auto result = future.wait_for(boost::chrono::milliseconds(1000));
    // we get here if (a) 1 second passes or (b) bar sets the promise value
    if (result==boost::future_status::ready) 
    { 
        /* bar set the promise value */ 
    }
    if (result==boost::future_status::timeout)
    {
        /* 1 second passed without bar setting promise value */ 
    }
}

void bar()
{
    prom.set_value(true);
}
Run Code Online (Sandbox Code Playgroud)