Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Boost::asio, Shared Memory and Interprocess Communication

I have an application that is written to use boost::asio exclusively as its source of input data as most of our objects are network communication based. Due to some specific requirements, we now require the ability to use shared memory as an input method as well. I've already written the shared memory component and it is working relatively well.

The problem is how to handle notifications from the shared memory process to the consuming application that data is available to be read -- we need to handle the data in the existing input thread (using boost::asio), and we also need to not block that input thread waiting for data.

I've implemented this by introducing an intermediate thread that waits on events to be signaled from the shared memory provider process then posts a completion handler to the input thread to handle reading in the data.

This is working now also, but the introduction of the intermediate thread means that in a significant amount of cases we have an extra context switch before we can read the data which has a negative impact on latency, and the overhead of the additional thread is also relatively expensive.

Here's a simplistic example of what the application is doing:

#include <iostream>
using namespace std;

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/bind.hpp>

class simple_thread
{
public:
   simple_thread(const std::string& name)
      : name_(name)
   {}

   void start()
   {
      thread_.reset(new boost::thread(
         boost::bind(&simple_thread::run, this)));
   }

private:
   virtual void do_run() = 0;

   void run()
   {
      cout << "Started " << name_ << " thread as: " << thread_->get_id() << "\n";
      do_run();
   }


protected:
   boost::scoped_ptr<boost::thread> thread_;
   std::string name_;
};

class input_thread
   : public simple_thread
{
public:
   input_thread() : simple_thread("Input")
   {}

   boost::asio::io_service& svc()
   {
      return svc_;
   }

   void do_run()
   {
      boost::system::error_code e;
      boost::asio::io_service::work w(svc_);
      svc_.run(e);
   }

private:
   boost::asio::io_service svc_;
};

struct dot
{
   void operator()()
   {
      cout << '.';
   }
};

class interrupt_thread
   : public simple_thread
{
public:
   interrupt_thread(input_thread& input)
      : simple_thread("Interrupt")
      , input_(input)
   {}

   void do_run()
   {
      do
      {
         boost::this_thread::sleep(boost::posix_time::milliseconds(500));
         input_.svc().post(dot());
      }
      while(true);
   }

private:
   input_thread& input_;
};

int main()
{
   input_thread inp;
   interrupt_thread intr(inp);

   inp.start();
   intr.start();

   while(true)
   {
      Sleep(1000);
   }
}

Is there any way to get the data handled in the input_thread directly (without having to post it in via the interrupt_thread? The assumption is that the interrupt thread is totally driven by timings from an external application (notification that data is available via a semaphore). Also, assume that we have total control of both the consuming and providing applications, that we have additional objects that need to be handled by the input_thread object (so we cannot simply block and wait on the semaphore objects there). The goal is to reduce the overhead, CPU utilization and latency of the data coming in via the shared memory providing application.

like image 707
Chad Avatar asked Apr 13 '12 17:04

Chad


People also ask

What is boost interprocess?

Interprocess simplifies the use of common interprocess communication and synchronization mechanisms and offers a wide range of them: Shared memory. Memory-mapped files. Semaphores, mutexes, condition variables and upgradable mutex types to place them in shared memory and memory mapped files.

How shared memory is used for interprocess communication?

Inter Process Communication through shared memory is a concept where two or more process can access the common memory. And communication is done via this shared memory where changes made by one process can be viewed by another process.

Is boost interprocess header only?

Boost Interprocess is a header-only library, so all you need to do is include the appropriate header in your sources and make the compiler aware of the include path.


1 Answers

I guess you have found your answer since you posted this question, this is for others benefit...

try and check out boost strands.

It gives you the ability to choose on which thread you want to do some work on.

It will automatically get queued on the specific strand, that's something you won't have to think about.

It even gives you a completion handler if you need to know when the work is done.

like image 113
TheSquad Avatar answered Sep 20 '22 15:09

TheSquad