shared_memory_pos.hpp
Go to the documentation of this file.
00001 
00010 /*****************************************************************************
00011 ** Ifdefs
00012 *****************************************************************************/
00013 
00014 #ifndef ECL_IPC_SHARED_MEMORY_RT_HPP_
00015 #define ECL_IPC_SHARED_MEMORY_RT_HPP_
00016 
00017 /*****************************************************************************
00018 ** Platform Check
00019 *****************************************************************************/
00020 
00021 #include <ecl/config.hpp>
00022 #if defined(ECL_IS_POSIX)
00023 #include <unistd.h>
00024 #include <bits/posix_opt.h>
00025 #ifdef _POSIX_SHARED_MEMORY_OBJECTS
00026 #if _POSIX_SHARED_MEMORY_OBJECTS > 0
00027 
00028 /*****************************************************************************
00029 ** Ecl Functionality Defines
00030 *****************************************************************************/
00031 
00032 #ifndef ECL_HAS_POSIX_SHARED_MEMORY
00033   #define ECL_HAS_POSIX_SHARED_MEMORY
00034 #endif
00035 #ifndef ECL_HAS_SHARED_MEMORY
00036   #define ECL_HAS_SHARED_MEMORY
00037 #endif
00038 
00039 /*****************************************************************************
00040 ** Includes
00041 *****************************************************************************/
00042 
00043 #include <sstream>
00044 #include <string>
00045 #include <sys/mman.h>        /* For shm_open() */
00046 #include <fcntl.h>           /* For O_* constants */
00047 #include <ecl/exceptions/macros.hpp>
00048 #include <ecl/exceptions/standard_exception.hpp>
00049 #include <ecl/config/macros.hpp>
00050 
00051 /*****************************************************************************
00052 ** Namespaces
00053 *****************************************************************************/
00054 
00055 namespace ecl {
00056 
00057 /*****************************************************************************
00058 ** Exception Handling
00059 *****************************************************************************/
00060 
00061 namespace ipc {
00062 
00063 #ifndef ECL_DISABLE_EXCEPTIONS
00064 
00072 // Have to be public since its called from a template (inline) function.
00073 ECL_PUBLIC ecl::StandardException openSharedSectionException(const char* loc);
00082 ECL_PUBLIC ecl::StandardException memoryMapException(const char* loc);
00083 #endif
00084 
00092 class ECL_PUBLIC SharedMemoryBase {
00093 public:
00099         void unlink();
00100 
00101 protected:
00102         SharedMemoryBase(const std::string &name_id) :
00103                 name(name_id),
00104                 shared_memory_manager(false)
00105         {};
00113         int open();
00114 
00115         std::string name;
00116         bool shared_memory_manager;
00117 };
00118 
00119 } // namespace ipc
00120 
00121 /*****************************************************************************
00122 ** Shared Memory
00123 *****************************************************************************/
00135 template <typename Storage>
00136 class ECL_PUBLIC SharedMemory : public ipc::SharedMemoryBase
00137 {
00138 public:
00139         /*********************
00140         ** C&D's
00141         **********************/
00142         SharedMemory(const std::string& string_id) ecl_throw_decl(StandardException);
00143         virtual ~SharedMemory();
00144 
00145         Storage* data() { return storage; }         
00147 private:
00148         SharedMemory() {} 
00149         const int shared_memory_size;
00150         Storage *storage;
00151 };
00152 
00153 /*****************************************************************************
00154 ** Implementation
00155 *****************************************************************************/
00156 
00168 template <typename Storage>
00169 SharedMemory<Storage>::SharedMemory(const std::string& string_id ) ecl_throw_decl(StandardException)  :
00170         ipc::SharedMemoryBase(std::string("/")+string_id),
00171         shared_memory_size(sizeof(Storage)),
00172         storage(NULL)
00173 {
00174         int shm_descriptor = open();
00175     if ( shm_descriptor == -1) {
00176         ecl_throw( ipc::openSharedSectionException(LOC) );
00177     }
00178     /*********************
00179      * Mapping
00180      *********************/
00181     /*
00182      * Map the shared memory into your process's address space.
00183      *
00184      * Address: 0 lets posix choose the address.
00185      * Memory Protections: PROT_READ,WRITE,EXEC,NONE. Tells the MMU what to do. Match with the shm_open parameters.
00186      *                     PROT_EXEC only useful if you want to run a shared library there.
00187      * Mapping Flags: Always choose MAP_SHARED for shared memory! Other options almost irrelevant.
00188      * Descriptor : shm_send_descriptor from above.
00189      * OFFSET : we should never really want to offset a chunk of memory. Just point it at the start (0).
00190      *
00191      * mmap(address,sharedMemSize,memprotections,mappingflags,descriptor,offset);
00192      */
00193     void * shm_address;
00194     if ( (shm_address = mmap(0,shared_memory_size,PROT_READ|PROT_WRITE,MAP_SHARED,shm_descriptor,(long) 0)) == MAP_FAILED )
00195     {
00196         shared_memory_manager = false;
00197         close(shm_descriptor);
00198         unlink();
00199         ecl_throw( ipc::memoryMapException(LOC) );
00200     }
00201     /*
00202      * When first created, the shared memory has 0 size. You need to inflate it before
00203      * you can use it. The second argument, the length is measured in bytes.
00204      */
00205     if ( ftruncate(shm_descriptor,shared_memory_size) < 0 )
00206     {
00207         shared_memory_manager = false;
00208         close(shm_descriptor);
00209         unlink();
00210         ecl_throw(StandardException(LOC,OpenError,"Shared memory created, but inflation to the desired size failed."));
00211     }
00212 
00213     /*********************
00214     ** Close
00215     **********************/
00216     /*
00217      * This does not unmap the memory allocated to the block. It just closes the file
00218      * descriptor. Should do it early for tidiness if for no other reason.
00219      */
00220     close(shm_descriptor);
00221 
00222     storage = (Storage*) shm_address;
00223 
00224     // If just allocated, initialise the shared memory structure.
00225     if ( shared_memory_manager ) {
00226         *storage = Storage();
00227     }
00228 }
00234 template <typename Storage>
00235 SharedMemory<Storage>::~SharedMemory()
00236 {
00237     /* Might be worth putting a check on this later (i.e. < 0 is an error). */
00238     munmap( (void*) storage,shared_memory_size);
00239 //    munmap(shm_address,shared_memory_size);
00240 
00241     if ( shared_memory_manager ) {
00242         unlink();
00243     }
00244 }
00245 
00246 }; // namespace ecl
00247 
00248 
00249 #endif /* _POSIX_SHARED_MEMORY_OBJECTS > 0 */
00250 #endif /* _POSIX_SHARED_MEMORY_OBJECTS */
00251 #endif /* ECL_IS_POSIX */
00252 
00253 #endif /* ECL_IPC_SHARED_MEMORY_RT_HPP_ */


ecl_ipc
Author(s): Daniel Stonier
autogenerated on Sun Oct 5 2014 23:35:45