diff options
Diffstat (limited to 'boost/interprocess/sync/windows/sync_utils.hpp')
-rw-r--r-- | boost/interprocess/sync/windows/sync_utils.hpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/boost/interprocess/sync/windows/sync_utils.hpp b/boost/interprocess/sync/windows/sync_utils.hpp new file mode 100644 index 0000000000..89c4aeda0b --- /dev/null +++ b/boost/interprocess/sync/windows/sync_utils.hpp @@ -0,0 +1,173 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP +#define BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include <boost/interprocess/detail/config_begin.hpp> +#include <boost/interprocess/detail/workaround.hpp> +#include <boost/interprocess/detail/win32_api.hpp> +#include <boost/interprocess/sync/spin/mutex.hpp> +#include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/sync/scoped_lock.hpp> +#include <boost/unordered/unordered_map.hpp> +#include <cstddef> + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +inline bool bytes_to_str(const void *mem, const std::size_t mem_length, char *out_str, std::size_t &out_length) +{ + const std::size_t need_mem = mem_length*2+1; + if(out_length < need_mem){ + return false; + } + + const char Characters [] = + { '0', '1', '2', '3', '4', '5', '6', '7' + , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + + std::size_t char_counter = 0; + const char *buf = (const char *)mem; + for(std::size_t i = 0; i != mem_length; ++i){ + out_str[char_counter++] = Characters[(buf[i]&0xF0)>>4]; + out_str[char_counter++] = Characters[(buf[i]&0x0F)]; + } + out_str[char_counter] = 0; + return true; +} + +struct sync_id +{ + sync_id() + { winapi::query_performance_counter(&rand); } + + __int64 rand; + + friend std::size_t hash_value(const sync_id &m) + { return boost::hash_value(m.rand); } + + friend bool operator==(const sync_id &l, const sync_id &r) + { return l.rand == r.rand; } +}; +/* +#define BOOST_NO_LONG_LONG ss + +#if defined(BOOST_NO_LONG_LONG) + +#error "defined(BOOST_NO_LONG_LONG)" +#else +#error "NOT defined(BOOST_NO_LONG_LONG)" +#endif +*/ +class sync_handles +{ + public: + enum type { MUTEX, SEMAPHORE }; + + private: + typedef boost::unordered_map<sync_id, void*> map_type; + static const std::size_t LengthOfGlobal = sizeof("Global\\boost.ipc")-1; + static const std::size_t StrSize = LengthOfGlobal + (sizeof(sync_id)*2+1); + typedef char NameBuf[StrSize]; + + void fill_name(NameBuf &name, const sync_id &id) + { + const char *n = "Global\\boost.ipc"; + std::size_t i = 0; + do{ + name[i] = n[i]; + ++i; + } while(n[i]); + std::size_t len = sizeof(NameBuf) - LengthOfGlobal; + bytes_to_str(&id.rand, sizeof(id.rand), &name[LengthOfGlobal], len); + } + + void erase_and_throw_if_error(void *hnd_val, const sync_id &id) + { + if(!hnd_val){ + map_.erase(id); + error_info err(winapi::get_last_error()); + throw interprocess_exception(err); + } + } + + void* open_or_create_semaphore(const sync_id &id, unsigned int initial_count) + { + NameBuf name; + fill_name(name, id); + void *hnd_val = winapi::open_or_create_semaphore + (name, (long)initial_count, (long)(((unsigned long)(-1))>>1), unrestricted_security.get_attributes()); + erase_and_throw_if_error(hnd_val, id); + return hnd_val; + } + + void* open_or_create_mutex(const sync_id &id) + { + NameBuf name; + fill_name(name, id); + void *hnd_val = winapi::open_or_create_mutex + (name, false, unrestricted_security.get_attributes()); + erase_and_throw_if_error(hnd_val, id); + return hnd_val; + } + + public: + void *obtain_mutex(const sync_id &id, bool *popen_created = 0) + { + scoped_lock<spin_mutex> lock(mtx_); + void *&hnd_val = map_[id]; + if(!hnd_val){ + hnd_val = open_or_create_mutex(id); + if(popen_created) *popen_created = true; + } + return hnd_val; + } + + void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0) + { + scoped_lock<spin_mutex> lock(mtx_); + void *&hnd_val = map_[id]; + if(!hnd_val){ + hnd_val = open_or_create_semaphore(id, initial_count); + if(popen_created) *popen_created = true; + } + return hnd_val; + } + + void destroy_handle(const sync_id &id) + { + scoped_lock<spin_mutex> lock(mtx_); + map_type::iterator it = map_.find(id); + if(it != map_.end()){ + winapi::close_handle(it->second); + map_.erase(it); + } + } + + private: + winapi::interprocess_all_access_security unrestricted_security; + spin_mutex mtx_; + map_type map_; +}; + + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include <boost/interprocess/detail/config_end.hpp> + +#endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP |