windows 跨平台等价于windows事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1677070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cross-Platform equivalent to windows events
提问by Fire Lancer
I'm trying to port some Windows code to Linux, ideally through platform-independent libraries (eg boost), however I'm not sure how to port this bit of event code.
我正在尝试将一些 Windows 代码移植到 Linux,理想情况下是通过独立于平台的库(例如 boost),但是我不确定如何移植这部分事件代码。
The bit of code involves two threads (lets call them A and B). A wants to do something that only B can, so it sends B a message, then waits for B to say its done. In windows this looks something like:
这段代码涉及两个线程(我们称它们为 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);
}
I looked at the boost::thread library, but it didnt seem to have anything that does this, the closes I could see was the boost::condition_variable, but it appears that is means in conjunction with a mutex, which is not the case here.
我查看了 boost::thread 库,但它似乎没有执行此操作的任何内容,我可以看到的关闭是 boost::condition_variable,但似乎是与互斥锁结合使用的方法,但事实并非如此这里。
采纳答案by Alan
I think a good, cross-platform equivalent to win32 events is boost::condition, so your code could look something like this:
我认为与 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();
}
回答by deft_code
All these answers are too complex, come on people it isn't that hard.
所有这些答案都太复杂了,拜托,这并不难。
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);
}
There is probably a bit more to do to get this fully working as I'm not familiar with the semantics of WaitForSingleObject
(what happens if two threads call it at the same time, what happens if the same thread calls it twice). However, the solution will look very much like this.
由于我不熟悉WaitForSingleObject
(如果两个线程同时调用它会发生什么,如果同一个线程调用它两次会发生什么)的语义,可能需要做更多的工作才能使其完全正常工作。但是,解决方案看起来非常像这样。
回答by oofafu
You could use a promise and a future, from boost thread:
您可以使用来自 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);
}
回答by Massood Khaari
Since comments are closed for me, I had to post my comments to previous posts as an answer. But actually I'm not answering.
由于我的评论已关闭,我不得不将我的评论发布到以前的帖子中作为答案。但实际上我没有回答。
1)There's a problem with @Alan 's solution.
The sample code he provided works well. But it is different from Windows Events functionality. When a Windows Event object is set, any number ofsubsequent calls to WaitForSingleObject
immediately returns, showing that the object is in signaled state. But with boost's mutex
/condition
solution, bar()
has to notify the condition for every foo()
calls that need it. This makes situation a lot harder for 'cross-platform'ing Windows Event functionality. notify_all()
also can't help.
1)@Alan 的解决方案有问题。他提供的示例代码运行良好。但它与 Windows 事件功能不同。设置Windows 事件对象后,任何数量的后续调用都会WaitForSingleObject
立即返回,表明该对象处于信号状态。但是使用 boost's mutex
/condition
解决方案,bar()
必须为每个foo()
需要它的调用通知条件。这使得“跨平台”Windows 事件功能的情况变得更加困难。notify_all()
也帮不上忙。
Of course this is somehow solved in @deft_code's sample code by using a boolean variable. (Although it suffers itself from race condition problem. Consider if SetEvent(...)
is called dead after while(!evt->m_bool)
and before evt->m_cond.wait(lock)
from within a separate thread. A deadlock will occur. This can however be solved by using some race condition management techniques to make the two statements while()
and wait()
atomic.) But it has its own shortcoming:
当然,这是通过使用布尔变量在@deft_code 的示例代码中以某种方式解决的。(虽然它会遇到竞争条件问题。考虑一下 if在单独的线程中SetEvent(...)
调用 dead afterwhile(!evt->m_bool)
和 before evt->m_cond.wait(lock)
。会发生死锁。然而,这可以通过使用一些竞争条件管理技术来解决,使这两个语句while()
和wait()
原子性。)但它也有自己的缺点:
2)There's also a problem with @deft_code 's code in making use of boost mutex
/condition
/bool
combination:
2)还有在利用升压与@deft_code的代码中的问题mutex
/ condition
/bool
组合:
Event objects in Windows can be namedwhich enables them to be used for inter-process synchronizations. For example, process A can create a named event and set it like this: SetEvent(hFileIsReady)
. Afterward, whatever number of processeswaiting for this event to be set (thereby calling WaitForSingleObject(hFileIsReady)
) will immediately continue their normal execution until the event is again reset within process A by ResetEvent(hFileIsReady)
.
Windows 中的事件对象可以命名,这使它们能够用于进程间同步。例如,进程A可以创建一个命名的事件,并将其设置是这样的:SetEvent(hFileIsReady)
。之后,无论有多少进程等待设置此事件(从而调用WaitForSingleObject(hFileIsReady)
),都将立即继续正常执行,直到该事件在进程 A 中再次被重置ResetEvent(hFileIsReady)
。
But the combination mutex
/condition
/bool
can't afford such a functionality. Of course, we can use boost named_condition
and named_mutex
. However, what about the boolean variable which we have to check before waiting?
但组合mutex
/ condition
/bool
买不起这样的功能。当然,我们可以使用 boostnamed_condition
和named_mutex
。但是,我们在等待之前必须检查的布尔变量呢?
回答by Mahmoud Al-Qudsi
For anyone involved in or working on porting multi-threaded native Windows C/C++ code to Linux/Mac, we've authored an open source (MIT-licensed) librarythat implements both manual and auto-reset WIN32 events on top of pthreads, including a complete implementation of WaitForSingleObject
and WaitForMultipleObjects
, making it the only WFMO port I know of available on Linux/Mac.
对于参与或致力于将多线程原生 Windows C/C++ 代码移植到 Linux/Mac 的任何人,我们编写了一个开源(MIT 许可)库,它在 pthread 之上实现手动和自动重置 WIN32 事件,包括一个完整的实施WaitForSingleObject
和WaitForMultipleObjects
,使之成为我所知道的唯一可用的WFMO端口在Linux / Mac上。
pevents is available on GitHuband has been fairly battle-tested and is in use by some big names; there is also a boost port of pevents floating around somewhere.
pevents可在 GitHub 上获得,并且已经过相当的实战测试,并被一些大牌使用;还有一个漂浮在某处的 pevents 增强端口。
Using pevents will make porting code from Windows significantly easier as the underlying paradigms are dramatically different between Windows and posix platforms - though I'd encourage anyone writing multi-platform code to use an existing cross-platform multithreading library like boost in the first place.
使用 pevents 将使从 Windows 移植代码变得更加容易,因为 Windows 和 posix 平台之间的底层范例有很大的不同——尽管我鼓励任何编写多平台代码的人首先使用现有的跨平台多线程库,比如 boost。
回答by chub
you can use boost thread barrier
您可以使用 boost 线程屏障
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <iostream>
void foo(boost::barrier* b)
{
std::cout << "foo done" << std::endl;
b->wait();
}
int main()
{
std::cout << "start foo" << std::endl;
boost::barrier b(2);
boost::thread t(&foo, &b);
b.wait();
std::cout << "after foo done" << std::endl;
t.join();
}
回答by Michael Kohne
I've done (or seen) all of the following at various times for things like this:
对于这样的事情,我已经在不同时间完成(或看到)以下所有内容:
Use a mutex + a condition variable.
使用互斥量 + 条件变量。
Use a pipe, having foo create the pipe and pass the write end of it to bar. Bar then writes into the pipe when bar is done. (This even works multi-process).
使用管道,让 foo 创建管道并将其写入端传递给 bar。当 bar 完成时,Bar 然后写入管道。(这甚至适用于多进程)。
Have foo poll on a boolean (yea, this is a bad idea.)
对布尔值进行 foo 轮询(是的,这是个坏主意。)
回答by bua
It looks like You're looking for signal-slot mechanizm. You can find one in:
看起来您正在寻找信号槽机制。您可以在以下位置找到:
both crossplatform.
两者都是跨平台的。
Qt example:
Qt 示例:
#include <QObject>
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int m_value;
};
Counter a, b;
QObject::connect(&a, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));
a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(value);
}
}
回答by Jean Davy
From Boost.Thread version 1.47 documentation:
来自 Boost.Thread 1.47 版文档:
The classes condition_variable and condition_variable_any provide a mechanism for one thread to wait for notification from another thread that a particular condition has become true.
类condition_variable 和condition_variable_any 为一个线程提供了一种机制,用于等待来自另一个线程的特定条件已变为真的通知。
回答by Elmar Weber
Under Posix compliant systems you can use Posix IPC. It is used for inter-process / inter-thread messaging. If I remember correctly there is a cygwin port available.
在 Posix 兼容系统下,您可以使用 Posix IPC。它用于进程间/线程间消息传递。如果我没记错的话,有一个 cygwin 端口可用。