Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-08 08:23:08

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 ">#
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 //Shield against external warnings
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    //key: id -> mapped: HANDLE. Hash map to allow efficient sync operations
0125    typedef boost::container::flat_map<sync_id, void*> id_map_type;
0126    //key: ordered address of the sync type -> key from id_map_type. Ordered map to allow closing handles when unmapping
0127    // Can't store iterators into id_map_type because they would get invalidated.
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); //Sanity check that handle we don't leak handles
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);   //The entry should be there
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;  //Sanity check that handle was ok
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 }  //namespace ipcdetail {
0277 }  //namespace interprocess {
0278 }  //namespace boost {
0279 
0280 #include <boost/interprocess/detail/config_end.hpp>
0281 
0282 #endif   //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP