The ArmarX shared memory provides unidirectional shared memory communication.
Further, classes are provided which allow unidirectional communication which either uses Ice or shared memory dependent on whether a local or a remote connection is used.
The API documentation can be found here: SharedMemory
Using simple shared memory
The simple shared memory mechanism provides mechanisms to share memory between a SharedMemoryProvider and a SharedMemoryConsumer. Both provider and consumer can be running in different processes in the same machine. The SharedMemoryProvider needs to be constructed before the SharedMemoryConsumer. Otherwise the SharedMemoryConsumer construction will fail.
Methods for synchronization are providing using either a scoped mechanism or lock / unlock methods.
SharedMemoryProvider<int>::pointer_type sharedMemoryProvider;
sharedMemoryProvider.reset( new SharedMemoryProvider<int>("SharedMemory", 1));
SharedMemoryConsumer<int>::pointer_type sharedMemoryConsumer;
try
{
sharedMemoryConsumer.reset( new SharedMemoryConsumer<int>("SharedMemory"));
} catch(exceptions::local::SharedMemoryException e)
{
}
{
SharedMemoryScopedWriteLockPtr lock = sharedMemoryProvider->getScopedWriteLock();
int*
data = sharedMemoryProvider->getMemory();
}
{
SharedMemoryScopedReadLockPtr lock = sharedMemoryConsumer->getScopedReadLock();
int*
data = sharedMemoryConsumer->getMemory();
printf(
"Data: %d\n", *
data);
}
Using combined Ice and shared memory transfer
The combined Ice and shared memory mechanism allows to exchange high amounts of data between two processes either via shared memory or using Ice. Whether Ice or shared memory transfer is used is selected automatically using the hardware id of the both machines involved in the communications. If the hardware ids of both sides are the same, shared memory transfer is used. Otherwise Ice transfer is used.
In general, the Provider needs to be started using start() before start() of the component can be called. The correct sequence is guaranteed when calling the constructors in onInitComponent() or equivalent and the start() methods in onConnectComponent(). The sequence is achieve making use of the components dependency mechanism.
A component that writes to the IceSharedMemory mechanism can be implemented in the following way:
{
class SharedMemoryWriter :
virtual public PeriodicComponent
{
protected:
void onInitComponent()
{
sharedMemoryProvider = new IceSharedMemoryProvider<int>(this, 1);
}
void onStartComponent()
{
sharedMemoryProvider->start();
counter = 0;
}
void periodicExec()
{
SharedMemoryScopedWriteLockPtr lock = sharedMemoryProvider->getScopedWriteLock();
int* buffer = sharedMemoryProvider->getBuffer();
*buffer = counter;
std::cout << "Set value to " << counter << std::endl;
counter++;
}
std::string getDefaultName() { return "SharedMemoryWriter"; }
private:
IceSharedMemoryProvider<int>::pointer_type sharedMemoryProvider;
}
}
This file offers overloads of toIce() and fromIce() functions for STL container types.
In a similar manner, read access to the IceSharedMemory mechanism is provided:
{
class SharedMemoryReader :
virtual public PeriodicComponent
{
protected:
void onInitComponent()
{
sharedMemoryConsumer = new IceSharedMemoryConsumer<int>(this,"SharedMemoryWriter");
}
void onStartComponent()
{
sharedMemoryConsumer->start();
}
void periodicExec()
{
int result;
sharedMemoryConsumer->getData(&result);
ARMARX_LOG << eINFO <<
"Retrieved value " << result << std::endl;
}
std::string getDefaultName() { return "SharedMemoryReader"; }
private:
IceSharedMemoryConsumer<int>::pointer_type sharedMemoryConsumer;
}
}