Cross-Platform equivalent to windows events
I think a good, cross-platform equivalent to win32 events is boost::condition, so your code could look something like this:
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();
}
Replacement for Windows specific HANDLE, Event Creation and Sync API in case of Linux
The replacement for CreateEvent is eventfd, you probably want EFD_CLOEXEC
and EFD_NONBLOCK
flags. Don’t use the semaphore flag unless you know what you’re doing.
The replacement for WaitForMultipleObjects is poll, specify the POLLIN
flag in the requested events. Just keep in mind the event is not being reset by poll, it will stay signalled. Read 8 bytes from the eventfd handle to reset. The functionality is identical to manual-reset events on Windows.
To signal an event, call write on the eventfd
handle, passing the address of a local uint64_t
variable with value 1.
To destroy events once you no longer need them, just call close.
Update: I’ve just noticed you’re passing bWaitAll=TRUE
to WaitForMultipleObjects
.
Unfortunately, Linux poll can’t quite do that. It returns when timeout is expired, or when at least 1 handle becomes signaled, whichever happens first.
Still, the workaround is not too hard. You can emulate bWaitAll
by calling poll multiple times in a loop until all of the events are signaled. No need to rebuild the array of handles, you can set file handle to a negative value for the events which became signaled after poll returned. Note that multiple of them may become signaled at once, poll return value tells how many of them did. Also don't forget to decrease the timeout value.
Is there a C++ cross platform named event like the CreateEvent() in Win32?
There is no built in way in C++ to do named events. But you can use boost to do it.
You're looking for boost::condition and boost::named_condition
As you also mentioned there exists: Poco.NamedEvent
Boost Equivalent for Windows Events
I think you need to use boost::mutex
, boost::unique_lock
, boost::condition_variable
and possibly bool
in order to imitate Events.
You actually might need sort of WaitForSingleObject
in order to wait for an event. Might be like this:
void wait_for_user_input()
{
boost::unique_lock<boost::mutex> lock(mut);
while(!data_ready)
{
cond.wait(lock);
}
process_user_input(); // it might be not necessary to hold mutex locked here!!!
// if so just add curly braces like this:
// void wait_for_user_input()
// {
// {
// boost::unique_lock<boost::mutex> lock(mut);
// while(!data_ready) { cond.wait(lock); }
// }
// process_user_input();
// }
}
Can two different processes communicate with each other using Windows events in WINAPI?
Yes, it is possible. When one process creates a handle to an Event object, you have the option of assigning a name to that object in the kernel. The other process can then create/open its own handle to that Event object using the same name.
Note that to accomplish what you want, you actually would need 2 Events, eg:
writer.exe:
HANDLE hReadable = CreateEvent(NULL, FALSE, FALSE, TEXT("ReaderCanRead"));
if (!hReadable) ...
HANDLE hWritable = CreateEvent(NULL, FALSE, TRUE, TEXT("WriterCanWrite"));
if (!hWritable) ...
...
while (!quit)
{
...
WaitForSingleObject(hWritable, INFINITE);
if (quit) break;
// write int...
SetEvent(hReadable);
...
}
reader.exe:
HANDLE hReadable = CreateEvent(NULL, FALSE, FALSE, TEXT("ReaderCanRead"));
// or: HANDLE hReadable = OpenEvent(SYNCHRONIZE, FALSE, TEXT("ReaderCanRead"));
if (!hReadable) ...
HANDLE hWritable = CreateEvent(NULL, FALSE, TRUE, TEXT("WriterCanWrite"));
// or: HANDLE hWritable = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("WriterCanWrite"));
if (!hWritable) ...
...
while (!quit)
{
...
WaitForSingleObject(hReadable, INFINITE);
if (quit) break;
// read int...
SetEvent(hWritable);
...
}
That being said, you might consider using a named block of shared memory via CreateFileMapping()
+MapViewOfFile()
, rather than using a physical file.
However, there are many other Inter-Process Communication mechanisms that are way more suitable to your producer/consumer model than using a shared file/memory protected by Events. Pipes, sockets, mailslots, even window messages, would be a much better choice.
Is there a UNIX/pthreads equivalent to Windows manual reset events?
It's Linux-only (I only mention it because you have a "linux" tag), but I think you could build something like this on the futex
syscall. See Ulrich Drepper's paper on Futexes for the gory details.
Very roughly, I envisage something along the lines of
void inline gate_wait(volatile int *gate)
{
if (*gate)
while (futex(gate, FUTEX_WAIT, 1, 0, 0, 0) == EINTR)
;
}
int inline gate_open(volatile int *gate)
{
*gate = 0;
return futex(gate, FUTEX_WAKE, INT_MAX, 0, 0, 0);
}
void inline gate_close(volatile int *gate)
{
*gate = 1;
}
If you do build this "gate" synchronisation primitive on top of futexes, it might be worth contributing it to Rusty Russell's userspace futex library.
Related Topics
Getting the Current Time (In Milliseconds) from the System Clock in Windows
Proper Way of Casting Pointer Types
C++ Cannot Convert from Base a to Derived Type B via Virtual Base A
Simple 3X3 Matrix Inverse Code (C++)
Function Template with an Operator
Overload Resolution and Arrays: Which Function Should Be Called
Using Opengl Glutdisplayfunc Within Class
C++ Object Instantiation VS Assignment
How to Handle or Avoid a Stack Overflow in C++
How to Perform a Pairwise Binary Operation Between the Elements of Two Containers
Why Gcc Does Not Use Load(Without Fence) and Store+Sfence for Sequential Consistency
C++ Const Keyword - Use Liberally
How to Use Makefiles in Visual Studio
How to Call a Template Member Function
When Do We Need to Have a Default Constructor