$search
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 #ifdef ECL_HAS_EXCEPTIONS 00064 00073 // Have to be public since its called from a template (inline) function. 00074 ECL_PUBLIC ecl::StandardException openSharedSectionException(const char* loc); 00083 ECL_PUBLIC ecl::StandardException memoryMapException(const char* loc); 00084 00085 00086 #endif /* ECL_HAS_EXCEPTIONS */ 00087 00095 class ECL_PUBLIC SharedMemoryBase { 00096 public: 00102 void unlink(); 00103 00104 protected: 00105 SharedMemoryBase(const std::string &name_id) : 00106 name(name_id), 00107 shared_memory_manager(false) 00108 {}; 00116 int open(); 00117 00118 std::string name; 00119 bool shared_memory_manager; 00120 }; 00121 00122 } // namespace ipc 00123 00124 /***************************************************************************** 00125 ** Shared Memory 00126 *****************************************************************************/ 00138 template <typename Storage> 00139 class ECL_PUBLIC SharedMemory : public ipc::SharedMemoryBase 00140 { 00141 public: 00142 /********************* 00143 ** C&D's 00144 **********************/ 00145 SharedMemory(const std::string& string_id) ecl_throw_decl(StandardException); 00146 virtual ~SharedMemory(); 00147 00148 Storage* data() { return storage; } 00150 private: 00151 SharedMemory() {} 00152 const int shared_memory_size; 00153 Storage *storage; 00154 }; 00155 00156 /***************************************************************************** 00157 ** Implementation 00158 *****************************************************************************/ 00159 00171 template <typename Storage> 00172 SharedMemory<Storage>::SharedMemory(const std::string& string_id ) ecl_throw_decl(StandardException) : 00173 ipc::SharedMemoryBase(std::string("/")+string_id), 00174 shared_memory_size(sizeof(Storage)), 00175 storage(NULL) 00176 { 00177 int shm_descriptor = open(); 00178 if ( shm_descriptor == -1) { 00179 ecl_throw( ipc::openSharedSectionException(LOC) ); 00180 } 00181 /********************* 00182 * Mapping 00183 *********************/ 00184 /* 00185 * Map the shared memory into your process's address space. 00186 * 00187 * Address: 0 lets posix choose the address. 00188 * Memory Protections: PROT_READ,WRITE,EXEC,NONE. Tells the MMU what to do. Match with the shm_open parameters. 00189 * PROT_EXEC only useful if you want to run a shared library there. 00190 * Mapping Flags: Always choose MAP_SHARED for shared memory! Other options almost irrelevant. 00191 * Descriptor : shm_send_descriptor from above. 00192 * OFFSET : we should never really want to offset a chunk of memory. Just point it at the start (0). 00193 * 00194 * mmap(address,sharedMemSize,memprotections,mappingflags,descriptor,offset); 00195 */ 00196 void * shm_address; 00197 if ( (shm_address = mmap(0,shared_memory_size,PROT_READ|PROT_WRITE,MAP_SHARED,shm_descriptor,(long) 0)) == MAP_FAILED ) 00198 { 00199 shared_memory_manager = false; 00200 close(shm_descriptor); 00201 unlink(); 00202 ecl_throw( ipc::memoryMapException(LOC) ); 00203 } 00204 /* 00205 * When first created, the shared memory has 0 size. You need to inflate it before 00206 * you can use it. The second argument, the length is measured in bytes. 00207 */ 00208 if ( ftruncate(shm_descriptor,shared_memory_size) < 0 ) 00209 { 00210 shared_memory_manager = false; 00211 close(shm_descriptor); 00212 unlink(); 00213 ecl_throw(StandardException(LOC,OpenError,"Shared memory created, but inflation to the desired size failed.")); 00214 } 00215 00216 /********************* 00217 ** Close 00218 **********************/ 00219 /* 00220 * This does not unmap the memory allocated to the block. It just closes the file 00221 * descriptor. Should do it early for tidiness if for no other reason. 00222 */ 00223 close(shm_descriptor); 00224 00225 storage = (Storage*) shm_address; 00226 00227 // If just allocated, initialise the shared memory structure. 00228 if ( shared_memory_manager ) { 00229 *storage = Storage(); 00230 } 00231 } 00237 template <typename Storage> 00238 SharedMemory<Storage>::~SharedMemory() 00239 { 00240 /* Might be worth putting a check on this later (i.e. < 0 is an error). */ 00241 munmap( (void*) storage,shared_memory_size); 00242 // munmap(shm_address,shared_memory_size); 00243 00244 if ( shared_memory_manager ) { 00245 unlink(); 00246 } 00247 } 00248 00249 }; // namespace ecl 00250 00251 00252 #endif /* _POSIX_SHARED_MEMORY_OBJECTS > 0 */ 00253 #endif /* _POSIX_SHARED_MEMORY_OBJECTS */ 00254 #endif /* ECL_IS_POSIX */ 00255 00256 #endif /* ECL_IPC_SHARED_MEMORY_RT_HPP_ */