This is the primary interface to shared memory.

Its d_accessPtr points to the attached shared memory block, but points to the
currently attached shared memory interface 'MmoryAccess' which itself is a
statically cast pointer to a shared data segment.

memorybridge3.cc calls MemoryAccess::create, which calls MemoryAccess::getID,
which calls shmget(), making available the required shared memory block.

In that shared memory block a MemoryAccess object is created using placement
new constructing the MemoryAccess object using memoryaccess1.cc.

The MemoryAccess constructor (memoryaccess1.cc) initializes its object by
filling the d_nBlocks elements of its d_block array with -1. The d_block array
itself is defined in the MemoryAccess interface as a array of size 1, but in
fact, because of the size of the shared memory block, contains d_nBlocks
elements. Each of its elements are either -1 (shared memory data not
available) or it contains the ID of a previously allocated shared memory block
containing 'd_blockSize' bytes. Those bytes may or may not have been filled by
write requests, but its size is known: d_blockSize.

A static vector s_loaded contains the indices of shared memory objects
loaded by possibly multiple MemoryAccess objects defined by one process. When
a MemoryAccess object is constructed it adds -1 to that vector, and the index
of that vector's last elememnt is stored in the MemoryAccess d_idx data
member. Thus each MemoryAccess object in a process has its own element in
s_loaded. 

When a data block must be made available the current offset (maintained by
MemoryBuf, since that object is the primary interface to the shared memory)
determines the required block index (in d_block): the current offset is used
to determine the d_block index, and if that element is -1 that data block
isn't available yet. In that case 'getID' is called which uses shmget to
obtain its ID. Alternatively d_block[index] may already be known.

Once the ID is available its shared memory block is activated by
MemoryAccess::activate. That member receives the block index and the ID.
If there is a currently loaded data block (s_loaded[d_idx] != -1) then, if the
requested ID equals the currently loaded block (s_loaded[d_idx]) then the data
block is already loaded and thus available. Otherwise the currenty loaded
block is disconnected by 'disconnect'.
Finally d_data is assigned to the location of the requested shared data block
by calling 'connect(id)' which calls shmat, attaching the shared data block.


block has already been defined d_block[blockIdx
