0

I am trying to figure out a good naming scheme for Boost Interprocess message_queue's. Suppose there is a group of processes all using the same queue. There may be multiple simultaneous 'runs' of this group of processes. I assume it is required for each run to use a unique name per queue that is used amongst the group of processes. The following prototype code sends a bunch of messages to a server process that reads the messages from a queue and then prints them:

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/interprocess/ipc/message_queue.hpp>
#include <boost/serialization/string.hpp>

#include <iostream>
#include <vector>

#include <unistd.h>

namespace ipc = boost::interprocess;

constexpr unsigned messages{1000000};
constexpr unsigned maxMessageSize{8192};

struct Message
{
  std::string prefix;

  template<typename Archive>
  void serialize(Archive& ar, const unsigned int)
  {
    // clang-format off
    ar & prefix;
    // clang-format on
  }
};

int loggerServerMain()
{
  try
  {
    // Open a message queue.
    ipc::message_queue mq(ipc::open_only, "message_queue");

    unsigned int priority;
    ipc::message_queue::size_type recvd_size;

    for (int i = 0; i < messages; ++i)
    {
      std::string data;
      data.resize(maxMessageSize);

      mq.receive(&data[0], maxMessageSize, recvd_size, priority);
      if (recvd_size > maxMessageSize)
        return 1;

      std::istringstream iss{data};
      boost::archive::binary_iarchive ia{iss};

      Message message;
      ia >> message;

      std::cout << message.prefix << '\n';
    }
  }
  catch (const ipc::interprocess_exception& ex)
  {
    std::cout << ex.what() << std::endl;
    return 1;
  }
  ipc::message_queue::remove("message_queue");
  return 0;
}

int main()
{
  try
  {
    ipc::message_queue::remove("message_queue");
    ipc::message_queue mq(ipc::create_only, "message_queue", 100, maxMessageSize);

    if (fork() == 0)
    {
      exit(loggerServerMain());
    }

    for (int i = 0; i < messages; ++i)
    {
      Message message{"lib" + std::to_string(i)};

      std::ostringstream oss;
      boost::archive::binary_oarchive oa{oss};
      oa << message;

      std::string data{oss.str()};
      mq.send(data.data(), data.size(), 0);
    }
  }
  catch (const ipc::interprocess_exception& ex)
  {
    std::cout << ex.what() << std::endl;
    return 1;
  }

  return 0;
}

So we have a process that forks a server, then proceeds to send a whole bunch of messages to the server which in turn will print the messages. We use a hardcoded name 'message_queue' for the name of the underlying message queue.

I was surprised to find out that this example still works when multiple instances of this process are started simultaneously, for example as follows:

./message_queue > 1.log & ; sleep 1 ; ./message_queue > 2.log

Both logs contain all messages, in the right order. The first instance of message_queue still runs when the second one is started. Both logs are created and written to simultaneously.

How can it be that there is no contention over the message queue when used from more process 'groups' simultaneously? I assumed the name of the message queue is some global defined at the system level, but from my example it seems this is defined per process tree somehow? I digged through the documentation of Boost Interprocess but could not find any mention of this.

I am using Linux 4.20, GCC 8.1.0. The example code is compiled as follows:

g++ -std=c++17 -O3 -o message_queue message_queue.cpp -lpthread -lboost_serialization -lrt
Ton van den Heuvel
  • 10,157
  • 6
  • 43
  • 82
  • 1
    The first line of your program removes the existing queue and recreates it. I assume the first process you start already has internal handles to the shared memory and doesn’t need to refer to it by name. It prevents the shared memory from being completely released so it continues to function while the second one uses a brand new shared queue. – John Drouhard Jan 21 '19 at 15:30
  • @JohnDrouhard, makes sense, thanks. – Ton van den Heuvel Jan 22 '19 at 07:46

0 Answers0