Search code examples
c++cwinapicustom-events

Can two different processes communicate with each other using Windows events in WINAPI?


I am in the midst of developing two applications that communicate using a file. These applications are running on the same machine. To be clear, I have a writer.exe and a reader.exe executables.

The writer.exe constantly writes a random integer to a common file "some_file.bin" and closes the file. It repeats the same process again: opens the file, writes random int and closes it. This is done in a while loop.

The reader.exe is constantly reading the file "some_file.bin", printing the read integer to its console.

Both of these applications are written in C++ using the std::fstream class for file I/O.

So far, this is not working properly, because we have a race condition happening here.

I want some way to properly communicate between these two processes, using Win32 Events, so that the writer.exe process knows to wait until the reader.exe process has finished reading, and the reader.exe process knows to pause until the writer.exe process has finished writing.

I'm hoping to do this using the CreateEvent, WaitForSingleObject family of API calls present natively on the Windows platform.

Please feel free to tell me if this is possible between two processes?

So far, I have only found examples using the above APIs to signal threads of one main process... ?


Solution

  • 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.