Program Listing for File shared_memory_pos.hpp
↰ Return to documentation for file (include/ecl/ipc/shared_memory_pos.hpp
)
/*****************************************************************************
** Ifdefs
*****************************************************************************/
#ifndef ECL_IPC_SHARED_MEMORY_RT_HPP_
#define ECL_IPC_SHARED_MEMORY_RT_HPP_
/*****************************************************************************
** Platform Check
*****************************************************************************/
#include <ecl/config.hpp>
#if defined(ECL_IS_POSIX)
#include <unistd.h>
#if !defined(ECL_IS_APPLE)
#include <bits/posix_opt.h>
#endif
#ifdef _POSIX_SHARED_MEMORY_OBJECTS
#if _POSIX_SHARED_MEMORY_OBJECTS > 0
/*****************************************************************************
** Ecl Functionality Defines
*****************************************************************************/
#ifndef ECL_HAS_POSIX_SHARED_MEMORY
#define ECL_HAS_POSIX_SHARED_MEMORY
#endif
#ifndef ECL_HAS_SHARED_MEMORY
#define ECL_HAS_SHARED_MEMORY
#endif
/*****************************************************************************
** Includes
*****************************************************************************/
#include <sstream>
#include <string>
#include <sys/mman.h> /* For shm_open() */
#include <fcntl.h> /* For O_* constants */
#include <ecl/exceptions/macros.hpp>
#include <ecl/exceptions/standard_exception.hpp>
#include <ecl/config/macros.hpp>
/*****************************************************************************
** Namespaces
*****************************************************************************/
namespace ecl {
/*****************************************************************************
** Exception Handling
*****************************************************************************/
namespace ipc {
#ifndef ECL_DISABLE_EXCEPTIONS
// Have to be public since its called from a template (inline) function.
ECL_PUBLIC ecl::StandardException openSharedSectionException(const char* loc);
ECL_PUBLIC ecl::StandardException memoryMapException(const char* loc);
#endif
class ECL_PUBLIC SharedMemoryBase {
public:
void unlink();
protected:
SharedMemoryBase(const std::string &name_id) :
name(name_id),
shared_memory_manager(false)
{};
int open();
std::string name;
bool shared_memory_manager;
};
} // namespace ipc
/*****************************************************************************
** Shared Memory
*****************************************************************************/
template <typename Storage>
class ECL_PUBLIC SharedMemory : public ipc::SharedMemoryBase
{
public:
/*********************
** C&D's
**********************/
SharedMemory(const std::string& string_id);
virtual ~SharedMemory();
Storage* data() { return storage; }
private:
SharedMemory() {}
const int shared_memory_size;
Storage *storage;
};
/*****************************************************************************
** Implementation
*****************************************************************************/
template <typename Storage>
SharedMemory<Storage>::SharedMemory(const std::string& string_id ) :
ipc::SharedMemoryBase(std::string("/")+string_id),
shared_memory_size(sizeof(Storage)),
storage(NULL)
{
int shm_descriptor = open();
if ( shm_descriptor == -1) {
ecl_throw( ipc::openSharedSectionException(LOC) );
}
/*********************
* Mapping
*********************/
/*
* Map the shared memory into your process's address space.
*
* Address: 0 lets posix choose the address.
* Memory Protections: PROT_READ,WRITE,EXEC,NONE. Tells the MMU what to do. Match with the shm_open parameters.
* PROT_EXEC only useful if you want to run a shared library there.
* Mapping Flags: Always choose MAP_SHARED for shared memory! Other options almost irrelevant.
* Descriptor : shm_send_descriptor from above.
* OFFSET : we should never really want to offset a chunk of memory. Just point it at the start (0).
*
* mmap(address,sharedMemSize,memprotections,mappingflags,descriptor,offset);
*/
void * shm_address;
if ( (shm_address = mmap(0,shared_memory_size,PROT_READ|PROT_WRITE,MAP_SHARED,shm_descriptor,(long) 0)) == MAP_FAILED )
{
shared_memory_manager = false;
close(shm_descriptor);
unlink();
ecl_throw( ipc::memoryMapException(LOC) );
}
/*
* When first created, the shared memory has 0 size. You need to inflate it before
* you can use it. The second argument, the length is measured in bytes.
*/
if ( ftruncate(shm_descriptor,shared_memory_size) < 0 )
{
shared_memory_manager = false;
close(shm_descriptor);
unlink();
ecl_throw(StandardException(LOC,OpenError,"Shared memory created, but inflation to the desired size failed."));
}
/*********************
** Close
**********************/
/*
* This does not unmap the memory allocated to the block. It just closes the file
* descriptor. Should do it early for tidiness if for no other reason.
*/
close(shm_descriptor);
storage = (Storage*) shm_address;
// If just allocated, initialise the shared memory structure.
if ( shared_memory_manager ) {
*storage = Storage();
}
}
template <typename Storage>
SharedMemory<Storage>::~SharedMemory()
{
/* Might be worth putting a check on this later (i.e. < 0 is an error). */
munmap( (void*) storage,shared_memory_size);
// munmap(shm_address,shared_memory_size);
if ( shared_memory_manager ) {
unlink();
}
}
} // namespace ecl
#endif /* _POSIX_SHARED_MEMORY_OBJECTS > 0 */
#endif /* _POSIX_SHARED_MEMORY_OBJECTS */
#endif /* ECL_IS_POSIX */
#endif /* ECL_IPC_SHARED_MEMORY_RT_HPP_ */