5

I need an IPC in my application. I'v tried socket, but its speed is not fast enough. Hence, I use shared memory to do that. To synchronize the communication, I use a flag in the memory and check it in a while-loop. It works, but the polling is time consuming which make it slower than the solution of socket. The implementation of shared memory in my code is shoom. I want to do that on both Windows and Mac, and I'm currently testing on Windows. The complete code is like:

Server:

#include "include/shoom.h"
#include <stdio.h>
#include <thread>

typedef struct _packet_ {
    uint8_t flag;
    int data;
} _packet;

int main()
{
    int data;
    _packet* ptr;
    shoom::Shm server("test", sizeof(_packet));

    if (server.Create() == shoom::kOK)
    {
        ptr = (_packet*)server.Data();

        while (1)
        {
            while (!ptr->flag)
            {
                std::this_thread::sleep_for(std::chrono::microseconds(100));
            }

            data = ptr->data;
            ptr->flag = 0;

            printf("%d\n", data);
        }
    }

    return 0;
}

Client:

#include "include/shoom.h"
#include <stdio.h>
#include <chrono>
#include <thread>

typedef struct _packet_ {
    uint8_t flag;
    int data;
} _packet;

int main()
{
    std::chrono::system_clock::time_point ts, te;
    double t;

    _packet* ptr;
    
    int data;

    shoom::Shm client("test", sizeof(_packet));

    if (client.Open() == shoom::kOK)
    {
        ptr = (_packet*)client.Data();

        for (data = 1; data <= 100; data++)
        {
            
            ptr->flag = 1;
            memcpy(&ptr->data, &data, sizeof(data));
            
            ts = std::chrono::system_clock::now();

            while (ptr->flag)
            {
                std::this_thread::sleep_for(std::chrono::microseconds(100));
            }

            te = std::chrono::system_clock::now();
            t = (double)std::chrono::duration_cast<std::chrono::microseconds>(te - ts).count();

            printf("%lf\n", t);
        }
    }

    return 0;
}

The bottleneck is the while-loop. No matter how long the sleep time is (< 1ms), the time cost of the while-loop is about 30ms. I've checked the loop count is less than 3.

Is there any better solution? like condition variable for threading.

  • 1
    There are IPC variants of mutexes and semaphores in POSIX, perhaps you can try them? [One can place mutex directly into the shared memory](https://stackoverflow.com/questions/42628949/using-pthread-mutex-shared-between-processes-correctly). – Quimby Jan 18 '22 at 09:57
  • 1
    As far as I know, ISO C++ itself has not IPC functionality. Therefore, you are probably looking for a platform-specific solution. In that case, please specify which platform your question applies to (e.g. POSIX, Linux, BSD), by tagging the question appropriately. – Andreas Wenzel Jan 18 '22 at 10:01
  • I suggest you add a few specifics, because any solution will be system/host dependent. In general terms, you need some form of synchronisation primitives, akin to a mutex or semaphore rather than using a waiting loop. But standard C++ does not specify if such synchronisation primitives are system-wide or specific to one process, so the choice there will depend on your host (e.g. posix/windows/other), whether the two processes are on the same host or different hosts or processors on a host, etc. – Peter Jan 18 '22 at 10:02
  • Is there a clear client/server setup? If so you could let the server write in its own memory and then let a client call an rpc function that will copy the current state to shared memory where it can read. I've also done solutions where there are many chunks in shared memory and then make rpc calls to basically ask for read access/release for smaller chunks. That way you have short calls to but still direct access to shared memory. – Pepijn Kramer Jan 18 '22 at 10:24
  • Thank you all. I post the complete code. Please have a look. – Chun-Hsien Lin Jan 18 '22 at 11:36
  • On MS-Windows I assume `std::chrono::microseconds(100)` will eventually call [::Sleep](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep) _"...This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds. The system clock "ticks" at a constant rate. If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time. ..."_ – Richard Critten Jan 18 '22 at 11:55

0 Answers0