12

I have a relatively complex class in c++. It works perfectly when used within one process. However, now I want multiple processes to be able to share one object instance of this class. One process (Master) will access read and write functions of the object, while the other 2 processes (Slave) will only use the read functions. I want to modify the class as little as possible. So far I have considered singletons and shared memory, but neither seems ideal or straightforward. This is a research application that will only ever be used by me on Linux. What is the simplest possible solution?

Thanks so much!

Edit: To be absolutely clear, the asker is interested in sharing an object across multiple processes, not threads.

BoBTFish
  • 19,167
  • 3
  • 49
  • 76
user1971455
  • 413
  • 1
  • 7
  • 16
  • 2
    I haven't used it, but you don't mention being aware of [Boost.Interprocess](http://www.boost.org/doc/libs/1_53_0/doc/html/interprocess.html). – BoBTFish May 30 '13 at 20:47
  • You may want to search for `shared memory`. [Here a question on SO](http://stackoverflow.com/questions/5656530/how-to-use-shared-memory-with-linux-in-c) but for `C` (witch may also work for C++) – A4L May 30 '13 at 20:48
  • Switch to Delphi and use BPLs (some kind of DLLs on steroids) :) – Gabriel Nov 07 '19 at 09:47
  • I had the fortune of working on a similar problem recently. Let me share my new found wisdom. The sharing part of data is the easy part. The real issue is with your multiple processes. It depends how these processes will run. That's the real question. Will the processing run as threads or as individual processes. If they will be running as separate processes then you need to account for memory sharing because individual processes don't have access to the same memory. If the multiprocessing is done using threads then the solution is fairly simple as others have suggested. –  Aug 24 '20 at 19:21
  • Nothing elaborate like a Boost library is required in either of the cases. –  Aug 24 '20 at 19:23

5 Answers5

4

Inter-process communication is never simple. You may want to use a library for IPC/RPC and expose only the function the slaves use to read data, not the entire class.

I can't give you any good recommendations because I have never found a library that made it simple and I don't have much experience with it.

Minthos
  • 900
  • 4
  • 13
1

I think the simplest coding solution would be a singleton with a global(or class instance) mutex, though the singleton part of that is optional. I personally think singletons to be an overused idiom. Up to you whether you think that is good design in this case or not. Really, adding the global mutex is all you need.

For the interprocess portion, I recommend boost.

http://www.boost.org/doc/libs/1_36_0/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.semaphores.semaphores_interprocess_semaphores

MobA11y
  • 18,425
  • 3
  • 49
  • 76
1

One idea might be to use socket or a socket library to share the data amongst the processes. A library which seems to be very handy for that might be ØMQ. You can also try to use Boost::Asio which is a bit more complex.

You can find a small example for ØMQ here.

Community
  • 1
  • 1
mistapink
  • 1,926
  • 1
  • 26
  • 37
1

One option is to have both the master and slave processes create instances of the same object. Because the master process will be the only one to modify this 'shared' object, it must only alert the slaves processes to any changes it makes to the 'shared' object. To do this, you could setup a messaging system which the master process will use to communicate changes to the shared object with the slave processes. The drawback here is that the slave processes may reference the shared object when it is out of sync with the master, but this is a common problem in replication. Also, you could use an RPC overlay to further make the master/slave applications easier to develop/maintain.

I'll try and provide a very high level example of this design below. Forgive me for utilizing real code and psuedo code side-by-side; I didn't want to fully code this, but also didn't want it to just be made up of comments :)

Here's our shared object that gets defined in both master/slave code

struct sharedobj {
  int var1;
};

Here's an example of the master process updating the shared object and propagating changes

int counter = 0;
sharedobj mysharedobj;
while(true){
  //update the local version first
  mysharedobj.var1 = counter++;

  //then call some function to push these changes to the slaves
  updateSharedObj(mysharedobj);
}

Here's the function that propagates the master's changes to the slaves;

updatedSharedObj(sharedobj obj){

  //set up some sort of message that encompasses these changes
  string msg = "var1:" + the string value of obj.var1;

  //go through the set of slave processes
  //if we've just done basic messaging, maybe we have a socket open for each process
  while(socketit != socketlist.end()){

    //send message to slave
    send(*socketit, msg.c_str(),msg.length(),0);

  }

}

And here's the slave code that receives these changes and updates its 'shared' object; most likely running in another thread so slave can run without having to stop and check for object updates.

while(true){

  //wait on the socket for updates
  read(mysock,msgbuf,msgbufsize,0);

  //parse the msgbuf
  int newv1 = the int value of var1 from the msg;

  //if we're in another thread we need to synchronize access to the object between
  //update thread and slave
  pthread_mutex_lock(&objlock);

  //update the value of var1
  sharedobj.var1 = newv1;

  //and release the lock
  pthread_mutex_unlock(&objlock);

}
ryanbwork
  • 2,123
  • 12
  • 12
1

See "shared memory" in Boost Interprocess: http://www.boost.org/doc/libs/1_63_0/doc/html/interprocess/sharedmemorybetweenprocesses.html

alex
  • 1,757
  • 4
  • 21
  • 32