1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/interprocess for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
12 #define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 #include <boost/interprocess/detail/win32_api.hpp>
25 #include <boost/interprocess/sync/spin/mutex.hpp>
26 #include <boost/interprocess/exceptions.hpp>
27 #include <boost/interprocess/sync/scoped_lock.hpp>
28 #include <boost/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
29 #include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
31 //Shield against external warnings
32 #include <boost/interprocess/detail/config_external_begin.hpp>
33 #include <boost/unordered/unordered_map.hpp>
34 #include <boost/interprocess/detail/config_external_end.hpp>
37 #include <boost/container/map.hpp>
41 namespace interprocess {
44 inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length)
46 const std::size_t need_mem = mem_length*2+1;
47 if(out_length < need_mem){
48 out_length = need_mem;
52 const char Characters [] =
53 { '0', '1', '2', '3', '4', '5', '6', '7'
54 , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
56 std::size_t char_counter = 0;
57 const char *buf = (const char *)mem;
58 for(std::size_t i = 0; i != mem_length; ++i){
59 out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4];
60 out_str[char_counter++] = Characters[(buf[i]&0x0F)];
62 out_str[char_counter] = 0;
69 typedef __int64 internal_type;
70 sync_id(const void *map_addr)
72 { winapi::query_performance_counter(&rand_); }
74 explicit sync_id(internal_type val, const void *map_addr)
78 const internal_type &internal_pod() const
81 internal_type &internal_pod()
84 const void *map_address() const
87 friend std::size_t hash_value(const sync_id &m)
88 { return boost::hash_value(m.rand_); }
90 friend bool operator==(const sync_id &l, const sync_id &r)
91 { return l.rand_ == r.rand_ && l.map_addr_ == r.map_addr_; }
95 const void * const map_addr_;
101 enum type { MUTEX, SEMAPHORE };
106 bool operator()(sync_id const * const l, sync_id const * const r) const
107 { return l->map_address() < r->map_address(); }
110 typedef boost::unordered_map<sync_id, void*> umap_type;
111 typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> map_type;
112 static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1;
113 static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1);
114 typedef char NameBuf[StrSize];
117 void fill_name(NameBuf &name, const sync_id &id)
119 const char *n = "Global\\boost.ipc";
125 std::size_t len = sizeof(NameBuf) - LengthOfGlobal;
126 bytes_to_str(&id.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len);
129 void throw_if_error(void *hnd_val)
132 error_info err(winapi::get_last_error());
133 throw interprocess_exception(err);
137 void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count)
141 permissions unrestricted_security;
142 unrestricted_security.set_unrestricted();
143 winapi_semaphore_wrapper sem_wrapper;
145 sem_wrapper.open_or_create
146 (name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created);
147 throw_if_error(sem_wrapper.handle());
148 return sem_wrapper.release();
151 void* open_or_create_mutex(const sync_id &id)
155 permissions unrestricted_security;
156 unrestricted_security.set_unrestricted();
157 winapi_mutex_wrapper mtx_wrapper;
158 mtx_wrapper.open_or_create(name, unrestricted_security);
159 throw_if_error(mtx_wrapper.handle());
160 return mtx_wrapper.release();
164 void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
166 umap_type::value_type v(id, (void*)0);
167 scoped_lock<spin_mutex> lock(mtx_);
168 umap_type::iterator it = umap_.insert(v).first;
169 void *&hnd_val = it->second;
171 map_[&it->first] = it;
172 hnd_val = open_or_create_mutex(id);
173 if(popen_created) *popen_created = true;
175 else if(popen_created){
176 *popen_created = false;
181 void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
183 umap_type::value_type v(id, (void*)0);
184 scoped_lock<spin_mutex> lock(mtx_);
185 umap_type::iterator it = umap_.insert(v).first;
186 void *&hnd_val = it->second;
188 map_[&it->first] = it;
189 hnd_val = open_or_create_semaphore(id, initial_count);
190 if(popen_created) *popen_created = true;
192 else if(popen_created){
193 *popen_created = false;
198 void destroy_handle(const sync_id &id)
200 scoped_lock<spin_mutex> lock(mtx_);
201 umap_type::iterator it = umap_.find(id);
202 umap_type::iterator itend = umap_.end();
205 winapi::close_handle(it->second);
206 const map_type::key_type &k = &it->first;
212 void destroy_syncs_in_range(const void *addr, std::size_t size)
214 const sync_id low_id(addr);
215 const sync_id hig_id(static_cast<const char*>(addr)+size);
216 scoped_lock<spin_mutex> lock(mtx_);
217 map_type::iterator itlow(map_.lower_bound(&low_id)),
218 ithig(map_.lower_bound(&hig_id));
219 while(itlow != ithig){
220 void * const hnd = umap_[*itlow->first];
221 winapi::close_handle(hnd);
222 umap_.erase(*itlow->first);
223 itlow = map_.erase(itlow);
234 } //namespace ipcdetail {
235 } //namespace interprocess {
236 } //namespace boost {
238 #include <boost/interprocess/detail/config_end.hpp>
240 #endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP