mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-06-05 23:44:56 -04:00
Squashed 'boost/' content from commit b4feb19f2
git-subtree-dir: boost git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2012. 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_WINDOWS_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/detail/windows_intermodule_singleton.hpp>
|
||||
#include <boost/interprocess/sync/windows/sync_utils.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class windows_mutex
|
||||
{
|
||||
windows_mutex(const windows_mutex &);
|
||||
windows_mutex &operator=(const windows_mutex &);
|
||||
public:
|
||||
|
||||
windows_mutex();
|
||||
~windows_mutex();
|
||||
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
void take_ownership(){};
|
||||
|
||||
private:
|
||||
const sync_id id_;
|
||||
};
|
||||
|
||||
inline windows_mutex::windows_mutex()
|
||||
: id_(this)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//Create mutex with the initial count
|
||||
bool open_or_created;
|
||||
(void)handles.obtain_mutex(this->id_, &open_or_created);
|
||||
//The mutex must be created, never opened
|
||||
BOOST_ASSERT(open_or_created);
|
||||
BOOST_ASSERT(open_or_created && winapi::get_last_error() != winapi::error_already_exists);
|
||||
(void)open_or_created;
|
||||
}
|
||||
|
||||
inline windows_mutex::~windows_mutex()
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
handles.destroy_handle(this->id_);
|
||||
}
|
||||
|
||||
inline void windows_mutex::lock(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
mut.lock();
|
||||
}
|
||||
|
||||
inline bool windows_mutex::try_lock(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
return mut.try_lock();
|
||||
}
|
||||
|
||||
inline bool windows_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
return mut.timed_lock(abs_time);
|
||||
}
|
||||
|
||||
inline void windows_mutex::unlock(void)
|
||||
{
|
||||
sync_handles &handles =
|
||||
windows_intermodule_singleton<sync_handles>::get();
|
||||
//This can throw
|
||||
winapi_mutex_functions mut(handles.obtain_mutex(this->id_));
|
||||
return mut.unlock();
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINDOWS_MUTEX_HPP
|
||||
@@ -0,0 +1,179 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_MUTEX_HPP
|
||||
#define BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/windows/sync_utils.hpp>
|
||||
#include <boost/interprocess/sync/windows/named_sync.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
|
||||
|
||||
class windows_named_mutex
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_mutex();
|
||||
windows_named_mutex(const windows_named_mutex &);
|
||||
windows_named_mutex &operator=(const windows_named_mutex &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
windows_named_mutex(create_only_t, const char *name, const permissions &perm = permissions());
|
||||
|
||||
windows_named_mutex(open_or_create_t, const char *name, const permissions &perm = permissions());
|
||||
|
||||
windows_named_mutex(open_only_t, const char *name);
|
||||
|
||||
~windows_named_mutex();
|
||||
|
||||
void unlock();
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
friend class interprocess_tester;
|
||||
void dont_close_on_destruction();
|
||||
winapi_mutex_wrapper m_mtx_wrapper;
|
||||
windows_named_sync m_named_sync;
|
||||
|
||||
class named_mut_callbacks : public windows_named_sync_interface
|
||||
{
|
||||
public:
|
||||
named_mut_callbacks(winapi_mutex_wrapper &mtx_wrapper)
|
||||
: m_mtx_wrapper(mtx_wrapper)
|
||||
{}
|
||||
|
||||
virtual std::size_t get_data_size() const
|
||||
{ return 0u; }
|
||||
|
||||
virtual const void *buffer_with_init_data_to_file()
|
||||
{ return 0; }
|
||||
|
||||
virtual const void *buffer_with_final_data_to_file()
|
||||
{ return 0; }
|
||||
|
||||
virtual void *buffer_to_store_init_data_from_file()
|
||||
{ return 0; }
|
||||
|
||||
virtual bool open(create_enum_t, const char *id_name)
|
||||
{
|
||||
std::string aux_str = "Global\\bipc.mut.";
|
||||
aux_str += id_name;
|
||||
//
|
||||
permissions mut_perm;
|
||||
mut_perm.set_unrestricted();
|
||||
return m_mtx_wrapper.open_or_create(aux_str.c_str(), mut_perm);
|
||||
}
|
||||
|
||||
virtual void close()
|
||||
{
|
||||
m_mtx_wrapper.close();
|
||||
}
|
||||
|
||||
virtual ~named_mut_callbacks()
|
||||
{}
|
||||
|
||||
private:
|
||||
winapi_mutex_wrapper& m_mtx_wrapper;
|
||||
};
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
inline windows_named_mutex::~windows_named_mutex()
|
||||
{
|
||||
named_mut_callbacks callbacks(m_mtx_wrapper);
|
||||
m_named_sync.close(callbacks);
|
||||
}
|
||||
|
||||
inline void windows_named_mutex::dont_close_on_destruction()
|
||||
{}
|
||||
|
||||
inline windows_named_mutex::windows_named_mutex
|
||||
(create_only_t, const char *name, const permissions &perm)
|
||||
: m_mtx_wrapper()
|
||||
{
|
||||
named_mut_callbacks callbacks(m_mtx_wrapper);
|
||||
m_named_sync.open_or_create(DoCreate, name, perm, callbacks);
|
||||
}
|
||||
|
||||
inline windows_named_mutex::windows_named_mutex
|
||||
(open_or_create_t, const char *name, const permissions &perm)
|
||||
: m_mtx_wrapper()
|
||||
{
|
||||
named_mut_callbacks callbacks(m_mtx_wrapper);
|
||||
m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks);
|
||||
}
|
||||
|
||||
inline windows_named_mutex::windows_named_mutex(open_only_t, const char *name)
|
||||
: m_mtx_wrapper()
|
||||
{
|
||||
named_mut_callbacks callbacks(m_mtx_wrapper);
|
||||
m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks);
|
||||
}
|
||||
|
||||
inline void windows_named_mutex::unlock()
|
||||
{
|
||||
m_mtx_wrapper.unlock();
|
||||
}
|
||||
|
||||
inline void windows_named_mutex::lock()
|
||||
{
|
||||
m_mtx_wrapper.lock();
|
||||
}
|
||||
|
||||
inline bool windows_named_mutex::try_lock()
|
||||
{
|
||||
return m_mtx_wrapper.try_lock();
|
||||
}
|
||||
|
||||
inline bool windows_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
return m_mtx_wrapper.timed_lock(abs_time);
|
||||
}
|
||||
|
||||
inline bool windows_named_mutex::remove(const char *name)
|
||||
{
|
||||
return windows_named_sync::remove(name);
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_MUTEX_HPP
|
||||
@@ -0,0 +1,219 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_SYNC_HPP
|
||||
#define BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/shared_dir_helpers.hpp>
|
||||
#include <boost/interprocess/sync/windows/sync_utils.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <string>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class windows_named_sync_interface
|
||||
{
|
||||
public:
|
||||
virtual std::size_t get_data_size() const = 0;
|
||||
virtual const void *buffer_with_final_data_to_file() = 0;
|
||||
virtual const void *buffer_with_init_data_to_file() = 0;
|
||||
virtual void *buffer_to_store_init_data_from_file() = 0;
|
||||
virtual bool open(create_enum_t creation_type, const char *id_name) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual ~windows_named_sync_interface() = 0;
|
||||
};
|
||||
|
||||
inline windows_named_sync_interface::~windows_named_sync_interface()
|
||||
{}
|
||||
|
||||
class windows_named_sync
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
windows_named_sync(const windows_named_sync &);
|
||||
windows_named_sync &operator=(const windows_named_sync &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
windows_named_sync();
|
||||
void open_or_create(create_enum_t creation_type, const char *name, const permissions &perm, windows_named_sync_interface &sync_interface);
|
||||
void close(windows_named_sync_interface &sync_interface);
|
||||
|
||||
static bool remove(const char *name);
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
private:
|
||||
void *m_file_hnd;
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
inline windows_named_sync::windows_named_sync()
|
||||
: m_file_hnd(winapi::invalid_handle_value)
|
||||
{}
|
||||
|
||||
inline void windows_named_sync::close(windows_named_sync_interface &sync_interface)
|
||||
{
|
||||
const std::size_t buflen = sync_interface.get_data_size();
|
||||
const std::size_t sizeof_file_info = sizeof(sync_id::internal_type) + buflen;
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
if(winapi::lock_file_ex
|
||||
(m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){
|
||||
if(winapi::set_file_pointer_ex(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){
|
||||
const void *buf = sync_interface.buffer_with_final_data_to_file();
|
||||
|
||||
unsigned long written_or_read = 0;
|
||||
if(winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0)){
|
||||
//...
|
||||
}
|
||||
}
|
||||
}
|
||||
sync_interface.close();
|
||||
if(m_file_hnd != winapi::invalid_handle_value){
|
||||
winapi::close_handle(m_file_hnd);
|
||||
m_file_hnd = winapi::invalid_handle_value;
|
||||
}
|
||||
}
|
||||
|
||||
inline void windows_named_sync::open_or_create
|
||||
( create_enum_t creation_type
|
||||
, const char *name
|
||||
, const permissions &perm
|
||||
, windows_named_sync_interface &sync_interface)
|
||||
{
|
||||
std::string aux_str(name);
|
||||
m_file_hnd = winapi::invalid_handle_value;
|
||||
//Use a file to emulate POSIX lifetime semantics. After this logic
|
||||
//we'll obtain the ID of the native handle to open in aux_str
|
||||
{
|
||||
create_shared_dir_cleaning_old_and_get_filepath(name, aux_str);
|
||||
//Create a file with required permissions.
|
||||
m_file_hnd = winapi::create_file
|
||||
( aux_str.c_str()
|
||||
, winapi::generic_read | winapi::generic_write
|
||||
, creation_type == DoOpen ? winapi::open_existing :
|
||||
(creation_type == DoCreate ? winapi::create_new : winapi::open_always)
|
||||
, 0
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions());
|
||||
|
||||
//Obtain OS error in case something has failed
|
||||
error_info err;
|
||||
bool success = false;
|
||||
if(m_file_hnd != winapi::invalid_handle_value){
|
||||
//Now lock the file
|
||||
const std::size_t buflen = sync_interface.get_data_size();
|
||||
typedef __int64 unique_id_type;
|
||||
const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen;
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
if(winapi::lock_file_ex
|
||||
(m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){
|
||||
__int64 filesize = 0;
|
||||
//Obtain the unique id to open the native semaphore.
|
||||
//If file size was created
|
||||
if(winapi::get_file_size(m_file_hnd, filesize)){
|
||||
unsigned long written_or_read = 0;
|
||||
unique_id_type unique_id_val;
|
||||
if(static_cast<std::size_t>(filesize) != sizeof_file_info){
|
||||
winapi::set_end_of_file(m_file_hnd);
|
||||
winapi::query_performance_counter(&unique_id_val);
|
||||
const void *buf = sync_interface.buffer_with_init_data_to_file();
|
||||
//Write unique ID in file. This ID will be used to calculate the semaphore name
|
||||
if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) &&
|
||||
written_or_read == sizeof(unique_id_val) &&
|
||||
winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) &&
|
||||
written_or_read == buflen ){
|
||||
success = true;
|
||||
}
|
||||
winapi::get_file_size(m_file_hnd, filesize);
|
||||
BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info);
|
||||
}
|
||||
else{
|
||||
void *buf = sync_interface.buffer_to_store_init_data_from_file();
|
||||
if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0) &&
|
||||
written_or_read == sizeof(unique_id_val) &&
|
||||
winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0) &&
|
||||
written_or_read == buflen ){
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
if(success){
|
||||
//Now create a global semaphore name based on the unique id
|
||||
char unique_id_name[sizeof(unique_id_val)*2+1];
|
||||
std::size_t name_suffix_length = sizeof(unique_id_name);
|
||||
bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length);
|
||||
success = sync_interface.open(creation_type, unique_id_name);
|
||||
}
|
||||
}
|
||||
|
||||
//Obtain OS error in case something has failed
|
||||
err = system_error_code();
|
||||
|
||||
//If this fails we have no possible rollback so don't check the return
|
||||
if(!winapi::unlock_file_ex(m_file_hnd, 0, sizeof_file_info, 0, &overlapped)){
|
||||
err = system_error_code();
|
||||
}
|
||||
}
|
||||
else{
|
||||
//Obtain OS error in case something has failed
|
||||
err = system_error_code();
|
||||
}
|
||||
}
|
||||
else{
|
||||
err = system_error_code();
|
||||
}
|
||||
|
||||
if(!success){
|
||||
if(m_file_hnd != winapi::invalid_handle_value){
|
||||
winapi::close_handle(m_file_hnd);
|
||||
m_file_hnd = winapi::invalid_handle_value;
|
||||
}
|
||||
//Throw as something went wrong
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool windows_named_sync::remove(const char *name)
|
||||
{
|
||||
try{
|
||||
//Make sure a temporary path is created for shared memory
|
||||
std::string semfile;
|
||||
ipcdetail::shared_filepath(name, semfile);
|
||||
return winapi::unlink_file(semfile.c_str());
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_SYNC_HPP
|
||||
@@ -0,0 +1,240 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2012. 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
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/interprocess/sync/windows/winapi_semaphore_wrapper.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_mutex_wrapper.hpp>
|
||||
|
||||
//Shield against external warnings
|
||||
#include <boost/interprocess/detail/config_external_begin.hpp>
|
||||
#include <boost/unordered/unordered_map.hpp>
|
||||
#include <boost/interprocess/detail/config_external_end.hpp>
|
||||
|
||||
|
||||
#include <boost/container/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){
|
||||
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;
|
||||
}
|
||||
|
||||
class sync_id
|
||||
{
|
||||
public:
|
||||
typedef __int64 internal_type;
|
||||
sync_id(const void *map_addr)
|
||||
: map_addr_(map_addr)
|
||||
{ winapi::query_performance_counter(&rand_); }
|
||||
|
||||
explicit sync_id(internal_type val, const void *map_addr)
|
||||
: map_addr_(map_addr)
|
||||
{ rand_ = val; }
|
||||
|
||||
const internal_type &internal_pod() const
|
||||
{ return rand_; }
|
||||
|
||||
internal_type &internal_pod()
|
||||
{ return rand_; }
|
||||
|
||||
const void *map_address() const
|
||||
{ return map_addr_; }
|
||||
|
||||
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_ && l.map_addr_ == r.map_addr_; }
|
||||
|
||||
private:
|
||||
internal_type rand_;
|
||||
const void * const map_addr_;
|
||||
};
|
||||
|
||||
class sync_handles
|
||||
{
|
||||
public:
|
||||
enum type { MUTEX, SEMAPHORE };
|
||||
|
||||
private:
|
||||
struct address_less
|
||||
{
|
||||
bool operator()(sync_id const * const l, sync_id const * const r) const
|
||||
{ return l->map_address() < r->map_address(); }
|
||||
};
|
||||
|
||||
typedef boost::unordered_map<sync_id, void*> umap_type;
|
||||
typedef boost::container::map<const sync_id*, umap_type::iterator, address_less> 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.internal_pod(), sizeof(id.internal_pod()), &name[LengthOfGlobal], len);
|
||||
}
|
||||
|
||||
void throw_if_error(void *hnd_val)
|
||||
{
|
||||
if(!hnd_val){
|
||||
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);
|
||||
permissions unrestricted_security;
|
||||
unrestricted_security.set_unrestricted();
|
||||
winapi_semaphore_wrapper sem_wrapper;
|
||||
bool created;
|
||||
sem_wrapper.open_or_create
|
||||
(name, (long)initial_count, winapi_semaphore_wrapper::MaxCount, unrestricted_security, created);
|
||||
throw_if_error(sem_wrapper.handle());
|
||||
return sem_wrapper.release();
|
||||
}
|
||||
|
||||
void* open_or_create_mutex(const sync_id &id)
|
||||
{
|
||||
NameBuf name;
|
||||
fill_name(name, id);
|
||||
permissions unrestricted_security;
|
||||
unrestricted_security.set_unrestricted();
|
||||
winapi_mutex_wrapper mtx_wrapper;
|
||||
mtx_wrapper.open_or_create(name, unrestricted_security);
|
||||
throw_if_error(mtx_wrapper.handle());
|
||||
return mtx_wrapper.release();
|
||||
}
|
||||
|
||||
public:
|
||||
void *obtain_mutex(const sync_id &id, bool *popen_created = 0)
|
||||
{
|
||||
umap_type::value_type v(id, (void*)0);
|
||||
scoped_lock<spin_mutex> lock(mtx_);
|
||||
umap_type::iterator it = umap_.insert(v).first;
|
||||
void *&hnd_val = it->second;
|
||||
if(!hnd_val){
|
||||
map_[&it->first] = it;
|
||||
hnd_val = open_or_create_mutex(id);
|
||||
if(popen_created) *popen_created = true;
|
||||
}
|
||||
else if(popen_created){
|
||||
*popen_created = false;
|
||||
}
|
||||
return hnd_val;
|
||||
}
|
||||
|
||||
void *obtain_semaphore(const sync_id &id, unsigned int initial_count, bool *popen_created = 0)
|
||||
{
|
||||
umap_type::value_type v(id, (void*)0);
|
||||
scoped_lock<spin_mutex> lock(mtx_);
|
||||
umap_type::iterator it = umap_.insert(v).first;
|
||||
void *&hnd_val = it->second;
|
||||
if(!hnd_val){
|
||||
map_[&it->first] = it;
|
||||
hnd_val = open_or_create_semaphore(id, initial_count);
|
||||
if(popen_created) *popen_created = true;
|
||||
}
|
||||
else if(popen_created){
|
||||
*popen_created = false;
|
||||
}
|
||||
return hnd_val;
|
||||
}
|
||||
|
||||
void destroy_handle(const sync_id &id)
|
||||
{
|
||||
scoped_lock<spin_mutex> lock(mtx_);
|
||||
umap_type::iterator it = umap_.find(id);
|
||||
umap_type::iterator itend = umap_.end();
|
||||
|
||||
if(it != itend){
|
||||
winapi::close_handle(it->second);
|
||||
const map_type::key_type &k = &it->first;
|
||||
map_.erase(k);
|
||||
umap_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_syncs_in_range(const void *addr, std::size_t size)
|
||||
{
|
||||
const sync_id low_id(addr);
|
||||
const sync_id hig_id(static_cast<const char*>(addr)+size);
|
||||
scoped_lock<spin_mutex> lock(mtx_);
|
||||
map_type::iterator itlow(map_.lower_bound(&low_id)),
|
||||
ithig(map_.lower_bound(&hig_id));
|
||||
while(itlow != ithig){
|
||||
void * const hnd = umap_[*itlow->first];
|
||||
winapi::close_handle(hnd);
|
||||
umap_.erase(*itlow->first);
|
||||
itlow = map_.erase(itlow);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
spin_mutex mtx_;
|
||||
umap_type umap_;
|
||||
map_type map_;
|
||||
};
|
||||
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_SYNC_UTILS_HPP
|
||||
@@ -0,0 +1,134 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINAPI_MUTEX_WRAPPER_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class winapi_mutex_functions
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
winapi_mutex_functions(const winapi_mutex_functions &);
|
||||
winapi_mutex_functions &operator=(const winapi_mutex_functions &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
winapi_mutex_functions(void *mtx_hnd)
|
||||
: m_mtx_hnd(mtx_hnd)
|
||||
{}
|
||||
|
||||
void unlock()
|
||||
{ winapi::release_mutex(m_mtx_hnd); }
|
||||
|
||||
void lock()
|
||||
{ return winapi_wrapper_wait_for_single_object(m_mtx_hnd); }
|
||||
|
||||
bool try_lock()
|
||||
{ return winapi_wrapper_try_wait_for_single_object(m_mtx_hnd); }
|
||||
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{ return winapi_wrapper_timed_wait_for_single_object(m_mtx_hnd, abs_time); }
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
protected:
|
||||
void *m_mtx_hnd;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
//Swappable mutex wrapper
|
||||
class winapi_mutex_wrapper
|
||||
: public winapi_mutex_functions
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
winapi_mutex_wrapper(const winapi_mutex_wrapper &);
|
||||
winapi_mutex_wrapper &operator=(const winapi_mutex_wrapper &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
//Note that Windows API does not return winapi::invalid_handle_value
|
||||
//when failing to create/open a mutex, but a nullptr
|
||||
|
||||
public:
|
||||
winapi_mutex_wrapper(void *mtx_hnd = 0)
|
||||
: winapi_mutex_functions(mtx_hnd)
|
||||
{}
|
||||
|
||||
~winapi_mutex_wrapper()
|
||||
{ this->close(); }
|
||||
|
||||
void *release()
|
||||
{
|
||||
void *hnd = m_mtx_hnd;
|
||||
m_mtx_hnd = 0;
|
||||
return hnd;
|
||||
}
|
||||
|
||||
void *handle() const
|
||||
{ return m_mtx_hnd; }
|
||||
|
||||
bool open_or_create(const char *name, const permissions &perm)
|
||||
{
|
||||
if(m_mtx_hnd == 0){
|
||||
m_mtx_hnd = winapi::open_or_create_mutex
|
||||
( name
|
||||
, false
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions()
|
||||
);
|
||||
return m_mtx_hnd != 0;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if(m_mtx_hnd != 0){
|
||||
winapi::close_handle(m_mtx_hnd);
|
||||
m_mtx_hnd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(winapi_mutex_wrapper &other)
|
||||
{ void *tmp = m_mtx_hnd; m_mtx_hnd = other.m_mtx_hnd; other.m_mtx_hnd = tmp; }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
|
||||
@@ -0,0 +1,168 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINAPI_SEMAPHORE_WRAPPER_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/windows/winapi_wrapper_common.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
class winapi_semaphore_functions
|
||||
{
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
|
||||
//Non-copyable
|
||||
winapi_semaphore_functions(const winapi_semaphore_functions &);
|
||||
winapi_semaphore_functions &operator=(const winapi_semaphore_functions &);
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
winapi_semaphore_functions(void *hnd)
|
||||
: m_sem_hnd(hnd)
|
||||
{}
|
||||
|
||||
void post(long count = 1)
|
||||
{
|
||||
long prev_count;
|
||||
winapi::release_semaphore(m_sem_hnd, count, &prev_count);
|
||||
}
|
||||
|
||||
void wait()
|
||||
{ return winapi_wrapper_wait_for_single_object(m_sem_hnd); }
|
||||
|
||||
bool try_wait()
|
||||
{ return winapi_wrapper_try_wait_for_single_object(m_sem_hnd); }
|
||||
|
||||
bool timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{ return winapi_wrapper_timed_wait_for_single_object(m_sem_hnd, abs_time); }
|
||||
|
||||
long value() const
|
||||
{
|
||||
long l_count, l_limit;
|
||||
if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit))
|
||||
return 0;
|
||||
return l_count;
|
||||
}
|
||||
|
||||
long limit() const
|
||||
{
|
||||
long l_count, l_limit;
|
||||
if(!winapi::get_semaphore_info(m_sem_hnd, l_count, l_limit))
|
||||
return 0;
|
||||
return l_limit;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
|
||||
protected:
|
||||
void *m_sem_hnd;
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
|
||||
};
|
||||
|
||||
|
||||
//Swappable semaphore wrapper
|
||||
class winapi_semaphore_wrapper
|
||||
: public winapi_semaphore_functions
|
||||
{
|
||||
winapi_semaphore_wrapper(const winapi_semaphore_wrapper &);
|
||||
winapi_semaphore_wrapper &operator=(const winapi_semaphore_wrapper &);
|
||||
|
||||
public:
|
||||
|
||||
//Long is 32 bits in windows
|
||||
static const long MaxCount = long(0x7FFFFFFF);
|
||||
|
||||
winapi_semaphore_wrapper(void *hnd = winapi::invalid_handle_value)
|
||||
: winapi_semaphore_functions(hnd)
|
||||
{}
|
||||
|
||||
~winapi_semaphore_wrapper()
|
||||
{ this->close(); }
|
||||
|
||||
void *release()
|
||||
{
|
||||
void *hnd = m_sem_hnd;
|
||||
m_sem_hnd = winapi::invalid_handle_value;
|
||||
return hnd;
|
||||
}
|
||||
|
||||
void *handle() const
|
||||
{ return m_sem_hnd; }
|
||||
|
||||
bool open_or_create( const char *name
|
||||
, long sem_count
|
||||
, long max_count
|
||||
, const permissions &perm
|
||||
, bool &created)
|
||||
{
|
||||
if(m_sem_hnd == winapi::invalid_handle_value){
|
||||
m_sem_hnd = winapi::open_or_create_semaphore
|
||||
( name
|
||||
, sem_count
|
||||
, max_count
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions()
|
||||
);
|
||||
created = winapi::get_last_error() != winapi::error_already_exists;
|
||||
return m_sem_hnd != winapi::invalid_handle_value;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool open_semaphore(const char *name)
|
||||
{
|
||||
if(m_sem_hnd == winapi::invalid_handle_value){
|
||||
m_sem_hnd = winapi::open_semaphore(name);
|
||||
return m_sem_hnd != winapi::invalid_handle_value;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if(m_sem_hnd != winapi::invalid_handle_value){
|
||||
winapi::close_handle(m_sem_hnd);
|
||||
m_sem_hnd = winapi::invalid_handle_value;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(winapi_semaphore_wrapper &other)
|
||||
{ void *tmp = m_sem_hnd; m_sem_hnd = other.m_sem_hnd; other.m_sem_hnd = tmp; }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_SEMAPHORE_WRAPPER_HPP
|
||||
@@ -0,0 +1,97 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINAPI_WRAPPER_COMMON_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WINAPI_WRAPPER_COMMON_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
# include <boost/config.hpp>
|
||||
#endif
|
||||
#
|
||||
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||
# 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/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
inline void winapi_wrapper_wait_for_single_object(void *handle)
|
||||
{
|
||||
unsigned long ret = winapi::wait_for_single_object(handle, winapi::infinite_time);
|
||||
if(ret != winapi::wait_object_0){
|
||||
if(ret != winapi::wait_abandoned){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
else{ //Special case for orphaned mutexes
|
||||
winapi::release_mutex(handle);
|
||||
throw interprocess_exception(owner_dead_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline bool winapi_wrapper_try_wait_for_single_object(void *handle)
|
||||
{
|
||||
unsigned long ret = winapi::wait_for_single_object(handle, 0);
|
||||
if(ret == winapi::wait_object_0){
|
||||
return true;
|
||||
}
|
||||
else if(ret == winapi::wait_timeout){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Windows does not support infinity abs_time so check it
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
winapi_wrapper_wait_for_single_object(handle);
|
||||
return true;
|
||||
}
|
||||
const boost::posix_time::ptime cur_time = microsec_clock::universal_time();
|
||||
//Windows uses relative wait times so check for negative waits
|
||||
//and implement as 0 wait to allow try-semantics as POSIX mandates.
|
||||
unsigned long ret = winapi::wait_for_single_object
|
||||
( handle
|
||||
, (abs_time <= cur_time) ? 0u
|
||||
: (abs_time - cur_time).total_milliseconds()
|
||||
);
|
||||
if(ret == winapi::wait_object_0){
|
||||
return true;
|
||||
}
|
||||
else if(ret == winapi::wait_timeout){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_WINAPI_MUTEX_WRAPPER_HPP
|
||||
Reference in New Issue
Block a user