I'm trying to write (in Linux), a "Sender" and "Receiver" programs that can send/receive a few types of messages between them, using shared memory, and message_queue. I decided to use boost/interprocess/ipc/message_queue as it looks like the best solution.
The problem is that since there are a few types of messages with different structures and sizes, the receiver cannot know how many bytes to receive() and how they are structured.
I can solve this by placing the "type enumerator" as the first field, and upon reading the type, the receiver knows what is the size and how to parse the message to be read.
mq.receive(&type, sizeof(type), recvd_size, priority);
switch (type) {
case typeA:
mq.receive(&VarOfStructA, sizeof(struct A), recvd_size, priority);
break;
case typeB:
mq.receive(&VarOfStructB, sizeof(struct B), recvd_size, priority);
break;
default:
break;
}
I tried to search for solutions, as I assume this is a common problem. However, I couldn't find any helpful idea.
Since c++17 you can use
std::variantfor a tagged union and if c++17 is not an option for you, then pickboost::variantas you are already using boost.Here is an example how to use a variant to send and receive messages between two processes or even over network. I used
conceptswhich is available since c++20 to produce better error messages but you can do without them.I didn't include the serialization part because this is per application requirement. Also the compiler compiles this better than a hand written switch statement in some cases and I think at worst it will be identical to a switch or if. In the write method an exception will be thrown in
std::visitif the variant isvalueless_by_exceptionand in the read method an exception will be thrown if the index is not contained in the variant.code and asm result on godbolt: https://godbolt.org/z/f4bM51x8E