Warning, file /include/boost/interprocess/detail/portable_intermodule_singleton.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
0012 #define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 0018 ">#
0019 #if defined(BOOST_HAS_PRAGMA_ONCE)
0020 #pragma once
0021 #endif
0022
0023 #include <boost/interprocess/detail/config_begin.hpp>
0024 #include <boost/interprocess/detail/workaround.hpp>
0025
0026 #include <boost/interprocess/detail/managed_global_memory.hpp>
0027 #include <boost/interprocess/detail/intermodule_singleton_common.hpp>
0028 #include <boost/interprocess/shared_memory_object.hpp>
0029 #include <boost/interprocess/detail/atomic.hpp>
0030 #include <boost/interprocess/detail/os_thread_functions.hpp>
0031 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
0032 #include <boost/interprocess/detail/os_file_functions.hpp>
0033 #include <boost/interprocess/detail/file_locking_helpers.hpp>
0034 #include <boost/assert.hpp>
0035 #include <cstddef>
0036 #include <cstdio>
0037 #include <cstring>
0038 #include <string>
0039
0040 namespace boost{
0041 namespace interprocess{
0042 namespace ipcdetail{
0043
0044 typedef basic_managed_global_memory<shared_memory_object, true> managed_global_memory;
0045
0046 namespace intermodule_singleton_helpers {
0047
0048 static void create_tmp_subdir_and_get_pid_based_filepath
0049 (const char *subdir_name, const char *file_prefix, OS_process_id_t pid, std::string &s, bool creation_time = false)
0050 {
0051
0052
0053 create_shared_dir_and_clean_old(s);
0054 s += "/";
0055 s += subdir_name;
0056 if(!open_or_create_shared_directory(s.c_str())){
0057 error_info err = system_error_code();
0058 throw interprocess_exception(err);
0059 }
0060 s += "/";
0061 s += file_prefix;
0062 if(creation_time){
0063 std::string sstamp;
0064 get_pid_creation_time_str(sstamp);
0065 s += sstamp;
0066 }
0067 else{
0068 pid_str_t pid_str;
0069 get_pid_str(pid_str, pid);
0070 s += pid_str;
0071 }
0072 }
0073
0074 static bool check_if_filename_complies_with_pid
0075 (const char *filename, const char *prefix, OS_process_id_t pid, std::string &file_suffix, bool creation_time = false)
0076 {
0077
0078 std::string fname(filename);
0079 std::string fprefix(prefix);
0080 if(fname.size() <= fprefix.size()){
0081 return false;
0082 }
0083 fname.resize(fprefix.size());
0084 if(fname != fprefix){
0085 return false;
0086 }
0087
0088
0089 fname = filename;
0090 fname.erase(0, fprefix.size());
0091 pid_str_t pid_str;
0092 get_pid_str(pid_str, pid);
0093 file_suffix = pid_str;
0094 if(creation_time){
0095 std::size_t p = fname.find('_');
0096 if (p == std::string::npos){
0097 return false;
0098 }
0099 std::string save_suffix(fname);
0100 fname.erase(p);
0101 fname.swap(file_suffix);
0102 bool ret = (file_suffix == fname);
0103 file_suffix.swap(save_suffix);
0104 return ret;
0105 }
0106 else{
0107 fname.swap(file_suffix);
0108 return (file_suffix == fname);
0109 }
0110 }
0111
0112 template<>
0113 struct thread_safe_global_map_dependant<managed_global_memory>
0114 {
0115 private:
0116 static const int GMemMarkToBeRemoved = -1;
0117 static const int GMemNotPresent = -2;
0118
0119 static const char *get_lock_file_subdir_name()
0120 { return "gmem"; }
0121
0122 static const char *get_lock_file_base_name()
0123 { return "lck"; }
0124
0125 static void create_and_get_singleton_lock_file_path(std::string &s)
0126 {
0127 create_tmp_subdir_and_get_pid_based_filepath
0128 (get_lock_file_subdir_name(), get_lock_file_base_name(), get_current_process_id(), s, true);
0129 }
0130
0131 struct gmem_erase_func
0132 {
0133 gmem_erase_func(const char *shm_name, const char *singleton_lock_file_path, managed_global_memory & shm)
0134 :shm_name_(shm_name), singleton_lock_file_path_(singleton_lock_file_path), shm_(shm)
0135 {}
0136
0137 void operator()()
0138 {
0139 locking_file_serial_id *pserial_id = shm_.find<locking_file_serial_id>("lock_file_fd").first;
0140 if(pserial_id){
0141 pserial_id->fd = GMemMarkToBeRemoved;
0142 }
0143 delete_file(singleton_lock_file_path_);
0144 shared_memory_object::remove(shm_name_);
0145 }
0146
0147 const char * const shm_name_;
0148 const char * const singleton_lock_file_path_;
0149 managed_global_memory & shm_;
0150 };
0151
0152
0153 static void apply_gmem_erase_logic(const char *filepath, const char *filename)
0154 {
0155 int fd = GMemMarkToBeRemoved;
0156 BOOST_INTERPROCESS_TRY{
0157 std::string str;
0158
0159 if(check_if_filename_complies_with_pid
0160 (filename, get_lock_file_base_name(), get_current_process_id(), str, true)){
0161 return;
0162 }
0163
0164 fd = try_open_and_lock_file(filepath);
0165 if(fd < 0){
0166 return;
0167 }
0168
0169
0170 str.insert(0, get_map_base_name());
0171 BOOST_INTERPROCESS_TRY{
0172 managed_global_memory shm(open_only, str.c_str());
0173 gmem_erase_func func(str.c_str(), filepath, shm);
0174 shm.try_atomic_func(func);
0175 }
0176 BOOST_INTERPROCESS_CATCH(interprocess_exception &e){
0177
0178 if(e.get_error_code() == not_found_error){
0179 delete_file(filepath);
0180 }
0181 } BOOST_INTERPROCESS_CATCH_END
0182 }
0183 BOOST_INTERPROCESS_CATCH(...){
0184
0185 } BOOST_INTERPROCESS_CATCH_END
0186 if(fd >= 0){
0187 close_lock_file(fd);
0188 }
0189 }
0190
0191 public:
0192
0193 static bool remove_old_gmem()
0194 {
0195 std::string refcstrRootDirectory;
0196 get_shared_dir(refcstrRootDirectory);
0197 refcstrRootDirectory += "/";
0198 refcstrRootDirectory += get_lock_file_subdir_name();
0199 return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic);
0200 }
0201
0202 struct lock_file_logic
0203 {
0204 lock_file_logic(managed_global_memory &shm)
0205 : mshm(shm)
0206 { shm.atomic_func(*this); }
0207
0208 void operator()(void)
0209 {
0210 retry_with_new_map = false;
0211
0212
0213 locking_file_serial_id *pserial_id =
0214 mshm.find<locking_file_serial_id>("lock_file_fd").first;
0215
0216 int fd;
0217
0218 if(!pserial_id){
0219 fd = GMemNotPresent;
0220 }
0221
0222 else{
0223 fd = pserial_id->fd;
0224 }
0225
0226 if(fd == GMemNotPresent){
0227 std::string lck_str;
0228
0229 create_and_get_singleton_lock_file_path(lck_str);
0230
0231 int fd_lockfile = open_or_create_and_lock_file(lck_str.c_str());
0232
0233
0234
0235 if(fd_lockfile < 0){
0236 this->register_lock_file(GMemMarkToBeRemoved);
0237 std::string s;
0238 get_map_name(s);
0239 shared_memory_object::remove(s.c_str());
0240 retry_with_new_map = true;
0241 }
0242
0243 else{
0244 this->register_lock_file(fd_lockfile);
0245 }
0246 }
0247
0248
0249
0250 else if (fd == GMemMarkToBeRemoved){
0251 retry_with_new_map = true;
0252 }
0253
0254
0255
0256
0257 else if(!is_valid_fd(fd) ||
0258 !is_normal_file(fd) ||
0259 0 != get_size(fd) ||
0260 !compare_file_serial(fd, *pserial_id)){
0261 pserial_id->fd = GMemMarkToBeRemoved;
0262 std::string s;
0263 get_map_name(s);
0264 shared_memory_object::remove(s.c_str());
0265 retry_with_new_map = true;
0266 }
0267 else{
0268
0269
0270 atomic_inc32(&pserial_id->modules_attached_to_gmem_count);
0271 }
0272 }
0273
0274 bool retry() const { return retry_with_new_map; }
0275
0276 private:
0277 locking_file_serial_id * register_lock_file(int fd)
0278 {
0279 locking_file_serial_id *pinfo = mshm.construct<locking_file_serial_id>("lock_file_fd")();
0280 fill_file_serial_id(fd, *pinfo);
0281 return pinfo;
0282 }
0283
0284 managed_global_memory &mshm;
0285 bool retry_with_new_map;
0286 };
0287
0288 static void construct_map(void *addr)
0289 {
0290 std::string s;
0291 intermodule_singleton_helpers::get_map_name(s);
0292 const char *MapName = s.c_str();
0293 const std::size_t MapSize = intermodule_singleton_helpers::get_map_size();;
0294 ::new (addr)managed_global_memory(open_or_create, MapName, MapSize);
0295 }
0296
0297 struct unlink_map_logic
0298 {
0299 unlink_map_logic(managed_global_memory &mshm)
0300 : mshm_(mshm)
0301 { mshm.atomic_func(*this); }
0302
0303 void operator()()
0304 {
0305 locking_file_serial_id *pserial_id =
0306 mshm_.find<locking_file_serial_id>
0307 ("lock_file_fd").first;
0308 BOOST_ASSERT(0 != pserial_id);
0309 if(1 == atomic_dec32(&pserial_id->modules_attached_to_gmem_count)){
0310 int fd = pserial_id->fd;
0311 if(fd > 0){
0312 pserial_id->fd = GMemMarkToBeRemoved;
0313 std::string s;
0314 create_and_get_singleton_lock_file_path(s);
0315 delete_file(s.c_str());
0316 close_lock_file(fd);
0317 intermodule_singleton_helpers::get_map_name(s);
0318 shared_memory_object::remove(s.c_str());
0319 }
0320 }
0321 }
0322
0323 private:
0324 managed_global_memory &mshm_;
0325 };
0326
0327 static ref_count_ptr *find(managed_global_memory &map, const char *name)
0328 {
0329 return map.find<ref_count_ptr>(name).first;
0330 }
0331
0332 static ref_count_ptr *insert(managed_global_memory &map, const char *name, const ref_count_ptr &ref)
0333 {
0334 return map.construct<ref_count_ptr>(name)(ref);
0335 }
0336
0337 static bool erase(managed_global_memory &map, const char *name)
0338 {
0339 return map.destroy<ref_count_ptr>(name);
0340 }
0341
0342 template<class F>
0343 static void atomic_func(managed_global_memory &map, F &f)
0344 {
0345 map.atomic_func(f);
0346 }
0347 };
0348
0349 }
0350
0351 template<typename C, bool LazyInit = true, bool Phoenix = false>
0352 class portable_intermodule_singleton
0353 : public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory>
0354 {};
0355
0356 }
0357 }
0358 }
0359
0360 #include <boost/interprocess/detail/config_end.hpp>
0361
0362 #endif