File indexing completed on 2025-01-18 09:38:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
0012 #define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 #pragma once
0020 #endif
0021
0022 #include <boost/interprocess/detail/config_begin.hpp>
0023 #include <boost/interprocess/detail/workaround.hpp>
0024 #include <boost/container/string.hpp>
0025
0026 #if !defined(BOOST_INTERPROCESS_WINDOWS)
0027 #error "This header can't be included from non-windows operating systems"
0028 #endif
0029
0030 #include <boost/assert.hpp>
0031 #include <boost/interprocess/detail/intermodule_singleton_common.hpp>
0032 #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
0033 #include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
0034 #include <boost/interprocess/sync/scoped_lock.hpp>
0035 #include <boost/cstdint.hpp>
0036 #include <string>
0037 #include <boost/container/map.hpp>
0038
0039 namespace boost{
0040 namespace interprocess{
0041 namespace ipcdetail{
0042
0043 namespace intermodule_singleton_helpers {
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 class windows_semaphore_based_map
0056 {
0057 typedef boost::container::map<boost::container::string, ref_count_ptr> map_type;
0058
0059 public:
0060 windows_semaphore_based_map()
0061 {
0062 map_type *m = new map_type;
0063 boost::uint32_t initial_count = 0;
0064 boost::uint32_t max_count = 0;
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 if(sizeof(void*) == sizeof(boost::uint32_t)){
0076
0077
0078
0079
0080
0081
0082
0083 union caster_union
0084 {
0085 void *addr;
0086 boost::uint32_t addr_uint32;
0087 } caster;
0088 caster.addr = m;
0089
0090 BOOST_ASSERT((caster.addr_uint32 & boost::uint32_t(3)) == 0);
0091 max_count = caster.addr_uint32 >> 2;
0092 }
0093 else if(sizeof(void*) == sizeof(boost::uint64_t)){
0094
0095
0096 union caster_union
0097 {
0098 void *addr;
0099 boost::uint64_t addr_uint64;
0100 } caster;
0101 caster.addr = m;
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 caster.addr = m;
0116 BOOST_ASSERT((caster.addr_uint64 & boost::uint64_t(3)) == 0);
0117 max_count = boost::uint32_t(caster.addr_uint64 >> 32);
0118 initial_count = boost::uint32_t(caster.addr_uint64);
0119 initial_count = initial_count/4;
0120
0121 BOOST_ASSERT((max_count & boost::uint32_t(0xC0000000)) == 0);
0122
0123 max_count |= boost::uint32_t(0x40000000);
0124 }
0125 bool created = false;
0126 const permissions & perm = permissions();
0127 std::string pid_creation_time, name;
0128 get_pid_creation_time_str(pid_creation_time);
0129 name = "bipc_gmap_sem_lock_";
0130 name += pid_creation_time;
0131 bool success = m_mtx_lock.open_or_create(name.c_str(), perm);
0132 name = "bipc_gmap_sem_count_";
0133 name += pid_creation_time;
0134 scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
0135 {
0136 success = success && m_sem_count.open_or_create
0137 ( name.c_str(), static_cast<long>(0), winapi_semaphore_wrapper::MaxCount, perm, created);
0138 name = "bipc_gmap_sem_map_";
0139 name += pid_creation_time;
0140 success = success && m_sem_map.open_or_create
0141 (name.c_str(), (long)initial_count, (long)max_count, perm, created);
0142 if(!success){
0143 delete m;
0144
0145 throw int(0);
0146 }
0147 if(!created){
0148 delete m;
0149 }
0150 else{
0151 BOOST_ASSERT(&get_map_unlocked() == m);
0152 }
0153 m_sem_count.post();
0154 }
0155 }
0156
0157 map_type &get_map_unlocked()
0158 {
0159 if(sizeof(void*) == sizeof(boost::uint32_t)){
0160 union caster_union
0161 {
0162 void *addr;
0163 boost::uint32_t addr_uint32;
0164 } caster;
0165 caster.addr = 0;
0166 caster.addr_uint32 = boost::uint32_t(m_sem_map.limit());
0167 caster.addr_uint32 = caster.addr_uint32 << 2u;
0168 return *static_cast<map_type*>(caster.addr);
0169 }
0170 else{
0171 union caster_union
0172 {
0173 void *addr;
0174 boost::uint64_t addr_uint64;
0175 } caster;
0176 boost::uint32_t max_count(boost::uint32_t(m_sem_map.limit()))
0177 , initial_count(boost::uint32_t(m_sem_map.value()));
0178
0179 max_count &= boost::uint32_t(0xBFFFFFFF);
0180 caster.addr_uint64 = max_count;
0181 caster.addr_uint64 = caster.addr_uint64 << 32u;
0182 caster.addr_uint64 |= boost::uint64_t(initial_count) << 2;
0183 return *static_cast<map_type*>(caster.addr);
0184 }
0185 }
0186
0187 ref_count_ptr *find(const char *name)
0188 {
0189 scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
0190 map_type &map = this->get_map_unlocked();
0191 map_type::iterator it = map.find(boost::container::string(name));
0192 if(it != map.end()){
0193 return &it->second;
0194 }
0195 else{
0196 return 0;
0197 }
0198 }
0199
0200 ref_count_ptr * insert(const char *name, const ref_count_ptr &ref)
0201 {
0202 scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
0203 map_type &map = this->get_map_unlocked();
0204 map_type::iterator it = map.insert(map_type::value_type(boost::container::string(name), ref)).first;
0205 return &it->second;
0206 }
0207
0208 bool erase(const char *name)
0209 {
0210 scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
0211 map_type &map = this->get_map_unlocked();
0212 return map.erase(boost::container::string(name)) != 0;
0213 }
0214
0215 template<class F>
0216 void atomic_func(F &f)
0217 {
0218 scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
0219 f();
0220 }
0221
0222 ~windows_semaphore_based_map()
0223 {
0224 scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock);
0225 m_sem_count.wait();
0226 if(0 == m_sem_count.value()){
0227 map_type &map = this->get_map_unlocked();
0228 BOOST_ASSERT(map.empty());
0229 delete ↦
0230 }
0231
0232 m_sem_map.close();
0233 m_sem_count.close();
0234
0235 }
0236
0237 private:
0238 winapi_mutex_wrapper m_mtx_lock;
0239 winapi_semaphore_wrapper m_sem_map;
0240 winapi_semaphore_wrapper m_sem_count;
0241 };
0242
0243 template<>
0244 struct thread_safe_global_map_dependant<windows_semaphore_based_map>
0245 {
0246 static void apply_gmem_erase_logic(const char *, const char *){}
0247
0248 static bool remove_old_gmem()
0249 { return true; }
0250
0251 struct lock_file_logic
0252 {
0253 lock_file_logic(windows_semaphore_based_map &)
0254 : retry_with_new_map(false)
0255 {}
0256
0257 void operator()(void){}
0258 bool retry() const { return retry_with_new_map; }
0259 private:
0260 const bool retry_with_new_map;
0261 };
0262
0263 static void construct_map(void *addr)
0264 {
0265 ::new (addr)windows_semaphore_based_map;
0266 }
0267
0268 struct unlink_map_logic
0269 {
0270 unlink_map_logic(windows_semaphore_based_map &)
0271 {}
0272 void operator()(){}
0273 };
0274
0275 static ref_count_ptr *find(windows_semaphore_based_map &map, const char *name)
0276 {
0277 return map.find(name);
0278 }
0279
0280 static ref_count_ptr * insert(windows_semaphore_based_map &map, const char *name, const ref_count_ptr &ref)
0281 {
0282 return map.insert(name, ref);
0283 }
0284
0285 static bool erase(windows_semaphore_based_map &map, const char *name)
0286 {
0287 return map.erase(name);
0288 }
0289
0290 template<class F>
0291 static void atomic_func(windows_semaphore_based_map &map, F &f)
0292 {
0293 map.atomic_func(f);
0294 }
0295 };
0296
0297 }
0298
0299 template<typename C, bool LazyInit = true, bool Phoenix = false>
0300 class windows_intermodule_singleton
0301 : public intermodule_singleton_impl
0302 < C
0303 , LazyInit
0304 , Phoenix
0305 , intermodule_singleton_helpers::windows_semaphore_based_map
0306 >
0307 {};
0308
0309 }
0310 }
0311 }
0312
0313 #include <boost/interprocess/detail/config_end.hpp>
0314
0315 #endif