annotate DEPENDENCIES/generic/include/boost/interprocess/sync/windows/sync_utils.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //////////////////////////////////////////////////////////////////////////////
Chris@16 2 //
Chris@16 3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
Chris@16 4 // Software License, Version 1.0. (See accompanying file
Chris@16 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6 //
Chris@16 7 // See http://www.boost.org/libs/interprocess for documentation.
Chris@16 8 //
Chris@16 9 //////////////////////////////////////////////////////////////////////////////
Chris@16 10
Chris@16 11 #ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
Chris@16 12 #define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
Chris@16 13
Chris@101 14 #ifndef BOOST_CONFIG_HPP
Chris@101 15 # include <boost/config.hpp>
Chris@101 16 #endif
Chris@101 17 #
Chris@101 18 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@16 19 # pragma once
Chris@16 20 #endif
Chris@16 21
Chris@16 22 #include <boost/interprocess/detail/config_begin.hpp>
Chris@16 23 #include <boost/interprocess/detail/workaround.hpp>
Chris@16 24 #include <boost/interprocess/detail/win32_api.hpp>
Chris@16 25 #include <boost/interprocess/sync/spin/mutex.hpp>
Chris@16 26 #include <boost/interprocess/exceptions.hpp>
Chris@16 27 #include <boost/interprocess/sync/scoped_lock.hpp>
Chris@16 28 #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
Chris@16 29 #include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
Chris@16 30
Chris@16 31 //Shield against external warnings
Chris@16 32 #include <boost/interprocess/detail/config_external_begin.hpp>
Chris@16 33 #include <boost/unordered/unordered_map.hpp>
Chris@16 34 #include <boost/interprocess/detail/config_external_end.hpp>
Chris@16 35
Chris@16 36
Chris@16 37 #include <boost/container/map.hpp>
Chris@16 38 #include <cstddef>
Chris@16 39
Chris@16 40 namespace boost {
Chris@16 41 namespace interprocess {
Chris@16 42 namespace ipcdetail {
Chris@16 43
Chris@16 44 inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length)
Chris@16 45 {
Chris@16 46 const std::size_t need_mem = mem_length*2+1;
Chris@16 47 if(out_length < need_mem){
Chris@16 48 out_length = need_mem;
Chris@16 49 return false;
Chris@16 50 }
Chris@16 51
Chris@16 52 const char Characters [] =
Chris@16 53 { '0', '1', '2', '3', '4', '5', '6', '7'
Chris@16 54 , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
Chris@16 55
Chris@16 56 std::size_t char_counter = 0;
Chris@16 57 const char *buf = (const char *)mem;
Chris@16 58 for(std::size_t i = 0; i != mem_length; ++i){
Chris@16 59 out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
Chris@16 60 out_str[char_counter++] = Characters[(buf[i]&0x0F)];
Chris@16 61 }
Chris@16 62 out_str[char_counter] = 0;
Chris@16 63 return true;
Chris@16 64 }
Chris@16 65
Chris@16 66 class sync_id
Chris@16 67 {
Chris@16 68 public:
Chris@16 69 typedef __int64 internal_type;
Chris@16 70 sync_id(const void *map_addr)
Chris@16 71 : map_addr_(map_addr)
Chris@16 72 { winapi::query_performance_counter(&rand_); }
Chris@16 73
Chris@16 74 explicit sync_id(internal_type val, const void *map_addr)
Chris@16 75 : map_addr_(map_addr)
Chris@16 76 { rand_ = val; }
Chris@16 77
Chris@16 78 const internal_type &internal_pod() const
Chris@16 79 { return rand_; }
Chris@16 80
Chris@16 81 internal_type &internal_pod()
Chris@16 82 { return rand_; }
Chris@16 83
Chris@16 84 const void *map_address() const
Chris@16 85 { return map_addr_; }
Chris@16 86
Chris@16 87 friend std::size_t hash_value(const sync_id &m)
Chris@16 88 { return boost::hash_value(m.rand_); }
Chris@16 89
Chris@16 90 friend bool operator==(const sync_id &l, const sync_id &r)
Chris@16 91 { return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; }
Chris@16 92
Chris@16 93 private:
Chris@16 94 internal_type rand_;
Chris@16 95 const void * const map_addr_;
Chris@16 96 };
Chris@16 97
Chris@16 98 class sync_handles
Chris@16 99 {
Chris@16 100 public:
Chris@16 101 enum type { MUTEX, SEMAPHORE };
Chris@16 102
Chris@16 103 private:
Chris@16 104 struct address_less
Chris@16 105 {
Chris@16 106 bool operator()(sync_id const * const l, sync_id const * const r) const
Chris@16 107 { return l->map_address() < r->map_address(); }
Chris@16 108 };
Chris@16 109
Chris@16 110 typedef boost::unordered_map<sync_id, void*> umap_type;
Chris@16 111 typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> map_type;
Chris@16 112 static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
Chris@16 113 static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
Chris@16 114 typedef char NameBuf[StrSize];
Chris@16 115
Chris@16 116
Chris@16 117 void fill_name(NameBuf &name, const sync_id &id)
Chris@16 118 {
Chris@16 119 const char *n = "Global\\boost.ipc";
Chris@16 120 std::size_t i = 0;
Chris@16 121 do{
Chris@16 122 name[i] = n[i];
Chris@16 123 ++i;
Chris@16 124 } while(n[i]);
Chris@16 125 std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
Chris@16 126 bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len);
Chris@16 127 }
Chris@16 128
Chris@16 129 void throw_if_error(void *hnd_val)
Chris@16 130 {
Chris@16 131 if(!hnd_val){
Chris@16 132 error_info err(winapi::get_last_error());
Chris@16 133 throw interprocess_exception(err);
Chris@16 134 }
Chris@16 135 }
Chris@16 136
Chris@16 137 void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count)
Chris@16 138 {
Chris@16 139 NameBuf name;
Chris@16 140 fill_name(name, id);
Chris@16 141 permissions unrestricted_security;
Chris@16 142 unrestricted_security.set_unrestricted();
Chris@16 143 winapi_semaphore_wrapper sem_wrapper;
Chris@16 144 bool created;
Chris@16 145 sem_wrapper.open_or_create
Chris@16 146 (name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created);
Chris@16 147 throw_if_error(sem_wrapper.handle());
Chris@16 148 return sem_wrapper.release();
Chris@16 149 }
Chris@16 150
Chris@16 151 void* open_or_create_mutex(const sync_id &id)
Chris@16 152 {
Chris@16 153 NameBuf name;
Chris@16 154 fill_name(name, id);
Chris@16 155 permissions unrestricted_security;
Chris@16 156 unrestricted_security.set_unrestricted();
Chris@16 157 winapi_mutex_wrapper mtx_wrapper;
Chris@16 158 mtx_wrapper.open_or_create(name, unrestricted_security);
Chris@16 159 throw_if_error(mtx_wrapper.handle());
Chris@16 160 return mtx_wrapper.release();
Chris@16 161 }
Chris@16 162
Chris@16 163 public:
Chris@16 164 void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
Chris@16 165 {
Chris@16 166 umap_type::value_type v(id, (void*)0);
Chris@16 167 scoped_lock<spin_mutex> lock(mtx_);
Chris@16 168 umap_type::iterator it = umap_.insert(v).first;
Chris@16 169 void *&hnd_val = it->second;
Chris@16 170 if(!hnd_val){
Chris@16 171 map_[&it->first] = it;
Chris@16 172 hnd_val = open_or_create_mutex(id);
Chris@16 173 if(popen_created) *popen_created = true;
Chris@16 174 }
Chris@16 175 else if(popen_created){
Chris@16 176 *popen_created = false;
Chris@16 177 }
Chris@16 178 return hnd_val;
Chris@16 179 }
Chris@16 180
Chris@16 181 void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
Chris@16 182 {
Chris@16 183 umap_type::value_type v(id, (void*)0);
Chris@16 184 scoped_lock<spin_mutex> lock(mtx_);
Chris@16 185 umap_type::iterator it = umap_.insert(v).first;
Chris@16 186 void *&hnd_val = it->second;
Chris@16 187 if(!hnd_val){
Chris@16 188 map_[&it->first] = it;
Chris@16 189 hnd_val = open_or_create_semaphore(id, initial_count);
Chris@16 190 if(popen_created) *popen_created = true;
Chris@16 191 }
Chris@16 192 else if(popen_created){
Chris@16 193 *popen_created = false;
Chris@16 194 }
Chris@16 195 return hnd_val;
Chris@16 196 }
Chris@16 197
Chris@16 198 void destroy_handle(const sync_id &id)
Chris@16 199 {
Chris@16 200 scoped_lock<spin_mutex> lock(mtx_);
Chris@16 201 umap_type::iterator it = umap_.find(id);
Chris@16 202 umap_type::iterator itend = umap_.end();
Chris@16 203
Chris@16 204 if(it != itend){
Chris@16 205 winapi::close_handle(it->second);
Chris@16 206 const map_type::key_type &k = &it->first;
Chris@16 207 map_.erase(k);
Chris@16 208 umap_.erase(it);
Chris@16 209 }
Chris@16 210 }
Chris@16 211
Chris@16 212 void destroy_syncs_in_range(const void *addr, std::size_t size)
Chris@16 213 {
Chris@16 214 const sync_id low_id(addr);
Chris@16 215 const sync_id hig_id(static_cast<const char*>(addr)+size);
Chris@16 216 scoped_lock<spin_mutex> lock(mtx_);
Chris@16 217 map_type::iterator itlow(map_.lower_bound(&low_id)),
Chris@16 218 ithig(map_.lower_bound(&hig_id));
Chris@16 219 while(itlow != ithig){
Chris@16 220 void * const hnd = umap_[*itlow->first];
Chris@16 221 winapi::close_handle(hnd);
Chris@16 222 umap_.erase(*itlow->first);
Chris@16 223 itlow = map_.erase(itlow);
Chris@16 224 }
Chris@16 225 }
Chris@16 226
Chris@16 227 private:
Chris@16 228 spin_mutex mtx_;
Chris@16 229 umap_type umap_;
Chris@16 230 map_type map_;
Chris@16 231 };
Chris@16 232
Chris@16 233
Chris@16 234 } //namespace ipcdetail {
Chris@16 235 } //namespace interprocess {
Chris@16 236 } //namespace boost {
Chris@16 237
Chris@16 238 #include <boost/interprocess/detail/config_end.hpp>
Chris@16 239
Chris@16 240 #endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP