mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Merged Interprocess to the release branch
[SVN r85615]
This commit is contained in:
@@ -2,4 +2,4 @@ import testing ;
|
||||
|
||||
# Tests from Jamfiles in individual library test subdirectories
|
||||
build-project example ; # test-suite interprocess_example
|
||||
build-project test ; # test-suite interprocess_test
|
||||
build-project test ; # test-suite interprocess_test
|
||||
@@ -6715,8 +6715,13 @@ thank them:
|
||||
|
||||
[section:release_notes_boost_1_55_00 Boost 1.55 Release]
|
||||
|
||||
* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7164 #7164],
|
||||
[@https://svn.boost.org/trac/boost/ticket/8277 #8277].
|
||||
* Fixed bugs [@https://svn.boost.org/trac/boost/ticket/7156 #7156],
|
||||
[@https://svn.boost.org/trac/boost/ticket/7164 #7164],
|
||||
[@https://svn.boost.org/trac/boost/ticket/8277 #8277],
|
||||
[@https://svn.boost.org/trac/boost/ticket/8976 #8976],
|
||||
[@https://svn.boost.org/trac/boost/ticket/9065 #9065],
|
||||
[@https://svn.boost.org/trac/boost/ticket/9073 #9073],
|
||||
[@https://svn.boost.org/trac/boost/ticket/8277 #9908].
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ inline boost::uint32_t atomic_cas32
|
||||
"bne- 1b\n\t"
|
||||
"2:"
|
||||
: "=&r"(prev)
|
||||
: "b" (mem), "r"(cmp), "r" (with)
|
||||
: "b" (mem), "r" (with), "r" (cmp)
|
||||
: "cc", "memory");
|
||||
return prev;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
@@ -145,7 +146,7 @@ class intermodule_singleton_common
|
||||
//If previous state was initializing, this means that another winner thread is
|
||||
//trying to initialize the singleton. Just wait until completes its work.
|
||||
else if(previous_module_singleton_initialized == Initializing){
|
||||
unsigned int k = 0;
|
||||
spin_wait swait;
|
||||
while(1){
|
||||
previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized);
|
||||
if(previous_module_singleton_initialized >= Initialized){
|
||||
@@ -153,7 +154,7 @@ class intermodule_singleton_common
|
||||
break;
|
||||
}
|
||||
else if(previous_module_singleton_initialized == Initializing){
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
else{
|
||||
//This can't be happening!
|
||||
@@ -207,7 +208,7 @@ class intermodule_singleton_common
|
||||
static void initialize_global_map_handle()
|
||||
{
|
||||
//Obtain unique map name and size
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(1){
|
||||
//Try to pass map state to initializing
|
||||
::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized);
|
||||
@@ -220,7 +221,7 @@ class intermodule_singleton_common
|
||||
}
|
||||
//If some other thread is doing the work wait
|
||||
else if(tmp == Initializing){
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
else{ //(tmp == Uninitialized)
|
||||
//If not initialized try it again?
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
@@ -354,7 +355,7 @@ class managed_open_or_create_impl
|
||||
//file and know if we have really created it or just open it
|
||||
//drop me a e-mail!
|
||||
bool completed = false;
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(!completed){
|
||||
try{
|
||||
create_device<FileBased>(dev, id, size, perm, file_like_t());
|
||||
@@ -385,7 +386,7 @@ class managed_open_or_create_impl
|
||||
catch(...){
|
||||
throw;
|
||||
}
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,12 +433,12 @@ class managed_open_or_create_impl
|
||||
else{
|
||||
if(FileBased){
|
||||
offset_t filesize = 0;
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(filesize == 0){
|
||||
if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
if(filesize == 1){
|
||||
throw interprocess_exception(error_info(corrupted_error));
|
||||
@@ -449,9 +450,9 @@ class managed_open_or_create_impl
|
||||
boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
|
||||
boost::uint32_t value = atomic_read32(patomic_word);
|
||||
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(value == InitializingSegment || value == UninitializedSegment){
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
value = atomic_read32(patomic_word);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,18 +15,36 @@
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/streams/bufferstream.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/detail/yield_k.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
# include <boost/interprocess/detail/win32_api.hpp>
|
||||
#else
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <pthread.h>
|
||||
# include <unistd.h>
|
||||
# include <sched.h>
|
||||
# include <time.h>
|
||||
# include <pthread.h>
|
||||
# include <unistd.h>
|
||||
# include <sched.h>
|
||||
# include <time.h>
|
||||
# ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE
|
||||
//Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas
|
||||
//others (FreeBSD & Darwin) need sys/types.h
|
||||
# include <sys/types.h>
|
||||
# include <sys/param.h>
|
||||
# include <sys/sysctl.h>
|
||||
# endif
|
||||
//According to the article "C/C++ tip: How to measure elapsed real time for benchmarking"
|
||||
# if defined(CLOCK_MONOTONIC_PRECISE) //BSD
|
||||
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE
|
||||
# elif defined(CLOCK_MONOTONIC_RAW) //Linux
|
||||
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW
|
||||
# elif defined(CLOCK_HIGHRES) //Solaris
|
||||
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES
|
||||
# elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris)
|
||||
# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC
|
||||
# elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
|
||||
# include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
|
||||
# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
||||
# else
|
||||
# error Unknown platform
|
||||
# error "No high resolution steady clock in your system, please provide a patch"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
@@ -57,6 +75,75 @@ inline OS_thread_id_t get_invalid_thread_id()
|
||||
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
||||
{ return id1 == id2; }
|
||||
|
||||
//return the system tick in ns
|
||||
inline unsigned long get_system_tick_ns()
|
||||
{
|
||||
unsigned long curres;
|
||||
winapi::set_timer_resolution(10000, 0, &curres);
|
||||
//Windows API returns the value in hundreds of ns
|
||||
return (curres - 1ul)*100ul;
|
||||
}
|
||||
|
||||
//return the system tick in us
|
||||
inline unsigned long get_system_tick_us()
|
||||
{
|
||||
unsigned long curres;
|
||||
winapi::set_timer_resolution(10000, 0, &curres);
|
||||
//Windows API returns the value in hundreds of ns
|
||||
return (curres - 1ul)/10ul + 1ul;
|
||||
}
|
||||
|
||||
typedef unsigned __int64 OS_highres_count_t;
|
||||
|
||||
inline OS_highres_count_t get_system_tick_in_highres_counts()
|
||||
{
|
||||
__int64 freq;
|
||||
unsigned long curres;
|
||||
winapi::set_timer_resolution(10000, 0, &curres);
|
||||
//Frequency in counts per second
|
||||
if(!winapi::query_performance_frequency(&freq)){
|
||||
//Tick resolution in ms
|
||||
return (curres-1)/10000u + 1;
|
||||
}
|
||||
else{
|
||||
//In femtoseconds
|
||||
__int64 count_fs = __int64(1000000000000000LL - 1LL)/freq + 1LL;
|
||||
__int64 tick_counts = (__int64(curres)*100000000LL - 1LL)/count_fs + 1LL;
|
||||
return static_cast<OS_highres_count_t>(tick_counts);
|
||||
}
|
||||
}
|
||||
|
||||
inline OS_highres_count_t get_current_system_highres_count()
|
||||
{
|
||||
__int64 count;
|
||||
if(!winapi::query_performance_counter(&count)){
|
||||
count = winapi::get_tick_count();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
inline void zero_highres_count(OS_highres_count_t &count)
|
||||
{ count = 0; }
|
||||
|
||||
inline bool is_highres_count_zero(const OS_highres_count_t &count)
|
||||
{ return count == 0; }
|
||||
|
||||
template <class Ostream>
|
||||
inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
|
||||
{
|
||||
ostream << count;
|
||||
return ostream;
|
||||
}
|
||||
|
||||
inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
||||
{ return l - r; }
|
||||
|
||||
inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
||||
{ return l < r; }
|
||||
|
||||
inline void thread_sleep_tick()
|
||||
{ winapi::sleep_tick(); }
|
||||
|
||||
inline void thread_yield()
|
||||
{ winapi::sched_yield(); }
|
||||
|
||||
@@ -98,6 +185,13 @@ inline long double get_current_process_creation_time()
|
||||
CreationTime.dwLowDateTime*resolution;
|
||||
}
|
||||
|
||||
inline unsigned int get_num_cores()
|
||||
{
|
||||
winapi::system_info sysinfo;
|
||||
winapi::get_system_info( &sysinfo );
|
||||
//in Windows dw is long which is equal in bits to int
|
||||
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
|
||||
}
|
||||
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
@@ -165,9 +259,132 @@ inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
||||
inline void thread_yield()
|
||||
{ ::sched_yield(); }
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
||||
typedef struct timespec OS_highres_count_t;
|
||||
#else
|
||||
typedef unsigned long long OS_highres_count_t;
|
||||
#endif
|
||||
|
||||
inline unsigned long get_system_tick_ns()
|
||||
{
|
||||
#ifdef _SC_CLK_TCK
|
||||
long hz =::sysconf(_SC_CLK_TCK); // ticks per sec
|
||||
if(hz <= 0){ //Try a typical value on error
|
||||
hz = 100;
|
||||
}
|
||||
return 999999999ul/static_cast<unsigned long>(hz)+1ul;
|
||||
#else
|
||||
#error "Can't obtain system tick value for your system, please provide a patch"
|
||||
#endif
|
||||
}
|
||||
|
||||
inline OS_highres_count_t get_system_tick_in_highres_counts()
|
||||
{
|
||||
#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
||||
struct timespec ts;
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = get_system_tick_ns();
|
||||
return ts;
|
||||
#else
|
||||
mach_timebase_info_data_t info;
|
||||
mach_timebase_info(&info);
|
||||
//ns
|
||||
return static_cast<OS_highres_count_t>
|
||||
(
|
||||
static_cast<double>(get_system_tick_ns())
|
||||
/ (static_cast<double>(info.numer) / info.denom)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
//return system ticks in us
|
||||
inline unsigned long get_system_tick_us()
|
||||
{
|
||||
return (get_system_tick_ns()-1)/1000ul + 1ul;
|
||||
}
|
||||
|
||||
inline OS_highres_count_t get_current_system_highres_count()
|
||||
{
|
||||
#if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC)
|
||||
struct timespec count;
|
||||
::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count);
|
||||
return count;
|
||||
#elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME)
|
||||
return ::mach_absolute_time();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME
|
||||
|
||||
inline void zero_highres_count(OS_highres_count_t &count)
|
||||
{ count.tv_sec = 0; count.tv_nsec = 0; }
|
||||
|
||||
inline bool is_highres_count_zero(const OS_highres_count_t &count)
|
||||
{ return count.tv_sec == 0 && count.tv_nsec == 0; }
|
||||
|
||||
template <class Ostream>
|
||||
inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
|
||||
{
|
||||
ostream << count.tv_sec << "s:" << count.tv_nsec << "ns";
|
||||
return ostream;
|
||||
}
|
||||
|
||||
inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
||||
{
|
||||
OS_highres_count_t res;
|
||||
|
||||
if (l.tv_nsec < r.tv_nsec){
|
||||
res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec;
|
||||
res.tv_sec = l.tv_sec - 1 - r.tv_sec;
|
||||
}
|
||||
else{
|
||||
res.tv_nsec = l.tv_nsec - r.tv_nsec;
|
||||
res.tv_sec = l.tv_sec - r.tv_sec;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
||||
{ return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); }
|
||||
|
||||
#else
|
||||
|
||||
inline void zero_highres_count(OS_highres_count_t &count)
|
||||
{ count = 0; }
|
||||
|
||||
inline bool is_highres_count_zero(const OS_highres_count_t &count)
|
||||
{ return count == 0; }
|
||||
|
||||
template <class Ostream>
|
||||
inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count)
|
||||
{
|
||||
ostream << count ;
|
||||
return ostream;
|
||||
}
|
||||
|
||||
inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
||||
{ return l - r; }
|
||||
|
||||
inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r)
|
||||
{ return l < r; }
|
||||
|
||||
#endif
|
||||
|
||||
inline void thread_sleep_tick()
|
||||
{
|
||||
struct timespec rqt;
|
||||
//Sleep for the half of the tick time
|
||||
rqt.tv_sec = 0;
|
||||
rqt.tv_nsec = get_system_tick_ns()/2;
|
||||
::nanosleep(&rqt, 0);
|
||||
}
|
||||
|
||||
inline void thread_sleep(unsigned int ms)
|
||||
{
|
||||
const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u };
|
||||
struct timespec rqt;
|
||||
rqt.tv_sec = ms/1000u;
|
||||
rqt.tv_nsec = (ms%1000u)*1000000u;
|
||||
::nanosleep(&rqt, 0);
|
||||
}
|
||||
|
||||
@@ -190,6 +407,39 @@ inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
||||
inline long double get_current_process_creation_time()
|
||||
{ return 0.0L; }
|
||||
|
||||
inline unsigned int get_num_cores()
|
||||
{
|
||||
#ifdef _SC_NPROCESSORS_ONLN
|
||||
long cores = ::sysconf(_SC_NPROCESSORS_ONLN);
|
||||
// sysconf returns -1 if the name is invalid, the option does not exist or
|
||||
// does not have a definite limit.
|
||||
// if sysconf returns some other negative number, we have no idea
|
||||
// what is going on. Default to something safe.
|
||||
if(cores <= 0){
|
||||
return 1;
|
||||
}
|
||||
//Check for overflow (unlikely)
|
||||
else if(static_cast<unsigned long>(cores) >=
|
||||
static_cast<unsigned long>(static_cast<unsigned int>(-1))){
|
||||
return static_cast<unsigned int>(-1);
|
||||
}
|
||||
else{
|
||||
return static_cast<unsigned int>(cores);
|
||||
}
|
||||
#elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU)
|
||||
int request[2] = { CTL_HW, HW_NCPU };
|
||||
int num_cores;
|
||||
std::size_t result_len = sizeof(num_cores);
|
||||
if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){
|
||||
//Return a safe value
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
return static_cast<unsigned int>(num_cores);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
|
||||
#include <boost/interprocess/detail/intermodule_singleton.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost{
|
||||
@@ -228,7 +229,7 @@ inline void robust_spin_mutex<Mutex>::lock()
|
||||
|
||||
//Now the logic. Try to lock, if successful mark the owner
|
||||
//if it fails, start recovery logic
|
||||
unsigned int spin_count = 0;
|
||||
spin_wait swait;
|
||||
while(1){
|
||||
if (mtx.try_lock()){
|
||||
atomic_write32(&this->owner, get_current_process_id());
|
||||
@@ -236,14 +237,10 @@ inline void robust_spin_mutex<Mutex>::lock()
|
||||
}
|
||||
else{
|
||||
//Do the dead owner checking each spin_threshold lock tries
|
||||
yield(spin_count);
|
||||
++spin_count;
|
||||
if(spin_count > spin_threshold){
|
||||
swait.yield();
|
||||
if(0 == (swait.count() & 255u)){
|
||||
//Check if owner dead and take ownership if possible
|
||||
if(!this->robust_check()){
|
||||
spin_count = 0;
|
||||
}
|
||||
else{
|
||||
if(this->robust_check()){
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -292,7 +289,7 @@ inline bool robust_spin_mutex<Mutex>::timed_lock
|
||||
if(now >= abs_time)
|
||||
return this->try_lock();
|
||||
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(this->try_lock()){
|
||||
break;
|
||||
@@ -303,7 +300,7 @@ inline bool robust_spin_mutex<Mutex>::timed_lock
|
||||
return this->try_lock();
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}while (true);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace ipcdetail {
|
||||
struct ::timeval result;
|
||||
std::size_t result_len = sizeof result;
|
||||
|
||||
if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
|
||||
if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0)
|
||||
return;
|
||||
|
||||
char bootstamp_str[256];
|
||||
|
||||
@@ -883,6 +883,7 @@ extern "C" __declspec(dllimport) int __stdcall GetProcessTimes
|
||||
, interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime
|
||||
, interprocess_filetime *lpUserTime );
|
||||
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetTickCount(void);
|
||||
extern "C" __declspec(dllimport) int __stdcall SwitchToThread();
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
|
||||
extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long);
|
||||
@@ -943,7 +944,6 @@ extern "C" __declspec(dllimport) int __stdcall FreeLibrary(void *);
|
||||
extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*);
|
||||
extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*);
|
||||
extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*);
|
||||
extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount);
|
||||
|
||||
//Advapi32.dll
|
||||
extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(void *, const char *, unsigned long, unsigned long, void **);
|
||||
@@ -1013,6 +1013,12 @@ typedef long (__stdcall *NtQuerySection_t)(void*, section_information_class, int
|
||||
typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int);
|
||||
typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long);
|
||||
typedef long (__stdcall *NtClose_t) (void*);
|
||||
typedef long (__stdcall *NtQueryTimerResolution_t) (unsigned long* LowestResolution, unsigned long* HighestResolution, unsigned long* CurrentResolution);
|
||||
typedef long (__stdcall *NtSetTimerResolution_t) (unsigned long RequestedResolution, int Set, unsigned long* ActualResolution);
|
||||
|
||||
//kernel32.dll
|
||||
typedef int (__stdcall *QueryPerformanceCounter_t) (__int64 *lpPerformanceCount);
|
||||
typedef int (__stdcall *QueryPerformanceFrequency_t)(__int64 *lpFrequency);
|
||||
|
||||
} //namespace winapi {
|
||||
} //namespace interprocess {
|
||||
@@ -1047,10 +1053,13 @@ inline unsigned long make_lang_id(unsigned long p, unsigned long s)
|
||||
inline void sched_yield()
|
||||
{
|
||||
if(!SwitchToThread()){
|
||||
Sleep(1);
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
inline void sleep_tick()
|
||||
{ Sleep(1); }
|
||||
|
||||
inline void sleep(unsigned long ms)
|
||||
{ Sleep(ms); }
|
||||
|
||||
@@ -1270,11 +1279,6 @@ inline long reg_query_value_ex(void *hKey, const char *lpValueName, unsigned lon
|
||||
inline long reg_close_key(void *hKey)
|
||||
{ return RegCloseKey(hKey); }
|
||||
|
||||
inline bool query_performance_counter(__int64 *lpPerformanceCount)
|
||||
{
|
||||
return 0 != QueryPerformanceCounter(lpPerformanceCount);
|
||||
}
|
||||
|
||||
inline void initialize_object_attributes
|
||||
( object_attributes_t *pobject_attr, unicode_string_t *name
|
||||
, unsigned long attr, void *rootdir, void *security_descr)
|
||||
@@ -1299,8 +1303,20 @@ inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf,
|
||||
template<int Dummy>
|
||||
struct function_address_holder
|
||||
{
|
||||
enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NtOpenFile, NtClose, NumFunction };
|
||||
enum { NtDll_dll, NumModule };
|
||||
enum { NtSetInformationFile
|
||||
, NtQuerySystemInformation
|
||||
, NtQueryObject
|
||||
, NtQuerySemaphore
|
||||
, NtQuerySection
|
||||
, NtOpenFile
|
||||
, NtClose
|
||||
, NtQueryTimerResolution
|
||||
, NtSetTimerResolution
|
||||
, QueryPerformanceCounter
|
||||
, QueryPerformanceFrequency
|
||||
, NumFunction
|
||||
};
|
||||
enum { NtDll_dll, Kernel32_dll, NumModule };
|
||||
|
||||
private:
|
||||
static const char *FunctionNames[NumFunction];
|
||||
@@ -1314,21 +1330,26 @@ struct function_address_holder
|
||||
static void *get_module_from_id(unsigned int id)
|
||||
{
|
||||
BOOST_ASSERT(id < (unsigned int)NumModule);
|
||||
return get_module_handle(ModuleNames[id]);
|
||||
void *addr = get_module_handle(ModuleNames[id]);
|
||||
BOOST_ASSERT(addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
static void *get_module(const unsigned int id)
|
||||
{
|
||||
BOOST_ASSERT(id < (unsigned int)NumModule);
|
||||
while(ModuleStates[id] < 2){
|
||||
for(unsigned i = 0; ModuleStates[id] < 2; ++i){
|
||||
if(interlocked_compare_exchange(&ModuleStates[id], 1, 0) == 0){
|
||||
ModuleAddresses[id] = get_module_from_id(id);
|
||||
interlocked_increment(&ModuleStates[id]);
|
||||
break;
|
||||
}
|
||||
else{
|
||||
else if(i & 1){
|
||||
sched_yield();
|
||||
}
|
||||
else{
|
||||
sleep_tick();
|
||||
}
|
||||
}
|
||||
return ModuleAddresses[id];
|
||||
}
|
||||
@@ -1336,22 +1357,27 @@ struct function_address_holder
|
||||
static void *get_address_from_dll(const unsigned int id)
|
||||
{
|
||||
BOOST_ASSERT(id < (unsigned int)NumFunction);
|
||||
return get_proc_address(get_module(FunctionModules[id]), FunctionNames[id]);
|
||||
void *addr = get_proc_address(get_module(FunctionModules[id]), FunctionNames[id]);
|
||||
BOOST_ASSERT(addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
public:
|
||||
static void *get(const unsigned int id)
|
||||
{
|
||||
BOOST_ASSERT(id < (unsigned int)NumFunction);
|
||||
while(FunctionStates[id] < 2){
|
||||
for(unsigned i = 0; FunctionStates[id] < 2; ++i){
|
||||
if(interlocked_compare_exchange(&FunctionStates[id], 1, 0) == 0){
|
||||
FunctionAddresses[id] = get_address_from_dll(id);
|
||||
interlocked_increment(&FunctionStates[id]);
|
||||
break;
|
||||
}
|
||||
else{
|
||||
else if(i & 1){
|
||||
sched_yield();
|
||||
}
|
||||
else{
|
||||
sleep_tick();
|
||||
}
|
||||
}
|
||||
return FunctionAddresses[id];
|
||||
}
|
||||
@@ -1366,7 +1392,11 @@ const char *function_address_holder<Dummy>::FunctionNames[function_address_holde
|
||||
"NtQuerySemaphore",
|
||||
"NtQuerySection",
|
||||
"NtOpenFile",
|
||||
"NtClose"
|
||||
"NtClose",
|
||||
"NtQueryTimerResolution",
|
||||
"NtSetTimerResolution",
|
||||
"QueryPerformanceCounter",
|
||||
"QueryPerformanceFrequency"
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
@@ -1378,13 +1408,18 @@ unsigned int function_address_holder<Dummy>::FunctionModules[function_address_ho
|
||||
NtDll_dll,
|
||||
NtDll_dll,
|
||||
NtDll_dll,
|
||||
NtDll_dll
|
||||
NtDll_dll,
|
||||
NtDll_dll,
|
||||
NtDll_dll,
|
||||
Kernel32_dll,
|
||||
Kernel32_dll
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
const char *function_address_holder<Dummy>::ModuleNames[function_address_holder<Dummy>::NumModule] =
|
||||
{
|
||||
"ntdll.dll"
|
||||
"ntdll.dll",
|
||||
"kernel32.dll"
|
||||
};
|
||||
|
||||
|
||||
@@ -1549,7 +1584,7 @@ class nt_query_mem_deleter
|
||||
delete[]m_buf;
|
||||
}
|
||||
|
||||
void realloc(std::size_t num_bytes)
|
||||
void realloc_mem(std::size_t num_bytes)
|
||||
{
|
||||
num_bytes += rename_suffix + rename_offset;
|
||||
char *buf = m_buf;
|
||||
@@ -1584,7 +1619,7 @@ class c_heap_deleter
|
||||
if(m_buf) ::free(m_buf);
|
||||
}
|
||||
|
||||
void realloc(std::size_t num_bytes)
|
||||
void realloc_mem(std::size_t num_bytes)
|
||||
{
|
||||
void *buf = ::realloc(m_buf, num_bytes);
|
||||
if(!buf){
|
||||
@@ -1639,7 +1674,7 @@ inline bool unlink_file(const char *filename)
|
||||
//Obtain file name with guessed length
|
||||
if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){
|
||||
//Obtain file name with exact length buffer
|
||||
nt_query_mem.realloc(size);
|
||||
nt_query_mem.realloc_mem(size);
|
||||
if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){
|
||||
return false;
|
||||
}
|
||||
@@ -2021,7 +2056,7 @@ inline bool get_last_bootup_time(std::string &stamp)
|
||||
if (error_insufficient_buffer == status) {
|
||||
status = 0;
|
||||
dwBytesToRead = dwMinimumBytesToRead;
|
||||
heap_deleter.realloc(dwMinimumBytesToRead);
|
||||
heap_deleter.realloc_mem(dwMinimumBytesToRead);
|
||||
if (!heap_deleter.get()){
|
||||
return false;
|
||||
}
|
||||
@@ -2065,11 +2100,8 @@ inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size)
|
||||
interprocess_section_basic_information info;
|
||||
unsigned long ntstatus =
|
||||
pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0);
|
||||
if(ntstatus){
|
||||
return false;
|
||||
}
|
||||
size = info.section_size;
|
||||
return true;
|
||||
return !ntstatus;
|
||||
}
|
||||
|
||||
inline bool get_semaphore_info(void *handle, long &count, long &limit)
|
||||
@@ -2079,14 +2111,41 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit)
|
||||
(winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore);
|
||||
unsigned int ret_len;
|
||||
long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len);
|
||||
if(status){
|
||||
return false;
|
||||
}
|
||||
count = info.count;
|
||||
limit = info.limit;
|
||||
return true;
|
||||
return !status;
|
||||
}
|
||||
|
||||
inline bool query_timer_resolution(unsigned long *lowres, unsigned long *highres, unsigned long *curres)
|
||||
{
|
||||
winapi::NtQueryTimerResolution_t pNtQueryTimerResolution =
|
||||
(winapi::NtQueryTimerResolution_t)dll_func::get(winapi::dll_func::NtQueryTimerResolution);
|
||||
return !pNtQueryTimerResolution(lowres, highres, curres);
|
||||
}
|
||||
|
||||
inline bool set_timer_resolution(unsigned long RequestedResolution, int Set, unsigned long* ActualResolution)
|
||||
{
|
||||
winapi::NtSetTimerResolution_t pNtSetTimerResolution =
|
||||
(winapi::NtSetTimerResolution_t)dll_func::get(winapi::dll_func::NtSetTimerResolution);
|
||||
return !pNtSetTimerResolution(RequestedResolution, Set, ActualResolution);
|
||||
}
|
||||
|
||||
inline bool query_performance_counter(__int64 *lpPerformanceCount)
|
||||
{
|
||||
QueryPerformanceCounter_t pQueryPerformanceCounter = (QueryPerformanceCounter_t)
|
||||
dll_func::get(dll_func::QueryPerformanceCounter);
|
||||
return 0 != pQueryPerformanceCounter(lpPerformanceCount);
|
||||
}
|
||||
|
||||
inline bool query_performance_frequency(__int64 *lpFrequency)
|
||||
{
|
||||
QueryPerformanceCounter_t pQueryPerformanceFrequency = (QueryPerformanceFrequency_t)
|
||||
dll_func::get(dll_func::QueryPerformanceFrequency);
|
||||
return 0 != pQueryPerformanceFrequency(lpFrequency);
|
||||
}
|
||||
|
||||
inline unsigned long get_tick_count()
|
||||
{ return GetTickCount(); }
|
||||
|
||||
} //namespace winapi
|
||||
} //namespace interprocess
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
//This file was copied from boost/smart_ptr/detail and
|
||||
//modified here to avoid dependencies with that library
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
|
||||
#define BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// yield_k.hpp
|
||||
//
|
||||
// Copyright (c) 2008 Peter Dimov
|
||||
//
|
||||
// void yield( unsigned k );
|
||||
//
|
||||
// Typical use:
|
||||
//
|
||||
// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
|
||||
//
|
||||
// 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
|
||||
//
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
// BOOST_INTERPROCESS_SMT_PAUSE
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
|
||||
|
||||
extern "C" void _mm_pause();
|
||||
#pragma intrinsic( _mm_pause )
|
||||
|
||||
#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
|
||||
|
||||
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
|
||||
|
||||
#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace interprocess
|
||||
{
|
||||
namespace ipcdetail
|
||||
{
|
||||
|
||||
inline void yield( unsigned k )
|
||||
{
|
||||
if( k < 4 )
|
||||
{
|
||||
}
|
||||
#if defined( BOOST_INTERPROCESS_SMT_PAUSE )
|
||||
else if( k < 16 ){
|
||||
BOOST_INTERPROCESS_SMT_PAUSE
|
||||
}
|
||||
#endif
|
||||
else if( k < 32 ){
|
||||
//Try to yield to another thread running on the current processor
|
||||
if(!winapi::SwitchToThread()){
|
||||
//If not yield to any thread of same or higher priority on any processor
|
||||
boost::interprocess::winapi::Sleep(0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//Yields to any thread on any processor
|
||||
boost::interprocess::winapi::Sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ipcdetail
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#else
|
||||
|
||||
#include <sched.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace interprocess
|
||||
{
|
||||
namespace ipcdetail
|
||||
{
|
||||
|
||||
inline void yield( unsigned k )
|
||||
{
|
||||
if( k < 4 )
|
||||
{
|
||||
}
|
||||
#if defined( BOOST_INTERPROCESS_SMT_PAUSE )
|
||||
else if( k < 16 )
|
||||
{
|
||||
BOOST_INTERPROCESS_SMT_PAUSE
|
||||
}
|
||||
#endif
|
||||
else if( k < 32 || k & 1 )
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
// g++ -Wextra warns on {} or {0}
|
||||
struct timespec rqtp = { 0, 0 };
|
||||
|
||||
// POSIX says that timespec has tv_sec and tv_nsec
|
||||
// But it doesn't guarantee order or placement
|
||||
|
||||
rqtp.tv_sec = 0;
|
||||
rqtp.tv_nsec = 1000;
|
||||
|
||||
nanosleep( &rqtp, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ipcdetail
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_DETAIL_YIELD_K_HPP_INCLUDED
|
||||
@@ -83,6 +83,8 @@ class sp_counted_impl_pd
|
||||
portable_rebind_alloc
|
||||
< const this_type >::type const_this_allocator;
|
||||
typedef typename this_allocator::pointer this_pointer;
|
||||
typedef typename boost::intrusive::
|
||||
pointer_traits<this_pointer> this_pointer_traits;
|
||||
|
||||
sp_counted_impl_pd( sp_counted_impl_pd const & );
|
||||
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
|
||||
@@ -115,11 +117,10 @@ class sp_counted_impl_pd
|
||||
|
||||
void destroy() // nothrow
|
||||
{
|
||||
//Self destruction, so get a copy of the allocator
|
||||
//(in the future we could move it)
|
||||
this_allocator a_copy(*this);
|
||||
//Self destruction, so move the allocator
|
||||
this_allocator a_copy(::boost::move(static_cast<this_allocator&>(*this)));
|
||||
BOOST_ASSERT(a_copy == *this);
|
||||
this_pointer this_ptr (this);
|
||||
this_pointer this_ptr(this_pointer_traits::pointer_to(*this));
|
||||
//Do it now!
|
||||
scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
|
||||
deleter_ptr(this_ptr, a_copy);
|
||||
|
||||
@@ -251,8 +251,11 @@ class basic_bufferbuf
|
||||
//!A basic_istream class that uses a fixed size character buffer
|
||||
//!as its formatting buffer.
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_ibufferstream
|
||||
: public std::basic_istream<CharT, CharTraits>
|
||||
class basic_ibufferstream :
|
||||
/// @cond
|
||||
private basic_bufferbuf<CharT, CharTraits>,
|
||||
/// @endcond
|
||||
public std::basic_istream<CharT, CharTraits>
|
||||
{
|
||||
public: // Typedefs
|
||||
typedef typename std::basic_ios
|
||||
@@ -262,24 +265,40 @@ class basic_ibufferstream
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_istream<char_type, CharTraits> base_t;
|
||||
typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t;
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_istream<char_type, CharTraits> base_t;
|
||||
bufferbuf_t & get_buf() { return *this; }
|
||||
const bufferbuf_t & get_buf() const{ return *this; }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Does not throw.
|
||||
basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: //basic_ios_t() is called first (lefting it uninitialized) as it's a
|
||||
//virtual base of basic_istream. The class will be initialized when
|
||||
//basic_istream is constructed calling basic_ios_t::init().
|
||||
//As bufferbuf_t's constructor does not throw there is no risk of
|
||||
//calling the basic_ios_t's destructor without calling basic_ios_t::init()
|
||||
bufferbuf_t(mode | std::ios_base::in)
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
basic_ibufferstream(const CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode = std::ios_base::in)
|
||||
: basic_ios_t(), base_t(0),
|
||||
m_buf(const_cast<CharT*>(buf), length, mode | std::ios_base::in)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: //basic_ios_t() is called first (lefting it uninitialized) as it's a
|
||||
//virtual base of basic_istream. The class will be initialized when
|
||||
//basic_istream is constructed calling basic_ios_t::init().
|
||||
//As bufferbuf_t's constructor does not throw there is no risk of
|
||||
//calling the basic_ios_t's destructor without calling basic_ios_t::init()
|
||||
bufferbuf_t(const_cast<CharT*>(buf), length, mode | std::ios_base::in)
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
~basic_ibufferstream(){};
|
||||
|
||||
@@ -287,29 +306,27 @@ class basic_ibufferstream
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); }
|
||||
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<const CharT *, std::size_t> buffer() const
|
||||
{ return m_buf.buffer(); }
|
||||
{ return get_buf().buffer(); }
|
||||
|
||||
//!Sets the underlying buffer to a new value. Resets
|
||||
//!stream position. Does not throw.
|
||||
void buffer(const CharT *buf, std::size_t length)
|
||||
{ m_buf.buffer(const_cast<CharT*>(buf), length); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_bufferbuf<CharT, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
{ get_buf().buffer(const_cast<CharT*>(buf), length); }
|
||||
};
|
||||
|
||||
//!A basic_ostream class that uses a fixed size character buffer
|
||||
//!as its formatting buffer.
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_obufferstream
|
||||
: public std::basic_ostream<CharT, CharTraits>
|
||||
class basic_obufferstream :
|
||||
/// @cond
|
||||
private basic_bufferbuf<CharT, CharTraits>,
|
||||
/// @endcond
|
||||
public std::basic_ostream<CharT, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef typename std::basic_ios
|
||||
@@ -321,23 +338,38 @@ class basic_obufferstream
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t;
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_ostream<char_type, CharTraits> base_t;
|
||||
bufferbuf_t & get_buf() { return *this; }
|
||||
const bufferbuf_t & get_buf() const{ return *this; }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor.
|
||||
//!Does not throw.
|
||||
basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: //basic_ios_t() is called first (lefting it uninitialized) as it's a
|
||||
//virtual base of basic_istream. The class will be initialized when
|
||||
//basic_istream is constructed calling basic_ios_t::init().
|
||||
//As bufferbuf_t's constructor does not throw there is no risk of
|
||||
//calling the basic_ios_t's destructor without calling basic_ios_t::init()
|
||||
bufferbuf_t(mode | std::ios_base::out)
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
basic_obufferstream(CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode = std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0),
|
||||
m_buf(buf, length, mode | std::ios_base::out)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: //basic_ios_t() is called first (lefting it uninitialized) as it's a
|
||||
//virtual base of basic_istream. The class will be initialized when
|
||||
//basic_istream is constructed calling basic_ios_t::init().
|
||||
//As bufferbuf_t's constructor does not throw there is no risk of
|
||||
//calling the basic_ios_t's destructor without calling basic_ios_t::init()
|
||||
bufferbuf_t(buf, length, mode | std::ios_base::out)
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
~basic_obufferstream(){}
|
||||
|
||||
@@ -345,31 +377,28 @@ class basic_obufferstream
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); }
|
||||
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<CharT *, std::size_t> buffer() const
|
||||
{ return m_buf.buffer(); }
|
||||
{ return get_buf().buffer(); }
|
||||
|
||||
//!Sets the underlying buffer to a new value. Resets
|
||||
//!stream position. Does not throw.
|
||||
void buffer(CharT *buf, std::size_t length)
|
||||
{ m_buf.buffer(buf, length); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_bufferbuf<CharT, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
{ get_buf().buffer(buf, length); }
|
||||
};
|
||||
|
||||
|
||||
//!A basic_iostream class that uses a fixed size character buffer
|
||||
//!as its formatting buffer.
|
||||
template <class CharT, class CharTraits>
|
||||
class basic_bufferstream
|
||||
: public std::basic_iostream<CharT, CharTraits>
|
||||
|
||||
class basic_bufferstream :
|
||||
/// @cond
|
||||
private basic_bufferbuf<CharT, CharTraits>,
|
||||
/// @endcond
|
||||
public std::basic_iostream<CharT, CharTraits>
|
||||
{
|
||||
public: // Typedefs
|
||||
typedef typename std::basic_ios
|
||||
@@ -381,8 +410,11 @@ class basic_bufferstream
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_iostream<char_type, CharTraits> base_t;
|
||||
typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t;
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_iostream<char_type, CharTraits> base_t;
|
||||
bufferbuf_t & get_buf() { return *this; }
|
||||
const bufferbuf_t & get_buf() const{ return *this; }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
@@ -390,16 +422,28 @@ class basic_bufferstream
|
||||
//!Does not throw.
|
||||
basic_bufferstream(std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: //basic_ios_t() is called first (lefting it uninitialized) as it's a
|
||||
//virtual base of basic_istream. The class will be initialized when
|
||||
//basic_istream is constructed calling basic_ios_t::init().
|
||||
//As bufferbuf_t's constructor does not throw there is no risk of
|
||||
//calling the basic_ios_t's destructor without calling basic_ios_t::init()
|
||||
bufferbuf_t(mode)
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
//!Constructor. Assigns formatting buffer.
|
||||
//!Does not throw.
|
||||
basic_bufferstream(CharT *buf, std::size_t length,
|
||||
std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(buf, length, mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: //basic_ios_t() is called first (lefting it uninitialized) as it's a
|
||||
//virtual base of basic_istream. The class will be initialized when
|
||||
//basic_istream is constructed calling basic_ios_t::init().
|
||||
//As bufferbuf_t's constructor does not throw there is no risk of
|
||||
//calling the basic_ios_t's destructor without calling basic_ios_t::init()
|
||||
bufferbuf_t(buf, length, mode)
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
~basic_bufferstream(){}
|
||||
|
||||
@@ -407,22 +451,17 @@ class basic_bufferstream
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_bufferbuf<CharT, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
|
||||
{ return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); }
|
||||
|
||||
//!Returns the pointer and size of the internal buffer.
|
||||
//!Does not throw.
|
||||
std::pair<CharT *, std::size_t> buffer() const
|
||||
{ return m_buf.buffer(); }
|
||||
{ return get_buf().buffer(); }
|
||||
|
||||
//!Sets the underlying buffer to a new value. Resets
|
||||
//!stream position. Does not throw.
|
||||
void buffer(CharT *buf, std::size_t length)
|
||||
{ m_buf.buffer(buf, length); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_bufferbuf<CharT, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
{ get_buf().buffer(buf, length); }
|
||||
};
|
||||
|
||||
//Some typedefs to simplify usage
|
||||
|
||||
@@ -92,8 +92,6 @@ class basic_vectorbuf
|
||||
: base_t(), m_mode(mode), m_vect(param)
|
||||
{ this->initialize_pointers(); }
|
||||
|
||||
virtual ~basic_vectorbuf(){}
|
||||
|
||||
public:
|
||||
|
||||
//!Swaps the underlying vector with the passed vector.
|
||||
@@ -367,10 +365,10 @@ class basic_vectorbuf
|
||||
//!boost::interprocess::basic_string
|
||||
template <class CharVector, class CharTraits>
|
||||
class basic_ivectorstream
|
||||
: public std::basic_istream<typename CharVector::value_type, CharTraits>
|
||||
/// @cond
|
||||
: private basic_vectorbuf<CharVector, CharTraits>
|
||||
, private basic_vectorbuf<CharVector, CharTraits>
|
||||
/// @endcond
|
||||
, public std::basic_istream<typename CharVector::value_type, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef CharVector vector_type;
|
||||
@@ -384,56 +382,62 @@ class basic_ivectorstream
|
||||
/// @cond
|
||||
private:
|
||||
typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_istream<char_type, CharTraits> base_t;
|
||||
|
||||
vectorbuf_t & m_buf() { return *this; }
|
||||
const vectorbuf_t & m_buf() const{ return *this; }
|
||||
vectorbuf_t & get_buf() { return *this; }
|
||||
const vectorbuf_t & get_buf() const{ return *this; }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
//!Constructor. Throws if vector_type default
|
||||
//!constructor throws.
|
||||
basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in)
|
||||
: vectorbuf_t(mode | std::ios_base::in), base_t(&m_buf())
|
||||
{}
|
||||
: base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
|
||||
//(via basic_ios::init() call in base_t's constructor) without the risk of a
|
||||
//previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
|
||||
, vectorbuf_t(mode | std::ios_base::in)
|
||||
{ this->base_t::rdbuf(&get_buf()); }
|
||||
|
||||
//!Constructor. Throws if vector_type(const VectorParameter ¶m)
|
||||
//!throws.
|
||||
template<class VectorParameter>
|
||||
basic_ivectorstream(const VectorParameter ¶m,
|
||||
std::ios_base::openmode mode = std::ios_base::in)
|
||||
: vectorbuf_t(param, mode | std::ios_base::in), base_t(&m_buf())
|
||||
: vectorbuf_t(param, mode | std::ios_base::in)
|
||||
//basic_ios_t() is constructed uninitialized as virtual base
|
||||
//and initialized inside base_t calling basic_ios::init()
|
||||
, base_t(&get_buf())
|
||||
{}
|
||||
|
||||
~basic_ivectorstream(){};
|
||||
|
||||
public:
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); }
|
||||
{ return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
|
||||
|
||||
//!Swaps the underlying vector with the passed vector.
|
||||
//!This function resets the read position in the stream.
|
||||
//!Does not throw.
|
||||
void swap_vector(vector_type &vect)
|
||||
{ m_buf().swap_vector(vect); }
|
||||
{ get_buf().swap_vector(vect); }
|
||||
|
||||
//!Returns a const reference to the internal vector.
|
||||
//!Does not throw.
|
||||
const vector_type &vector() const
|
||||
{ return m_buf().vector(); }
|
||||
{ return get_buf().vector(); }
|
||||
|
||||
//!Calls reserve() method of the internal vector.
|
||||
//!Resets the stream to the first position.
|
||||
//!Throws if the internals vector's reserve throws.
|
||||
void reserve(typename vector_type::size_type size)
|
||||
{ m_buf().reserve(size); }
|
||||
{ get_buf().reserve(size); }
|
||||
|
||||
//!Calls clear() method of the internal vector.
|
||||
//!Resets the stream to the first position.
|
||||
void clear()
|
||||
{ m_buf().clear(); }
|
||||
{ get_buf().clear(); }
|
||||
};
|
||||
|
||||
//!A basic_ostream class that holds a character vector specified by CharVector
|
||||
@@ -442,10 +446,10 @@ class basic_ivectorstream
|
||||
//!boost::interprocess::basic_string
|
||||
template <class CharVector, class CharTraits>
|
||||
class basic_ovectorstream
|
||||
: public std::basic_ostream<typename CharVector::value_type, CharTraits>
|
||||
/// @cond
|
||||
: private basic_vectorbuf<CharVector, CharTraits>
|
||||
, private basic_vectorbuf<CharVector, CharTraits>
|
||||
/// @endcond
|
||||
, public std::basic_ostream<typename CharVector::value_type, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef CharVector vector_type;
|
||||
@@ -459,54 +463,58 @@ class basic_ovectorstream
|
||||
/// @cond
|
||||
private:
|
||||
typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_ostream<char_type, CharTraits> base_t;
|
||||
|
||||
vectorbuf_t & m_buf() { return *this; }
|
||||
const vectorbuf_t & m_buf()const { return *this; }
|
||||
vectorbuf_t & get_buf() { return *this; }
|
||||
const vectorbuf_t & get_buf()const { return *this; }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
//!Constructor. Throws if vector_type default
|
||||
//!constructor throws.
|
||||
basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out)
|
||||
: vectorbuf_t(mode | std::ios_base::out), base_t(&m_buf())
|
||||
{}
|
||||
: base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
|
||||
//(via basic_ios::init() call in base_t's constructor) without the risk of a
|
||||
//previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
|
||||
, vectorbuf_t(mode | std::ios_base::out)
|
||||
{ this->base_t::rdbuf(&get_buf()); }
|
||||
|
||||
//!Constructor. Throws if vector_type(const VectorParameter ¶m)
|
||||
//!throws.
|
||||
template<class VectorParameter>
|
||||
basic_ovectorstream(const VectorParameter ¶m,
|
||||
std::ios_base::openmode mode = std::ios_base::out)
|
||||
: vectorbuf_t(param, mode | std::ios_base::out), base_t(&m_buf())
|
||||
{}
|
||||
|
||||
~basic_ovectorstream(){}
|
||||
: base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
|
||||
//(via basic_ios::init() call in base_t's constructor) without the risk of a
|
||||
//previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
|
||||
, vectorbuf_t(param, mode | std::ios_base::out)
|
||||
{ this->base_t::rdbuf(&get_buf()); }
|
||||
|
||||
public:
|
||||
//!Returns the address of the stored
|
||||
//!stream buffer.
|
||||
basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); }
|
||||
{ return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
|
||||
|
||||
//!Swaps the underlying vector with the passed vector.
|
||||
//!This function resets the write position in the stream.
|
||||
//!Does not throw.
|
||||
void swap_vector(vector_type &vect)
|
||||
{ m_buf().swap_vector(vect); }
|
||||
{ get_buf().swap_vector(vect); }
|
||||
|
||||
//!Returns a const reference to the internal vector.
|
||||
//!Does not throw.
|
||||
const vector_type &vector() const
|
||||
{ return m_buf().vector(); }
|
||||
{ return get_buf().vector(); }
|
||||
|
||||
//!Calls reserve() method of the internal vector.
|
||||
//!Resets the stream to the first position.
|
||||
//!Throws if the internals vector's reserve throws.
|
||||
void reserve(typename vector_type::size_type size)
|
||||
{ m_buf().reserve(size); }
|
||||
{ get_buf().reserve(size); }
|
||||
};
|
||||
|
||||
|
||||
//!A basic_iostream class that holds a character vector specified by CharVector
|
||||
//!template parameter as its formatting buffer. The vector must have
|
||||
//!contiguous storage, like std::vector, boost::interprocess::vector or
|
||||
@@ -514,7 +522,9 @@ class basic_ovectorstream
|
||||
template <class CharVector, class CharTraits>
|
||||
class basic_vectorstream
|
||||
: public std::basic_iostream<typename CharVector::value_type, CharTraits>
|
||||
|
||||
/// @cond
|
||||
, private basic_vectorbuf<CharVector, CharTraits>
|
||||
/// @endcond
|
||||
{
|
||||
public:
|
||||
typedef CharVector vector_type;
|
||||
@@ -527,8 +537,12 @@ class basic_vectorstream
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_iostream<char_type, CharTraits> base_t;
|
||||
typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_iostream<char_type, CharTraits> base_t;
|
||||
|
||||
vectorbuf_t & get_buf() { return *this; }
|
||||
const vectorbuf_t & get_buf() const{ return *this; }
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
@@ -536,50 +550,49 @@ class basic_vectorstream
|
||||
//!constructor throws.
|
||||
basic_vectorstream(std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
: base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
|
||||
//(via basic_ios::init() call in base_t's constructor) without the risk of a
|
||||
//previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
|
||||
, vectorbuf_t(mode)
|
||||
{ this->base_t::rdbuf(&get_buf()); }
|
||||
|
||||
//!Constructor. Throws if vector_type(const VectorParameter ¶m)
|
||||
//!throws.
|
||||
template<class VectorParameter>
|
||||
basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(param, mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_vectorstream(){}
|
||||
: base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
|
||||
//(via basic_ios::init() call in base_t's constructor) without the risk of a
|
||||
//previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
|
||||
, vectorbuf_t(param, mode)
|
||||
{ this->base_t::rdbuf(&get_buf()); }
|
||||
|
||||
public:
|
||||
//Returns the address of the stored stream buffer.
|
||||
basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf); }
|
||||
{ return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
|
||||
|
||||
//!Swaps the underlying vector with the passed vector.
|
||||
//!This function resets the read/write position in the stream.
|
||||
//!Does not throw.
|
||||
void swap_vector(vector_type &vect)
|
||||
{ m_buf.swap_vector(vect); }
|
||||
{ get_buf().swap_vector(vect); }
|
||||
|
||||
//!Returns a const reference to the internal vector.
|
||||
//!Does not throw.
|
||||
const vector_type &vector() const
|
||||
{ return m_buf.vector(); }
|
||||
{ return get_buf().vector(); }
|
||||
|
||||
//!Calls reserve() method of the internal vector.
|
||||
//!Resets the stream to the first position.
|
||||
//!Throws if the internals vector's reserve throws.
|
||||
void reserve(typename vector_type::size_type size)
|
||||
{ m_buf.reserve(size); }
|
||||
{ get_buf().reserve(size); }
|
||||
|
||||
//!Calls clear() method of the internal vector.
|
||||
//!Resets the stream to the first position.
|
||||
void clear()
|
||||
{ m_buf.clear(); }
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
basic_vectorbuf<CharVector, CharTraits> m_buf;
|
||||
/// @endcond
|
||||
{ get_buf().clear(); }
|
||||
};
|
||||
|
||||
//Some typedefs to simplify usage
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
//!\file
|
||||
@@ -149,7 +150,7 @@ class file_lock
|
||||
using namespace boost::detail;
|
||||
|
||||
if(now >= abs_time) return false;
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(!ipcdetail::try_acquire_file_lock(hnd, acquired))
|
||||
return false;
|
||||
@@ -164,7 +165,7 @@ class file_lock
|
||||
return true;
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
}while (true);
|
||||
}
|
||||
@@ -178,7 +179,7 @@ class file_lock
|
||||
|
||||
if(now >= abs_time) return false;
|
||||
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(!ipcdetail::try_acquire_file_lock_sharable(hnd, acquired))
|
||||
return false;
|
||||
@@ -193,7 +194,7 @@ class file_lock
|
||||
return true;
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
}while (true);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
# include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
# include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#endif
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
@@ -119,7 +120,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
//Obtain current count and target time
|
||||
boost::posix_time::ptime now = microsec_clock::universal_time();
|
||||
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(this->try_lock()){
|
||||
break;
|
||||
@@ -130,7 +131,7 @@ inline bool posix_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
return false;
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}while (true);
|
||||
return true;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#ifndef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
# include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
# include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#endif
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
@@ -108,7 +109,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
|
||||
|
||||
//Obtain current count and target time
|
||||
boost::posix_time::ptime now = microsec_clock::universal_time();
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(this->try_lock()){
|
||||
break;
|
||||
@@ -119,7 +120,7 @@ inline bool posix_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab
|
||||
return false;
|
||||
}
|
||||
// relinquish current time slice
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}while (true);
|
||||
return true;
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <boost/interprocess/sync/posix/ptime_to_timespec.hpp>
|
||||
#else
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
@@ -195,11 +196,11 @@ inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &
|
||||
return false;
|
||||
#else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
boost::posix_time::ptime now;
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(semaphore_try_wait(handle))
|
||||
return true;
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}while((now = microsec_clock::universal_time()) < abs_time);
|
||||
return false;
|
||||
#endif //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
@@ -140,9 +141,9 @@ inline void spin_condition::notify(boost::uint32_t command)
|
||||
}
|
||||
|
||||
//Notify that all threads should execute wait logic
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(SLEEP != atomic_cas32(const_cast<boost::uint32_t*>(&m_command), command, SLEEP)){
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
//The enter mutex will rest locked until the last waiting thread unlocks it
|
||||
}
|
||||
@@ -206,9 +207,9 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled,
|
||||
while(1){
|
||||
//The thread sleeps/spins until a spin_condition commands a notification
|
||||
//Notification occurred, we will lock the checking mutex so that
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(atomic_read32(&m_command) == SLEEP){
|
||||
yield(k++);
|
||||
swait.yield();
|
||||
|
||||
//Check for timeout
|
||||
if(tout_enabled){
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
@@ -60,7 +61,7 @@ inline spin_mutex::~spin_mutex()
|
||||
|
||||
inline void spin_mutex::lock(void)
|
||||
{
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast<boost::uint32_t*>(&m_s), 1, 0);
|
||||
|
||||
@@ -68,7 +69,7 @@ inline void spin_mutex::lock(void)
|
||||
break;
|
||||
}
|
||||
// relinquish current timeslice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}while (true);
|
||||
}
|
||||
|
||||
@@ -87,7 +88,7 @@ inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
//Obtain current count and target time
|
||||
boost::posix_time::ptime now = microsec_clock::universal_time();
|
||||
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(this->try_lock()){
|
||||
break;
|
||||
@@ -98,7 +99,7 @@ inline bool spin_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
return false;
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}while (true);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
@@ -59,11 +60,9 @@ inline void spin_semaphore::post()
|
||||
|
||||
inline void spin_semaphore::wait()
|
||||
{
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(!ipcdetail::atomic_add_unless32(&m_count, boost::uint32_t(-1), boost::uint32_t(0))){
|
||||
while(ipcdetail::atomic_read32(&m_count) == 0){
|
||||
ipcdetail::yield(k++);
|
||||
}
|
||||
swait.yield();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
//Obtain current count and target time
|
||||
boost::posix_time::ptime now(microsec_clock::universal_time());
|
||||
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
do{
|
||||
if(this->try_wait()){
|
||||
break;
|
||||
@@ -92,7 +91,7 @@ inline bool spin_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
return this->try_wait();
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}while (true);
|
||||
return true;
|
||||
}
|
||||
|
||||
186
include/boost/interprocess/sync/spin/wait.hpp
Normal file
186
include/boost/interprocess/sync/spin/wait.hpp
Normal file
@@ -0,0 +1,186 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Peter Dimov 2008.
|
||||
// (C) Copyright Ion Gaztanaga 2013. 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Parts of this file come from boost/smart_ptr/detail/yield_k.hpp
|
||||
//Many thanks to Peter Dimov.
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
|
||||
#define BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
|
||||
//#define BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
// BOOST_INTERPROCESS_SMT_PAUSE
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
|
||||
|
||||
extern "C" void _mm_pause();
|
||||
#pragma intrinsic( _mm_pause )
|
||||
|
||||
#define BOOST_INTERPROCESS_SMT_PAUSE _mm_pause();
|
||||
|
||||
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
|
||||
|
||||
#define BOOST_INTERPROCESS_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail {
|
||||
|
||||
template<int Dummy = 0>
|
||||
class num_core_holder
|
||||
{
|
||||
public:
|
||||
static unsigned int get()
|
||||
{
|
||||
if(!num_cores){
|
||||
return ipcdetail::get_num_cores();
|
||||
}
|
||||
else{
|
||||
return num_cores;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static unsigned int num_cores;
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
unsigned int num_core_holder<Dummy>::num_cores = ipcdetail::get_num_cores();
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
class spin_wait
|
||||
{
|
||||
public:
|
||||
spin_wait()
|
||||
: m_k(0u)
|
||||
{
|
||||
(void)m_nop_pause_limit;
|
||||
(void)m_yield_only_counts;
|
||||
(void)m_count_start;
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
~spin_wait()
|
||||
{
|
||||
if(m_k){
|
||||
std::cout << "final m_k: " << m_k
|
||||
<< " system tick(us): " << ipcdetail::get_system_tick_us() << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned int count() const
|
||||
{ return m_k; }
|
||||
|
||||
void yield()
|
||||
{
|
||||
//Lazy initialization of limits
|
||||
if( !m_k){
|
||||
this->init_limits();
|
||||
}
|
||||
//Nop tries
|
||||
if( m_k < (m_nop_pause_limit >> 2) ){
|
||||
|
||||
}
|
||||
//Pause tries if the processor supports it
|
||||
#if defined(BOOST_INTERPROCESS_SMT_PAUSE)
|
||||
else if( m_k < m_nop_pause_limit ){
|
||||
BOOST_INTERPROCESS_SMT_PAUSE
|
||||
}
|
||||
#endif
|
||||
//Yield/Sleep strategy
|
||||
else{
|
||||
//Lazy initialization of tick information
|
||||
if(m_k == m_nop_pause_limit){
|
||||
this->init_tick_info();
|
||||
}
|
||||
else if( this->yield_or_sleep() ){
|
||||
ipcdetail::thread_yield();
|
||||
}
|
||||
else{
|
||||
ipcdetail::thread_sleep_tick();
|
||||
}
|
||||
}
|
||||
++m_k;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_k = 0u;
|
||||
m_count_start = ipcdetail::get_current_system_highres_count();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init_limits()
|
||||
{
|
||||
unsigned int num_cores = ipcdetail::num_core_holder<0>::get();
|
||||
m_nop_pause_limit = num_cores > 1u ? 32u : 0u;
|
||||
}
|
||||
|
||||
void init_tick_info()
|
||||
{
|
||||
m_yield_only_counts = ipcdetail::get_system_tick_in_highres_counts();
|
||||
m_count_start = ipcdetail::get_current_system_highres_count();
|
||||
}
|
||||
|
||||
//Returns true if yield must be called, false is sleep must be called
|
||||
bool yield_or_sleep()
|
||||
{
|
||||
if(ipcdetail::is_highres_count_zero(m_yield_only_counts)){ //If yield-only limit was reached then yield one in every two tries
|
||||
return (m_k & 1u) != 0;
|
||||
}
|
||||
else{ //Try to see if we've reched yield-only time limit
|
||||
const ipcdetail::OS_highres_count_t now = ipcdetail::get_current_system_highres_count();
|
||||
const ipcdetail::OS_highres_count_t elapsed = ipcdetail::system_highres_count_subtract(now, m_count_start);
|
||||
if(!ipcdetail::system_highres_count_less(elapsed, m_yield_only_counts)){
|
||||
#ifdef BOOST_INTERPROCESS_SPIN_WAIT_DEBUG
|
||||
std::cout << "elapsed!\n"
|
||||
<< " m_yield_only_counts: ";
|
||||
ipcdetail::ostream_highres_count(std::cout, m_yield_only_counts)
|
||||
<< " system tick(us): " << ipcdetail::get_system_tick_us() << '\n'
|
||||
<< " m_k: " << m_k << " elapsed counts: ";
|
||||
ipcdetail::ostream_highres_count(std::cout, elapsed) << std::endl;
|
||||
#endif
|
||||
//Yield-only time reached, now it's time to sleep
|
||||
ipcdetail::zero_highres_count(m_yield_only_counts);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true; //Otherwise yield
|
||||
}
|
||||
|
||||
unsigned int m_k;
|
||||
unsigned int m_nop_pause_limit;
|
||||
ipcdetail::OS_highres_count_t m_yield_only_counts;
|
||||
ipcdetail::OS_highres_count_t m_count_start;
|
||||
};
|
||||
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_INTERPROCESS_SYNC_WAIT_HPP_INCLUDED
|
||||
@@ -33,7 +33,7 @@ static int bufferstream_test()
|
||||
const int BufSize = 10001;
|
||||
//This will be zero-initialized
|
||||
static char buffer [BufSize];
|
||||
bufferstream bufstream;;
|
||||
bufferstream bufstream;
|
||||
std::stringstream std_stringstream;
|
||||
std::string str1, str2, str3("testline:");
|
||||
int number1, number2;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <cstdlib> //std::system
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/interprocess/managed_shared_memory.hpp>
|
||||
#include <boost/interprocess/sync/spin/wait.hpp>
|
||||
#include "get_process_id_name.hpp"
|
||||
#include "mutex_test_template.hpp"
|
||||
#include <iostream>
|
||||
@@ -66,9 +67,9 @@ int robust_mutex_test(int argc, char *argv[])
|
||||
return 1;
|
||||
|
||||
//Wait until child locks the mutexes and dies
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(!*go_ahead){
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
|
||||
std::cout << "... recovering mutex[0]" << std::endl;
|
||||
@@ -164,9 +165,9 @@ int robust_mutex_test(int argc, char *argv[])
|
||||
}
|
||||
|
||||
//Wait until child locks the 2nd mutex and dies
|
||||
unsigned k = 0;
|
||||
spin_wait swait;
|
||||
while(!*go_ahead2){
|
||||
ipcdetail::yield(k++);
|
||||
swait.yield();
|
||||
}
|
||||
|
||||
//Done, now try to lock number 3 to see if robust
|
||||
|
||||
Reference in New Issue
Block a user