views:

464

answers:

5

We have a need for multiple programs to call functions in a common library. The library functions access and update a common global memory. Each program’s function calls need to see this common global memory. That is one function call needs to see the updates of any prior function call even if called from another program. For compatibility reasons we have several design constraints on how the functions exposed by the shared library must operate:

  • Any data items (both standard data types and objects) that are declared globally must be visible to all callers regardless of the thread in which the code is running.
  • Any data items that are declared locally in a function are only visible inside that function.
  • Any standard data type or an instance of any class may appear either locally or globally or both.

One solution is to put the library’s common global memory in named shared memory. The first library call would create the named shared memory and initialize it. Subsequent program calls would get the address of the shared memory and use it as a pointer to the global data structure. Object instances declared globally would need to be dynamically allocated in shared memory while object instances declared locally could be placed on the stack or in the local heap of the caller thread. Problems arise because initialized objects in the global memory can create and point to sub-objects which allocate (new) additional memory. These new allocations also need to be in the shared memory and seen by all library callers. Another complication is these objects, which contain strings, files, etc., can also be used in the calling program. When declared in the calling program, the object’s memory is local to the calling program, not shared. So the object’s code needs to handle either case. It appears to us that the solution will require that we override the global placement new, regular new and delete operators. We found a design for a memory management system that looks like it will work but we haven’t found any actual implementations. If anyone knows of an implementation of Nathan Myers’ memory management design (http://www.cantrip.org/wave12.html?seenIEPage=1) I would appreciate a link to it. Alternatively if anyone knows of another shared memory manager that accommodates dynamically allocating objects I would love to know about it as well. I've checked the Boost libraries and all the other sources I can find but nothing seems to do what we need. We prefer not to have to write one ourselves. Since performance and robustness are important it would be nice to use proven code. Thanks in advance for any ideas/help.

Thanks for the suggestions about the ATL and OSSP libraries. I am checking them out now although I'm afraid ATL is too Wincentric if are target turns out to be Unix.

One other thing now seems clear to us. Since objects can be dynamically created during execution, the memory management scheme must be able to allocate additional pages of shared memory. This is now starting to look like a full-blown heap replacement memory manager.

A: 

OSSP mm - Shared Memory Allocation:

man 3 mm

vitaly.v.ch
+1  A: 

Take a look at boost.interprocess.

Nikolai N Fetissov
As I mentioned in the post, we looked at the Boost library. Unfortunately it didn't accomplish what we needed. It lead us to some promising resouces, though, such as the link I mentioned in the post.
BillC
A: 

As I'm sure you have found, this is a very complex problem, and very difficult to correctly implement. A few tips from my experiences. First of all, you'll definitely want to synchronize access to the shared memory allocations using semaphores. Secondly, any modifications to the shared objects by multiple processes need to be protected by semaphores as well. Finally, you need to think in terms of offsets from the start of the shared memory region, rather than absolute pointer values, when defining your objects and data structures (it's generally possible for the memory to be mapped at a different address in each attached process, although you can choose a fixed mapping address if you need to). Putting it all together in a robust manner is the hard part. It's easy for shared memory based data structures to become corrupted if a process should unexpectedly die, so some cleanup / recovery mechanism is usually required.

Andrew
You're exactly right. The problem is complex and that's why we don't want to have to write the code from scratch.
BillC
A: 

You can try to use the ATL Server Library, it provides all the resources to manage threads and caches. See samples at ATL Server Samples

lsalamon
A: 

Also study mutexes and semaphores. When two or more entities need to share memory or data, there needs to be a "traffic signal" mechanism to limit write access to only one user.

Thomas Matthews
Thanks. We understand that this needs to be thread safe and have implemented mutexes to control access. The main problem we have is how to ensure that some objects are allocated in shared memory, along with any objects they instantiate, while other instances of the same objects are allocated locally.
BillC
Mixing process-local and shared memory like you're describing seems generally like a recipe for disaster. Defining a more formal inter-process communication protocol is probably a better approach.
Andrew