Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-11 08:50:42

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2011-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_WINDOWS_NAMED_SYNC_HPP
0012 #define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_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/creation_tags.hpp>
0026 #include <boost/interprocess/permissions.hpp>
0027 #include <boost/interprocess/detail/shared_dir_helpers.hpp>
0028 #include <boost/interprocess/sync/windows/sync_utils.hpp>
0029 #include <boost/interprocess/errors.hpp>
0030 #include <boost/interprocess/exceptions.hpp>
0031 #include <string>
0032 #include <boost/assert.hpp>
0033 
0034 namespace boost {
0035 namespace interprocess {
0036 namespace ipcdetail {
0037 
0038 class windows_named_sync_interface
0039 {
0040    public:
0041    virtual std::size_t get_data_size() const = 0;
0042    virtual const void *buffer_with_final_data_to_file() = 0;
0043    virtual const void *buffer_with_init_data_to_file() = 0;
0044    virtual void *buffer_to_store_init_data_from_file() = 0;
0045    virtual bool open(create_enum_t creation_type, const char *id_name) = 0;
0046    virtual bool open(create_enum_t creation_type, const wchar_t *id_name) = 0;
0047    virtual void close() = 0;
0048    virtual ~windows_named_sync_interface() = 0;
0049 };
0050 
0051 inline windows_named_sync_interface::~windows_named_sync_interface()
0052 {}
0053 
0054 class windows_named_sync
0055 {
0056    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0057 
0058    //Non-copyable
0059    windows_named_sync(const windows_named_sync &);
0060    windows_named_sync &operator=(const windows_named_sync &);
0061    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0062 
0063    public:
0064    windows_named_sync();
0065    template <class CharT>
0066    void open_or_create(create_enum_t creation_type, const CharT *name, const permissions &perm, windows_named_sync_interface &sync_interface);
0067    void close(windows_named_sync_interface &sync_interface);
0068 
0069    static bool remove(const char *name);
0070    static bool remove(const wchar_t *name);
0071 
0072    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0073    private:
0074    void *m_file_hnd;
0075 
0076    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0077 };
0078 
0079 inline windows_named_sync::windows_named_sync()
0080    : m_file_hnd(winapi::invalid_handle_value)
0081 {}
0082 
0083 inline void windows_named_sync::close(windows_named_sync_interface &sync_interface)
0084 {
0085    const unsigned long buflen = static_cast<unsigned long>(sync_interface.get_data_size());
0086    winapi::interprocess_overlapped overlapped;
0087    if(winapi::lock_file_ex
0088       (m_file_hnd, winapi::lockfile_exclusive_lock, 0, 1, 0, &overlapped)){
0089       if(winapi::set_file_pointer(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){
0090          const void *buf = sync_interface.buffer_with_final_data_to_file();
0091 
0092          unsigned long written_or_read = 0;
0093          if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){
0094             //...
0095          }
0096       }
0097    }
0098    sync_interface.close();
0099    //close_handle unlocks the lock
0100    if(m_file_hnd != winapi::invalid_handle_value){
0101       winapi::close_handle(m_file_hnd);
0102       m_file_hnd = winapi::invalid_handle_value;
0103    }
0104 }
0105 
0106 template <class CharT>
0107 inline void windows_named_sync::open_or_create
0108    ( create_enum_t creation_type
0109    , const CharT *name
0110    , const permissions &perm
0111    , windows_named_sync_interface &sync_interface)
0112 {
0113    std::basic_string<CharT> aux_str(name);
0114    m_file_hnd  = winapi::invalid_handle_value;
0115    //Use a file to emulate POSIX lifetime semantics. After this logic
0116    //we'll obtain the ID of the native handle to open in aux_str
0117    {
0118       create_shared_dir_cleaning_old_and_get_filepath(name, aux_str);
0119       //Create a file with required permissions.
0120       m_file_hnd = winapi::create_file
0121          ( aux_str.c_str()
0122          , winapi::generic_read | winapi::generic_write
0123          , creation_type == DoOpen ? winapi::open_existing :
0124                (creation_type == DoCreate ? winapi::create_new : winapi::open_always)
0125          , 0
0126          , (winapi::interprocess_security_attributes*)perm.get_permissions());
0127 
0128       //Obtain OS error in case something has failed
0129       error_info err;
0130       bool success = false;
0131       if(m_file_hnd != winapi::invalid_handle_value){
0132          //Now lock the file
0133          const unsigned long buflen = static_cast<unsigned long>(sync_interface.get_data_size());
0134          typedef __int64 unique_id_type;
0135          const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen;
0136          winapi::interprocess_overlapped overlapped;
0137          if(winapi::lock_file_ex
0138             (m_file_hnd, winapi::lockfile_exclusive_lock, 0, 1, 0, &overlapped)){
0139             __int64 filesize = 0;
0140             //Obtain the unique id to open the native semaphore.
0141             //If file size was created
0142             if(winapi::get_file_size(m_file_hnd, filesize)){
0143                unsigned long written_or_read = 0;
0144                unique_id_type unique_id_val;
0145                if(static_cast<std::size_t>(filesize) != sizeof_file_info){
0146                   winapi::set_end_of_file(m_file_hnd);
0147                   winapi::query_performance_counter(&unique_id_val);
0148                   const void *buf = sync_interface.buffer_with_init_data_to_file();
0149                   //Write unique ID in file. This ID will be used to calculate the semaphore name
0150                   if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0)  &&
0151                      written_or_read == sizeof(unique_id_val) &&
0152                      winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) &&
0153                      written_or_read == buflen ){
0154                      success = true;
0155                   }
0156                   winapi::get_file_size(m_file_hnd, filesize);
0157                   BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info);
0158                }
0159                else{
0160                   void *buf = sync_interface.buffer_to_store_init_data_from_file();
0161                   if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0)  &&
0162                      written_or_read == sizeof(unique_id_val) &&
0163                      winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0)  &&
0164                      written_or_read == buflen   ){
0165                      success = true;
0166                   }
0167                }
0168                if(success){
0169                   //Now create a global semaphore name based on the unique id
0170                   CharT unique_id_name[sizeof(unique_id_val)*2+1];
0171                   std::size_t name_suffix_length = sizeof(unique_id_name);
0172                   bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length);
0173                   success = sync_interface.open(creation_type, unique_id_name);
0174                }
0175             }
0176 
0177             //Obtain OS error in case something has failed
0178             if(!success)
0179                err = system_error_code();
0180 
0181             //If this fails we have no possible rollback so don't check the return
0182             if(!winapi::unlock_file_ex(m_file_hnd, 0, 1, 0, &overlapped)){
0183                err = system_error_code();
0184             }
0185          }
0186          else{
0187             //Obtain OS error in case something has failed
0188             err = system_error_code();
0189          }
0190       }
0191       else{
0192          err = system_error_code();
0193       }
0194 
0195       if(!success){
0196          if(m_file_hnd != winapi::invalid_handle_value){
0197             winapi::close_handle(m_file_hnd);
0198             m_file_hnd = winapi::invalid_handle_value;
0199          }
0200          //Throw as something went wrong
0201          throw interprocess_exception(err);
0202       }
0203    }
0204 }
0205 
0206 inline bool windows_named_sync::remove(const char *name)
0207 {
0208    BOOST_INTERPROCESS_TRY{
0209       //Make sure a temporary path is created for shared memory
0210       std::string semfile;
0211       ipcdetail::shared_filepath(name, semfile);
0212       return winapi::unlink_file(semfile.c_str());
0213    }
0214    BOOST_INTERPROCESS_CATCH(...){
0215       return false;
0216    } BOOST_INTERPROCESS_CATCH_END
0217 }
0218 
0219 inline bool windows_named_sync::remove(const wchar_t *name)
0220 {
0221    BOOST_INTERPROCESS_TRY{
0222       //Make sure a temporary path is created for shared memory
0223       std::wstring semfile;
0224       ipcdetail::shared_filepath(name, semfile);
0225       return winapi::unlink_file(semfile.c_str());
0226    }
0227    BOOST_INTERPROCESS_CATCH(...){
0228       return false;
0229    } BOOST_INTERPROCESS_CATCH_END
0230 }
0231 
0232 }  //namespace ipcdetail {
0233 }  //namespace interprocess {
0234 }  //namespace boost {
0235 
0236 #include <boost/interprocess/detail/config_end.hpp>
0237 
0238 #endif   //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP