Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-09 08:13:44

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