Merged Interprocess to the release branch

[SVN r85615]
This commit is contained in:
Ion Gaztañaga
2013-09-08 20:07:03 +00:00
parent c99f2ccc48
commit e559ac3275
23 changed files with 753 additions and 331 deletions

View File

@@ -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

View File

@@ -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]

View File

@@ -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;
}

View File

@@ -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?

View File

@@ -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);
}

View File

@@ -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];

View File

@@ -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;

View File

@@ -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];

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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 &param)
//!throws.
template<class VectorParameter>
basic_ivectorstream(const VectorParameter &param,
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 &param)
//!throws.
template<class VectorParameter>
basic_ovectorstream(const VectorParameter &param,
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 &param)
//!throws.
template<class VectorParameter>
basic_vectorstream(const VectorParameter &param, 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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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){

View File

@@ -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;

View File

@@ -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;
}

View 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

View File

@@ -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;

View File

@@ -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