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