File indexing completed on 2026-05-08 08:23:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
0012 #define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_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/interprocess/detail/win32_api.hpp>
0026 #include <boost/interprocess/sync/spin/mutex.hpp>
0027 #include <boost/interprocess/exceptions.hpp>
0028 #include <boost/interprocess/sync/scoped_lock.hpp>
0029 #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
0030 #include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
0031
0032
0033 #include <boost/interprocess/detail/config_external_begin.hpp>
0034 #include <boost/container/map.hpp>
0035 #include <boost/interprocess/detail/config_external_end.hpp>
0036 #include <boost/container/flat_map.hpp>
0037
0038 #include <cstddef>
0039
0040 namespace boost {
0041 namespace interprocess {
0042 namespace ipcdetail {
0043
0044 inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length)
0045 {
0046 const std::size_t need_mem = mem_length*2+1;
0047 if(out_length < need_mem){
0048 out_length = need_mem;
0049 return false;
0050 }
0051
0052 const char Characters [] =
0053 { '0', '1', '2', '3', '4', '5', '6', '7'
0054 , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0055
0056 std::size_t char_counter = 0;
0057 const char *buf = (const char *)mem;
0058 for(std::size_t i = 0; i != mem_length; ++i){
0059 out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
0060 out_str[char_counter++] = Characters[(buf[i]&0x0F)];
0061 }
0062 out_str[char_counter] = 0;
0063 return true;
0064 }
0065
0066 inline bool bytes_to_str(const void *mem, const std::size_t mem_length, wchar_t *out_str, std::size_t &out_length)
0067 {
0068 const std::size_t need_mem = mem_length*2+1;
0069 if(out_length < need_mem){
0070 out_length = need_mem;
0071 return false;
0072 }
0073
0074 const wchar_t Characters [] =
0075 { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7'
0076 , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' };
0077
0078 std::size_t char_counter = 0;
0079 const char *buf = (const char *)mem;
0080 for(std::size_t i = 0; i != mem_length; ++i){
0081 out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
0082 out_str[char_counter++] = Characters[(buf[i]&0x0F)];
0083 }
0084 out_str[char_counter] = 0;
0085 return true;
0086 }
0087
0088 class sync_id
0089 {
0090 public:
0091 typedef __int64 internal_type;
0092 sync_id()
0093 { winapi::query_performance_counter(&rand_); }
0094
0095 explicit sync_id(internal_type val)
0096 { rand_ = val; }
0097
0098 const internal_type &internal_pod() const
0099 { return rand_; }
0100
0101 internal_type &internal_pod()
0102 { return rand_; }
0103
0104 friend std::size_t hash_value(const sync_id &m)
0105 { return static_cast<std::size_t>(m.rand_); }
0106
0107 friend bool operator==(const sync_id &l, const sync_id &r)
0108 { return l.rand_ == r.rand_; }
0109
0110 friend bool operator<(const sync_id &l, const sync_id &r)
0111 { return l.rand_ < r.rand_; }
0112
0113 private:
0114 internal_type rand_;
0115 };
0116
0117 class sync_handles
0118 {
0119 public:
0120 enum type { MUTEX, SEMAPHORE };
0121
0122 private:
0123
0124
0125 typedef boost::container::flat_map<sync_id, void*> id_map_type;
0126
0127
0128 typedef boost::container::flat_map<const void*, sync_id> addr_map_type;
0129 static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
0130 static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
0131 typedef char NameBuf[StrSize];
0132
0133 void fill_name(NameBuf &name, const sync_id &id)
0134 {
0135 const char *n = "Global\\boost.ipc";
0136 std::size_t i = 0;
0137 do{
0138 name[i] = n[i];
0139 ++i;
0140 } while(n[i]);
0141 std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
0142 bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len);
0143 }
0144
0145 void throw_if_error(void *hnd_val)
0146 {
0147 if(!hnd_val){
0148 error_info err(static_cast<int>(winapi::get_last_error()));
0149 throw interprocess_exception(err);
0150 }
0151 }
0152
0153 void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count)
0154 {
0155 NameBuf name;
0156 fill_name(name, id);
0157 permissions unrestricted_security;
0158 unrestricted_security.set_unrestricted();
0159 winapi_semaphore_wrapper sem_wrapper;
0160 bool created;
0161 sem_wrapper.open_or_create
0162 (name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created);
0163 throw_if_error(sem_wrapper.handle());
0164 return sem_wrapper.release();
0165 }
0166
0167 void* open_or_create_mutex(const sync_id &id)
0168 {
0169 NameBuf name;
0170 fill_name(name, id);
0171 permissions unrestricted_security;
0172 unrestricted_security.set_unrestricted();
0173 winapi_mutex_wrapper mtx_wrapper;
0174 mtx_wrapper.open_or_create(name, unrestricted_security);
0175 throw_if_error(mtx_wrapper.handle());
0176 return mtx_wrapper.release();
0177 }
0178
0179 public:
0180 sync_handles()
0181 : num_handles_()
0182 {}
0183
0184 ~sync_handles()
0185 {
0186 BOOST_ASSERT(num_handles_ == 0);
0187 }
0188
0189 void *obtain_mutex(const sync_id &id, const void *mapping_address, bool *popen_created = 0)
0190 {
0191 id_map_type::value_type v(id, (void*)0);
0192 scoped_lock<spin_mutex> lock(mtx_);
0193 id_map_type::iterator it = umap_.insert(v).first;
0194 void *&hnd_val = it->second;
0195 if(!hnd_val){
0196 BOOST_ASSERT(map_.find(mapping_address) == map_.end());
0197 map_[mapping_address] = id;
0198 hnd_val = open_or_create_mutex(id);
0199 if(popen_created) *popen_created = true;
0200 ++num_handles_;
0201 }
0202 else if(popen_created){
0203 BOOST_ASSERT(map_.find(mapping_address) != map_.end());
0204 *popen_created = false;
0205 }
0206
0207 return hnd_val;
0208 }
0209
0210 void *obtain_semaphore(const sync_id &id, const void *mapping_address, unsigned int initial_count, bool *popen_created = 0)
0211 {
0212 id_map_type::value_type v(id, (void*)0);
0213 scoped_lock<spin_mutex> lock(mtx_);
0214 id_map_type::iterator it = umap_.insert(v).first;
0215 void *&hnd_val = it->second;
0216 if(!hnd_val){
0217 BOOST_ASSERT(map_.find(mapping_address) == map_.end());
0218 map_[mapping_address] = id;
0219 hnd_val = open_or_create_semaphore(id, initial_count);
0220 if(popen_created) *popen_created = true;
0221 ++num_handles_;
0222 }
0223 else if(popen_created){
0224 BOOST_ASSERT(map_.find(mapping_address) != map_.end());
0225 *popen_created = false;
0226 }
0227 return hnd_val;
0228 }
0229
0230 void destroy_handle(const sync_id &id, const void *mapping_address)
0231 {
0232 scoped_lock<spin_mutex> lock(mtx_);
0233 id_map_type::iterator it = umap_.find(id);
0234 id_map_type::iterator itend = umap_.end();
0235
0236 if(it != itend){
0237 winapi::close_handle(it->second);
0238 --num_handles_;
0239 std::size_t i = map_.erase(mapping_address);
0240 (void)i;
0241 BOOST_ASSERT(i == 1);
0242 umap_.erase(it);
0243 }
0244 }
0245
0246 void destroy_syncs_in_range(const void *addr, std::size_t size)
0247 {
0248 const void *low_id(addr);
0249 const void *hig_id(static_cast<const char*>(addr)+size);
0250 scoped_lock<spin_mutex> lock(mtx_);
0251 addr_map_type::iterator itlow(map_.lower_bound(low_id)),
0252 ithig(map_.lower_bound(hig_id)),
0253 it(itlow);
0254 for (; it != ithig; ++it){
0255 sync_id ukey = it->second;
0256 id_map_type::iterator uit = umap_.find(ukey);
0257 BOOST_ASSERT(uit != umap_.end());
0258 void * const hnd = uit->second;
0259 umap_.erase(ukey);
0260 int ret = winapi::close_handle(hnd);
0261 --num_handles_;
0262 BOOST_ASSERT(ret != 0); (void)ret;
0263 }
0264
0265 map_.erase(itlow, ithig);
0266 }
0267
0268 private:
0269 spin_mutex mtx_;
0270 id_map_type umap_;
0271 addr_map_type map_;
0272 std::size_t num_handles_;
0273 };
0274
0275
0276 }
0277 }
0278 }
0279
0280 #include <boost/interprocess/detail/config_end.hpp>
0281
0282 #endif