Added boost header
This commit is contained in:
593
test/external/boost/interprocess/detail/atomic.hpp
vendored
Normal file
593
test/external/boost/interprocess/detail/atomic.hpp
vendored
Normal file
@@ -0,0 +1,593 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006-2009
|
||||
// (C) Copyright Markus Schoepflin 2007
|
||||
// (C) Copyright Bryce Lelbach 2010
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically increment an boost::uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem);
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem);
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val);
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with": what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp);
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <boost/interprocess/detail/win32_api.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return winapi::interlocked_decrement(reinterpret_cast<volatile long*>(mem)) + 1; }
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return winapi::interlocked_increment(reinterpret_cast<volatile long*>(mem))-1; }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ winapi::interlocked_exchange(reinterpret_cast<volatile long*>(mem), val); }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with": what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{ return winapi::interlocked_compare_exchange(reinterpret_cast<volatile long*>(mem), with, cmp); }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
boost::uint32_t prev = cmp;
|
||||
// This version by Mans Rullgard of Pathscale
|
||||
__asm__ __volatile__ ( "lock\n\t"
|
||||
"cmpxchg %2,%0"
|
||||
: "+m"(*mem), "+a"(prev)
|
||||
: "r"(with)
|
||||
: "cc");
|
||||
|
||||
return prev;
|
||||
/*
|
||||
asm volatile( "lock\n\t"
|
||||
"cmpxchg %3,%1"
|
||||
: "=a" (prev), "=m" (*(mem))
|
||||
: "0" (prev), "r" (with)
|
||||
: "memory", "cc");
|
||||
*/
|
||||
/*
|
||||
boost::uint32_t prev;
|
||||
|
||||
asm volatile ("lock; cmpxchgl %1, %2"
|
||||
: "=a" (prev)
|
||||
: "r" (with), "m" (*(mem)), "0"(cmp));
|
||||
asm volatile("" : : : "memory");
|
||||
|
||||
return prev;
|
||||
*/
|
||||
}
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{
|
||||
// int r = *pw;
|
||||
// *mem += val;
|
||||
// return r;
|
||||
int r;
|
||||
|
||||
asm volatile
|
||||
(
|
||||
"lock\n\t"
|
||||
"xadd %1, %0":
|
||||
"+m"( *mem ), "=r"( r ): // outputs (%0, %1)
|
||||
"1"( val ): // inputs (%2 == %1)
|
||||
"memory", "cc" // clobbers
|
||||
);
|
||||
|
||||
return r;
|
||||
/*
|
||||
asm volatile( "lock\n\t; xaddl %0,%1"
|
||||
: "=r"(val), "=m"(*mem)
|
||||
: "0"(val), "m"(*mem));
|
||||
asm volatile("" : : : "memory");
|
||||
|
||||
return val;
|
||||
*/
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, (boost::uint32_t)-1); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__))
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{
|
||||
boost::uint32_t prev, temp;
|
||||
|
||||
asm volatile ("0:\n\t" // retry local label
|
||||
"lwarx %0,0,%2\n\t" // load prev and reserve
|
||||
"add %1,%0,%3\n\t" // temp = prev + val
|
||||
"stwcx. %1,0,%2\n\t" // conditionally store
|
||||
"bne- 0b" // start over if we lost
|
||||
// the reservation
|
||||
//XXX find a cleaner way to define the temp
|
||||
//it's not an output
|
||||
: "=&r" (prev), "=&r" (temp) // output, temp
|
||||
: "b" (mem), "r" (val) // inputs
|
||||
: "memory", "cc"); // clobbered
|
||||
return prev;
|
||||
}
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
boost::uint32_t prev;
|
||||
|
||||
asm volatile ("0:\n\t" // retry local label
|
||||
"lwarx %0,0,%1\n\t" // load prev and reserve
|
||||
"cmpw %0,%3\n\t" // does it match cmp?
|
||||
"bne- 1f\n\t" // ...no, bail out
|
||||
"stwcx. %2,0,%1\n\t" // ...yes, conditionally
|
||||
// store with
|
||||
"bne- 0b\n\t" // start over if we lost
|
||||
// the reservation
|
||||
"1:" // exit local label
|
||||
|
||||
: "=&r"(prev) // output
|
||||
: "b" (mem), "r" (with), "r"(cmp) // inputs
|
||||
: "memory", "cc"); // clobbered
|
||||
return prev;
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, boost::uint32_t(-1u)); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ return __sync_fetch_and_add(const_cast<boost::uint32_t *>(mem), val); }
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, (boost::uint32_t)-1); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{ return __sync_val_compare_and_swap(const_cast<boost::uint32_t *>(mem), cmp, with); }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif (defined(sun) || defined(__sun))
|
||||
|
||||
#include <atomic.h>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically add 'val' to an boost::uint32_t
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (int32_t)val) - val; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{ return atomic_cas_32(reinterpret_cast<volatile ::uint32_t*>(mem), cmp, with); }
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), 1) - 1; }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add_32_nv(reinterpret_cast<volatile ::uint32_t*>(mem), (boost::uint32_t)-1) + 1; }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__osf__) && defined(__DECCXX)
|
||||
|
||||
#include <machine/builtins.h>
|
||||
#include <c_asm.h>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
//! Atomically decrement a uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
//! Acquire, memory barrier after decrement.
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ boost::uint32_t old_val = __ATOMIC_DECREMENT_LONG(mem); __MB(); return old_val; }
|
||||
|
||||
//! Atomically increment a uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
//! Release, memory barrier before increment.
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ __MB(); return __ATOMIC_INCREMENT_LONG(mem); }
|
||||
|
||||
// Rational for the implementation of the atomic read and write functions.
|
||||
//
|
||||
// 1. The Alpha Architecture Handbook requires that access to a byte,
|
||||
// an aligned word, an aligned longword, or an aligned quadword is
|
||||
// atomic. (See 'Alpha Architecture Handbook', version 4, chapter 5.2.2.)
|
||||
//
|
||||
// 2. The CXX User's Guide states that volatile quantities are accessed
|
||||
// with single assembler instructions, and that a compilation error
|
||||
// occurs when declaring a quantity as volatile which is not properly
|
||||
// aligned.
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
//! Acquire, memory barrier after load.
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ boost::uint32_t old_val = *mem; __MB(); return old_val; }
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
//! Release, memory barrier before store.
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ __MB(); *mem = val; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
//! Memory barrier between load and store.
|
||||
inline boost::uint32_t atomic_cas32(
|
||||
volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
// Note:
|
||||
//
|
||||
// Branch prediction prefers backward branches, and the Alpha Architecture
|
||||
// Handbook explicitely states that the loop should not be implemented like
|
||||
// it is below. (See chapter 4.2.5.) Therefore the code should probably look
|
||||
// like this:
|
||||
//
|
||||
// return asm(
|
||||
// "10: ldl_l %v0,(%a0) ;"
|
||||
// " cmpeq %v0,%a2,%t0 ;"
|
||||
// " beq %t0,20f ;"
|
||||
// " mb ;"
|
||||
// " mov %a1,%t0 ;"
|
||||
// " stl_c %t0,(%a0) ;"
|
||||
// " beq %t0,30f ;"
|
||||
// "20: ret ;"
|
||||
// "30: br 10b;",
|
||||
// mem, with, cmp);
|
||||
//
|
||||
// But as the compiler always transforms this into the form where a backward
|
||||
// branch is taken on failure, we can as well implement it in the straight
|
||||
// forward form, as this is what it will end up in anyway.
|
||||
|
||||
return asm(
|
||||
"10: ldl_l %v0,(%a0) ;" // load prev value from mem and lock mem
|
||||
" cmpeq %v0,%a2,%t0 ;" // compare with given value
|
||||
" beq %t0,20f ;" // if not equal, we're done
|
||||
" mb ;" // memory barrier
|
||||
" mov %a1,%t0 ;" // load new value into scratch register
|
||||
" stl_c %t0,(%a0) ;" // store new value to locked mem (overwriting scratch)
|
||||
" beq %t0,10b ;" // store failed because lock has been stolen, retry
|
||||
"20: ",
|
||||
mem, with, cmp);
|
||||
}
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX)
|
||||
|
||||
#include <builtins.h>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting
|
||||
//all the functions with casts
|
||||
|
||||
//! From XLC documenation :
|
||||
//! This function can be used with a subsequent stwcxu call to implement a
|
||||
//! read-modify-write on a specified memory location. The two functions work
|
||||
//! together to ensure that if the store is successfully performed, no other
|
||||
//! processor or mechanism can modify the target doubleword between the time
|
||||
//! lwarxu function is executed and the time the stwcxu functio ncompletes.
|
||||
//! "mem" : pointer to the object
|
||||
//! Returns the value at pointed to by mem
|
||||
inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem)
|
||||
{
|
||||
return static_cast<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(mem)));
|
||||
}
|
||||
|
||||
//! "mem" : pointer to the object
|
||||
//! "val" : the value to store
|
||||
//! Returns true if the update of mem is successful and false if it is
|
||||
//!unsuccessful
|
||||
inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val)
|
||||
{
|
||||
return (__stwcx(reinterpret_cast<volatile int*>(mem), static_cast<int>(val)) != 0);
|
||||
}
|
||||
|
||||
//! "mem": pointer to the object
|
||||
//! "val": amount to add
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_add32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{
|
||||
boost::uint32_t oldValue;
|
||||
do
|
||||
{
|
||||
oldValue = lwarxu(mem);
|
||||
}while (!stwcxu(mem, oldValue+val));
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
//! Atomically increment an apr_uint32_t by 1
|
||||
//! "mem": pointer to the object
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, 1); }
|
||||
|
||||
//! Atomically decrement an boost::uint32_t by 1
|
||||
//! "mem": pointer to the atomic value
|
||||
//! Returns the old value pointed to by mem
|
||||
inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem)
|
||||
{ return atomic_add32(mem, (boost::uint32_t)-1); }
|
||||
|
||||
//! Atomically read an boost::uint32_t from memory
|
||||
inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem)
|
||||
{ return *mem; }
|
||||
|
||||
//! Compare an boost::uint32_t's value with "cmp".
|
||||
//! If they are the same swap the value with "with"
|
||||
//! "mem": pointer to the value
|
||||
//! "with" what to swap it with
|
||||
//! "cmp": the value to compare it to
|
||||
//! Returns the old value of *mem
|
||||
inline boost::uint32_t atomic_cas32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp)
|
||||
{
|
||||
boost::uint32_t oldValue;
|
||||
boost::uint32_t valueToStore;
|
||||
do
|
||||
{
|
||||
oldValue = lwarxu(mem);
|
||||
} while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue));
|
||||
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
//! Atomically set an boost::uint32_t in memory
|
||||
//! "mem": pointer to the object
|
||||
//! "param": val value that the object will assume
|
||||
inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val)
|
||||
{ *mem = val; }
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#else
|
||||
|
||||
#error No atomic operations implemented for this platform, sorry!
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
inline bool atomic_add_unless32
|
||||
(volatile boost::uint32_t *mem, boost::uint32_t value, boost::uint32_t unless_this)
|
||||
{
|
||||
boost::uint32_t old, c(atomic_read32(mem));
|
||||
while(c != unless_this && (old = atomic_cas32(mem, c + value, c)) != c){
|
||||
c = old;
|
||||
}
|
||||
return c != unless_this;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP
|
||||
29
test/external/boost/interprocess/detail/cast_tags.hpp
vendored
Normal file
29
test/external/boost/interprocess/detail/cast_tags.hpp
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
|
||||
#define BOOST_INTERPROCESS_CAST_TAGS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
struct static_cast_tag {};
|
||||
struct const_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
struct reinterpret_cast_tag {};
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP
|
||||
|
||||
47
test/external/boost/interprocess/detail/config_begin.hpp
vendored
Normal file
47
test/external/boost/interprocess/detail/config_begin.hpp
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef BOOST_INTERPROCESS_CONFIG_INCLUDED
|
||||
#define BOOST_INTERPROCESS_CONFIG_INCLUDED
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#ifndef _CRT_SECURE_NO_DEPRECATE
|
||||
#define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4702) // unreachable code
|
||||
#pragma warning (disable : 4706) // assignment within conditional expression
|
||||
#pragma warning (disable : 4127) // conditional expression is constant
|
||||
#pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning (disable : 4284) // odd return type for operator->
|
||||
#pragma warning (disable : 4244) // possible loss of data
|
||||
#pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2"
|
||||
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
|
||||
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
|
||||
#pragma warning (disable : 4355) // "this" : used in base member initializer list
|
||||
#pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated
|
||||
#pragma warning (disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning (disable : 4512) // assignment operator could not be generated
|
||||
#pragma warning (disable : 4514) // unreferenced inline removed
|
||||
#pragma warning (disable : 4521) // Disable "multiple copy constructors specified"
|
||||
#pragma warning (disable : 4522) // "class" : multiple assignment operators specified
|
||||
#pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter
|
||||
#pragma warning (disable : 4710) // function not inlined
|
||||
#pragma warning (disable : 4711) // function selected for automatic inline expansion
|
||||
#pragma warning (disable : 4786) // identifier truncated in debug info
|
||||
#pragma warning (disable : 4996) // "function": was declared deprecated
|
||||
#pragma warning (disable : 4197) // top-level volatile in cast is ignored
|
||||
#pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception'
|
||||
// with /GR-; unpredictable behavior may result
|
||||
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
|
||||
#pragma warning (disable : 4671) // the copy constructor is inaccessible
|
||||
#endif
|
||||
17
test/external/boost/interprocess/detail/config_end.hpp
vendored
Normal file
17
test/external/boost/interprocess/detail/config_end.hpp
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#if defined BOOST_MSVC
|
||||
#pragma warning (pop)
|
||||
#ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
|
||||
#undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE
|
||||
#undef _CRT_SECURE_NO_DEPRECATE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
202
test/external/boost/interprocess/detail/file_wrapper.hpp
vendored
Normal file
202
test/external/boost/interprocess/detail/file_wrapper.hpp
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
class file_wrapper
|
||||
{
|
||||
/// @cond
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper)
|
||||
/// @endcond
|
||||
public:
|
||||
|
||||
//!Default constructor.
|
||||
//!Represents an empty file_wrapper.
|
||||
file_wrapper();
|
||||
|
||||
//!Creates a file object with name "name" and mode "mode", with the access mode "mode"
|
||||
//!If the file previously exists, throws an error.
|
||||
file_wrapper(create_only_t, const char *name, mode_t mode, const permissions &perm = permissions())
|
||||
{ this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); }
|
||||
|
||||
//!Tries to create a file with name "name" and mode "mode", with the
|
||||
//!access mode "mode". If the file previously exists, it tries to open it with mode "mode".
|
||||
//!Otherwise throws an error.
|
||||
file_wrapper(open_or_create_t, const char *name, mode_t mode, const permissions &perm = permissions())
|
||||
{ this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); }
|
||||
|
||||
//!Tries to open a file with name "name", with the access mode "mode".
|
||||
//!If the file does not previously exist, it throws an error.
|
||||
file_wrapper(open_only_t, const char *name, mode_t mode)
|
||||
{ this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); }
|
||||
|
||||
//!Moves the ownership of "moved"'s file to *this.
|
||||
//!After the call, "moved" does not represent any file.
|
||||
//!Does not throw
|
||||
file_wrapper(BOOST_RV_REF(file_wrapper) moved)
|
||||
: m_handle(file_handle_t(ipcdetail::invalid_file()))
|
||||
{ this->swap(moved); }
|
||||
|
||||
//!Moves the ownership of "moved"'s file to *this.
|
||||
//!After the call, "moved" does not represent any file.
|
||||
//!Does not throw
|
||||
file_wrapper &operator=(BOOST_RV_REF(file_wrapper) moved)
|
||||
{
|
||||
file_wrapper tmp(boost::interprocess::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps to file_wrappers.
|
||||
//!Does not throw
|
||||
void swap(file_wrapper &other);
|
||||
|
||||
//!Erases a file from the system.
|
||||
//!Returns false on error. Never throws
|
||||
static bool remove(const char *name);
|
||||
|
||||
//!Sets the size of the file
|
||||
void truncate(offset_t length);
|
||||
|
||||
//!Closes the
|
||||
//!file
|
||||
~file_wrapper();
|
||||
|
||||
//!Returns the name of the file
|
||||
//!used in the constructor
|
||||
const char *get_name() const;
|
||||
|
||||
//!Returns the name of the file
|
||||
//!used in the constructor
|
||||
bool get_size(offset_t &size) const;
|
||||
|
||||
//!Returns access mode
|
||||
//!used in the constructor
|
||||
mode_t get_mode() const;
|
||||
|
||||
//!Get mapping handle
|
||||
//!to use with mapped_region
|
||||
mapping_handle_t get_mapping_handle() const;
|
||||
|
||||
private:
|
||||
//!Closes a previously opened file mapping. Never throws.
|
||||
void priv_close();
|
||||
//!Closes a previously opened file mapping. Never throws.
|
||||
bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm);
|
||||
|
||||
file_handle_t m_handle;
|
||||
mode_t m_mode;
|
||||
std::string m_filename;
|
||||
};
|
||||
|
||||
inline file_wrapper::file_wrapper()
|
||||
: m_handle(file_handle_t(ipcdetail::invalid_file()))
|
||||
{}
|
||||
|
||||
inline file_wrapper::~file_wrapper()
|
||||
{ this->priv_close(); }
|
||||
|
||||
inline const char *file_wrapper::get_name() const
|
||||
{ return m_filename.c_str(); }
|
||||
|
||||
inline bool file_wrapper::get_size(offset_t &size) const
|
||||
{ return get_file_size((file_handle_t)m_handle, size); }
|
||||
|
||||
inline void file_wrapper::swap(file_wrapper &other)
|
||||
{
|
||||
std::swap(m_handle, other.m_handle);
|
||||
std::swap(m_mode, other.m_mode);
|
||||
m_filename.swap(other.m_filename);
|
||||
}
|
||||
|
||||
inline mapping_handle_t file_wrapper::get_mapping_handle() const
|
||||
{ return mapping_handle_from_file_handle(m_handle); }
|
||||
|
||||
inline mode_t file_wrapper::get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
inline bool file_wrapper::priv_open_or_create
|
||||
(ipcdetail::create_enum_t type,
|
||||
const char *filename,
|
||||
mode_t mode,
|
||||
const permissions &perm = permissions())
|
||||
{
|
||||
m_filename = filename;
|
||||
|
||||
if(mode != read_only && mode != read_write){
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Open file existing native API to obtain the handle
|
||||
switch(type){
|
||||
case ipcdetail::DoOpen:
|
||||
m_handle = open_existing_file(filename, mode);
|
||||
break;
|
||||
case ipcdetail::DoCreate:
|
||||
m_handle = create_new_file(filename, mode, perm);
|
||||
break;
|
||||
case ipcdetail::DoOpenOrCreate:
|
||||
m_handle = create_or_open_file(filename, mode, perm);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Check for error
|
||||
if(m_handle == invalid_file()){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
|
||||
m_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool file_wrapper::remove(const char *filename)
|
||||
{ return delete_file(filename); }
|
||||
|
||||
inline void file_wrapper::truncate(offset_t length)
|
||||
{
|
||||
if(!truncate_file(m_handle, length)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void file_wrapper::priv_close()
|
||||
{
|
||||
if(m_handle != invalid_file()){
|
||||
close_file(m_handle);
|
||||
m_handle = invalid_file();
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP
|
||||
73
test/external/boost/interprocess/detail/in_place_interface.hpp
vendored
Normal file
73
test/external/boost/interprocess/detail/in_place_interface.hpp
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
|
||||
#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <typeinfo> //typeid
|
||||
|
||||
//!\file
|
||||
//!Describes an abstract interface for placement construction and destruction.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
struct in_place_interface
|
||||
{
|
||||
in_place_interface(std::size_t alignm, std::size_t sz, const char *tname)
|
||||
: alignment(alignm), size(sz), type_name(tname)
|
||||
{}
|
||||
|
||||
std::size_t alignment;
|
||||
std::size_t size;
|
||||
const char *type_name;
|
||||
|
||||
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed) = 0;
|
||||
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) = 0;
|
||||
virtual ~in_place_interface(){}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct placement_destroy : public in_place_interface
|
||||
{
|
||||
placement_destroy()
|
||||
: in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name())
|
||||
{}
|
||||
|
||||
virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed)
|
||||
{
|
||||
T* memory = static_cast<T*>(mem);
|
||||
for(destroyed = 0; destroyed < num; ++destroyed)
|
||||
(memory++)->~T();
|
||||
}
|
||||
|
||||
virtual void construct_n(void *, std::size_t, std::size_t &) {}
|
||||
|
||||
private:
|
||||
void destroy(void *mem)
|
||||
{ static_cast<T*>(mem)->~T(); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
|
||||
1035
test/external/boost/interprocess/detail/intermodule_singleton.hpp
vendored
Normal file
1035
test/external/boost/interprocess/detail/intermodule_singleton.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
31
test/external/boost/interprocess/detail/interprocess_tester.hpp
vendored
Normal file
31
test/external/boost/interprocess/detail/interprocess_tester.hpp
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
class interprocess_tester
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
static void dont_close_on_destruction(T &t)
|
||||
{ t.dont_close_on_destruction(); }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP
|
||||
|
||||
1042
test/external/boost/interprocess/detail/intersegment_ptr.hpp
vendored
Normal file
1042
test/external/boost/interprocess/detail/intersegment_ptr.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
754
test/external/boost/interprocess/detail/managed_memory_impl.hpp
vendored
Normal file
754
test/external/boost/interprocess/detail/managed_memory_impl.hpp
vendored
Normal file
@@ -0,0 +1,754 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
|
||||
#include <boost/interprocess/sync/mutex_family.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/offset_ptr.hpp>
|
||||
#include <boost/interprocess/segment_manager.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
//
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
//
|
||||
#include <utility>
|
||||
#include <fstream>
|
||||
#include <new>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named shared memory allocation user class.
|
||||
//!
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class BasicManagedMemoryImpl>
|
||||
class create_open_func;
|
||||
|
||||
template<
|
||||
class CharType,
|
||||
class MemoryAlgorithm,
|
||||
template<class IndexConfig> class IndexType
|
||||
>
|
||||
struct segment_manager_type
|
||||
{
|
||||
typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
|
||||
};
|
||||
|
||||
//!This class is designed to be a base class to classes that manage
|
||||
//!creation of objects in a fixed size memory buffer. Apart
|
||||
//!from allocating raw memory, the user can construct named objects. To
|
||||
//!achieve this, this class uses the reserved space provided by the allocation
|
||||
//!algorithm to place a named_allocator_algo, who takes care of name mappings.
|
||||
//!The class can be customized with the char type used for object names
|
||||
//!and the memory allocation algorithm to be used.*/
|
||||
template < class CharType
|
||||
, class MemoryAlgorithm
|
||||
, template<class IndexConfig> class IndexType
|
||||
, std::size_t Offset = 0
|
||||
>
|
||||
class basic_managed_memory_impl
|
||||
{
|
||||
//Non-copyable
|
||||
basic_managed_memory_impl(const basic_managed_memory_impl &);
|
||||
basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
|
||||
|
||||
template<class BasicManagedMemoryImpl>
|
||||
friend class create_open_func;
|
||||
|
||||
public:
|
||||
typedef typename segment_manager_type
|
||||
<CharType, MemoryAlgorithm, IndexType>::type segment_manager;
|
||||
typedef CharType char_type;
|
||||
typedef MemoryAlgorithm memory_algorithm;
|
||||
typedef typename MemoryAlgorithm::mutex_family mutex_family;
|
||||
typedef CharType char_t;
|
||||
typedef typename MemoryAlgorithm::size_type size_type;
|
||||
typedef typename MemoryAlgorithm::difference_type difference_type;
|
||||
typedef difference_type handle_t;
|
||||
typedef typename segment_manager::
|
||||
const_named_iterator const_named_iterator;
|
||||
typedef typename segment_manager::
|
||||
const_unique_iterator const_unique_iterator;
|
||||
|
||||
/// @cond
|
||||
|
||||
typedef typename
|
||||
segment_manager::char_ptr_holder_t char_ptr_holder_t;
|
||||
//Experimental. Don't use.
|
||||
|
||||
typedef typename segment_manager::multiallocation_chain multiallocation_chain;
|
||||
|
||||
/// @endcond
|
||||
|
||||
static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
|
||||
|
||||
private:
|
||||
typedef basic_managed_memory_impl
|
||||
<CharType, MemoryAlgorithm, IndexType, Offset> self_t;
|
||||
protected:
|
||||
template<class ManagedMemory>
|
||||
static bool grow(const char *filename, size_type extra_bytes)
|
||||
{
|
||||
typedef typename ManagedMemory::device_type device_type;
|
||||
//Increase file size
|
||||
try{
|
||||
offset_t old_size;
|
||||
{
|
||||
device_type f(open_or_create, filename, read_write);
|
||||
if(!f.get_size(old_size))
|
||||
return false;
|
||||
f.truncate(old_size + extra_bytes);
|
||||
}
|
||||
ManagedMemory managed_memory(open_only, filename);
|
||||
//Grow always works
|
||||
managed_memory.self_t::grow(extra_bytes);
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class ManagedMemory>
|
||||
static bool shrink_to_fit(const char *filename)
|
||||
{
|
||||
typedef typename ManagedMemory::device_type device_type;
|
||||
size_type new_size, old_size;
|
||||
try{
|
||||
ManagedMemory managed_memory(open_only, filename);
|
||||
old_size = managed_memory.get_size();
|
||||
managed_memory.self_t::shrink_to_fit();
|
||||
new_size = managed_memory.get_size();
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Decrease file size
|
||||
{
|
||||
device_type f(open_or_create, filename, read_write);
|
||||
f.truncate(new_size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//!Constructor. Allocates basic resources. Never throws.
|
||||
basic_managed_memory_impl()
|
||||
: mp_header(0){}
|
||||
|
||||
//!Destructor. Calls close. Never throws.
|
||||
~basic_managed_memory_impl()
|
||||
{ this->close_impl(); }
|
||||
|
||||
//!Places segment manager in the reserved space. This can throw.
|
||||
bool create_impl (void *addr, size_type size)
|
||||
{
|
||||
if(mp_header) return false;
|
||||
|
||||
//Check if there is enough space
|
||||
if(size < segment_manager::get_min_size())
|
||||
return false;
|
||||
|
||||
//This function should not throw. The index construction can
|
||||
//throw if constructor allocates memory. So we must catch it.
|
||||
BOOST_TRY{
|
||||
//Let's construct the allocator in memory
|
||||
mp_header = new(addr) segment_manager(size);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
return false;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return true;
|
||||
}
|
||||
|
||||
//!Connects to a segment manager in the reserved buffer. Never throws.
|
||||
bool open_impl (void *addr, size_type)
|
||||
{
|
||||
if(mp_header) return false;
|
||||
mp_header = static_cast<segment_manager*>(addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
//!Frees resources. Never throws.
|
||||
bool close_impl()
|
||||
{
|
||||
bool ret = mp_header != 0;
|
||||
mp_header = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
//!Frees resources and destroys common resources. Never throws.
|
||||
bool destroy_impl()
|
||||
{
|
||||
if(mp_header == 0)
|
||||
return false;
|
||||
mp_header->~segment_manager();
|
||||
this->close_impl();
|
||||
return true;
|
||||
}
|
||||
|
||||
//!
|
||||
void grow(size_type extra_bytes)
|
||||
{ mp_header->grow(extra_bytes); }
|
||||
|
||||
void shrink_to_fit()
|
||||
{ mp_header->shrink_to_fit(); }
|
||||
|
||||
public:
|
||||
|
||||
//!Returns segment manager. Never throws.
|
||||
segment_manager *get_segment_manager() const
|
||||
{ return mp_header; }
|
||||
|
||||
//!Returns the base address of the memory in this process. Never throws.
|
||||
void * get_address () const
|
||||
{ return reinterpret_cast<char*>(mp_header) - Offset; }
|
||||
|
||||
//!Returns the size of memory segment. Never throws.
|
||||
size_type get_size () const
|
||||
{ return mp_header->get_size() + Offset; }
|
||||
|
||||
//!Returns the number of free bytes of the memory
|
||||
//!segment
|
||||
size_type get_free_memory() const
|
||||
{ return mp_header->get_free_memory(); }
|
||||
|
||||
//!Returns the result of "all_memory_deallocated()" function
|
||||
//!of the used memory algorithm
|
||||
bool all_memory_deallocated()
|
||||
{ return mp_header->all_memory_deallocated(); }
|
||||
|
||||
//!Returns the result of "check_sanity()" function
|
||||
//!of the used memory algorithm
|
||||
bool check_sanity()
|
||||
{ return mp_header->check_sanity(); }
|
||||
|
||||
//!Writes to zero free memory (memory not yet allocated) of
|
||||
//!the memory algorithm
|
||||
void zero_free_memory()
|
||||
{ mp_header->zero_free_memory(); }
|
||||
|
||||
//!Transforms an absolute address into an offset from base address.
|
||||
//!The address must belong to the memory segment. Never throws.
|
||||
handle_t get_handle_from_address (const void *ptr) const
|
||||
{
|
||||
return (handle_t)(reinterpret_cast<const char*>(ptr) -
|
||||
reinterpret_cast<const char*>(this->get_address()));
|
||||
}
|
||||
|
||||
//!Returns true if the address belongs to the managed memory segment
|
||||
bool belongs_to_segment (const void *ptr) const
|
||||
{
|
||||
return ptr >= this->get_address() &&
|
||||
ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
|
||||
}
|
||||
|
||||
//!Transforms previously obtained offset into an absolute address in the
|
||||
//!process space of the current process. Never throws.*/
|
||||
void * get_address_from_handle (handle_t offset) const
|
||||
{ return reinterpret_cast<char*>(this->get_address()) + offset; }
|
||||
|
||||
//!Searches for nbytes of free memory in the segment, marks the
|
||||
//!memory as used and return the pointer to the memory. If no
|
||||
//!memory is available throws a boost::interprocess::bad_alloc exception
|
||||
void* allocate (size_type nbytes)
|
||||
{ return mp_header->allocate(nbytes); }
|
||||
|
||||
//!Searches for nbytes of free memory in the segment, marks the
|
||||
//!memory as used and return the pointer to the memory. If no memory
|
||||
//!is available returns 0. Never throws.
|
||||
void* allocate (size_type nbytes, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate(nbytes, nothrow); }
|
||||
|
||||
//!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
|
||||
//!must be power of two. If no memory
|
||||
//!is available returns 0. Never throws.
|
||||
void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate_aligned(nbytes, alignment, nothrow); }
|
||||
|
||||
template<class T>
|
||||
std::pair<T *, bool>
|
||||
allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
|
||||
size_type preferred_size,size_type &received_size,
|
||||
T *reuse_ptr = 0)
|
||||
{
|
||||
return mp_header->allocation_command
|
||||
(command, limit_size, preferred_size, received_size, reuse_ptr);
|
||||
}
|
||||
|
||||
//!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
|
||||
//!must be power of two. If no
|
||||
//!memory is available throws a boost::interprocess::bad_alloc exception
|
||||
void * allocate_aligned(size_type nbytes, size_type alignment)
|
||||
{ return mp_header->allocate_aligned(nbytes, alignment); }
|
||||
|
||||
/// @cond
|
||||
|
||||
//Experimental. Don't use.
|
||||
|
||||
//!Allocates n_elements of elem_size bytes.
|
||||
multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements)
|
||||
{ return mp_header->allocate_many(elem_bytes, num_elements); }
|
||||
|
||||
//!Allocates n_elements, each one of elem_sizes[i] bytes.
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements)
|
||||
{ return mp_header->allocate_many(elem_sizes, n_elements); }
|
||||
|
||||
//!Allocates n_elements of elem_size bytes.
|
||||
multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate_many(elem_bytes, num_elements, nothrow); }
|
||||
|
||||
//!Allocates n_elements, each one of elem_sizes[i] bytes.
|
||||
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, std::nothrow_t nothrow)
|
||||
{ return mp_header->allocate_many(elem_sizes, n_elements, nothrow); }
|
||||
|
||||
//!Allocates n_elements, each one of elem_sizes[i] bytes.
|
||||
void deallocate_many(multiallocation_chain chain)
|
||||
{ return mp_header->deallocate_many(boost::interprocess::move(chain)); }
|
||||
|
||||
/// @endcond
|
||||
|
||||
//!Marks previously allocated memory as free. Never throws.
|
||||
void deallocate (void *addr)
|
||||
{ if (mp_header) mp_header->deallocate(addr); }
|
||||
|
||||
//!Tries to find a previous named allocation address. Returns a memory
|
||||
//!buffer and the object count. If not found returned pointer is 0.
|
||||
//!Never throws.
|
||||
template <class T>
|
||||
std::pair<T*, size_type> find (char_ptr_holder_t name)
|
||||
{ return mp_header->template find<T>(name); }
|
||||
|
||||
//!Creates a named object or array in memory
|
||||
//!
|
||||
//!Allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
construct(char_ptr_holder_t name)
|
||||
{ return mp_header->template construct<T>(name); }
|
||||
|
||||
//!Finds or creates a named object or array in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
find_or_construct(char_ptr_holder_t name)
|
||||
{ return mp_header->template find_or_construct<T>(name); }
|
||||
|
||||
//!Creates a named object or array in memory
|
||||
//!
|
||||
//!Allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Returns 0 if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
construct(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template construct<T>(name, nothrow); }
|
||||
|
||||
//!Finds or creates a named object or array in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs a T object or an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. If an array is being constructed all objects are
|
||||
//!created using the same parameters given to this function.
|
||||
//!
|
||||
//!-> Returns 0 if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and if an
|
||||
//!array was being constructed, destructors of created objects are called
|
||||
//!before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_proxy<T>::type
|
||||
find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template find_or_construct<T>(name, nothrow); }
|
||||
|
||||
//!Creates a named array from iterators in memory
|
||||
//!
|
||||
//!Allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
construct_it(char_ptr_holder_t name)
|
||||
{ return mp_header->template construct_it<T>(name); }
|
||||
|
||||
//!Finds or creates a named array from iterators in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> Throws boost::interprocess::bad_alloc if there is no available memory
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
find_or_construct_it(char_ptr_holder_t name)
|
||||
{ return mp_header->template find_or_construct_it<T>(name); }
|
||||
|
||||
//!Creates a named array from iterators in memory
|
||||
//!
|
||||
//!Allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> If there is no available memory, returns 0.
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.*/
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template construct_it<T>(name, nothrow); }
|
||||
|
||||
//!Finds or creates a named array from iterators in memory
|
||||
//!
|
||||
//!Tries to find an object with the given name in memory. If
|
||||
//!found, returns the pointer to this pointer. If the object is not found,
|
||||
//!allocates and constructs an array of T in memory,
|
||||
//!associates this with the given name and returns a pointer to the
|
||||
//!created object. Each element in the array is created using the
|
||||
//!objects returned when dereferencing iterators as parameters
|
||||
//!and incrementing all iterators for each element.
|
||||
//!
|
||||
//!-> If the name was previously used, returns 0.
|
||||
//!
|
||||
//!-> If there is no available memory, returns 0.
|
||||
//!
|
||||
//!-> If T's constructor throws, the function throws that exception.
|
||||
//!
|
||||
//!Memory is freed automatically if T's constructor throws and
|
||||
//!destructors of created objects are called before freeing the memory.*/
|
||||
template <class T>
|
||||
typename segment_manager::template construct_iter_proxy<T>::type
|
||||
find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow)
|
||||
{ return mp_header->template find_or_construct_it<T>(name, nothrow); }
|
||||
|
||||
//!Calls a functor and guarantees that no new construction, search or
|
||||
//!destruction will be executed by any process while executing the object
|
||||
//!function call. If the functor throws, this function throws.
|
||||
template <class Func>
|
||||
void atomic_func(Func &f)
|
||||
{ mp_header->atomic_func(f); }
|
||||
|
||||
//!Tries to call a functor guaranteeing that no new construction, search or
|
||||
//!destruction will be executed by any process while executing the object
|
||||
//!function call. If the atomic function can't be immediatelly executed
|
||||
//!because the internal mutex is already locked, returns false.
|
||||
//!If the functor throws, this function throws.
|
||||
template <class Func>
|
||||
bool try_atomic_func(Func &f)
|
||||
{ return mp_header->try_atomic_func(f); }
|
||||
|
||||
//!Destroys a named memory object or array.
|
||||
//!
|
||||
//!Finds the object with the given name, calls its destructors,
|
||||
//!frees used memory and returns true.
|
||||
//!
|
||||
//!-> If the object is not found, it returns false.
|
||||
//!
|
||||
//!Exception Handling:
|
||||
//!
|
||||
//!When deleting a dynamically object or array, the Standard
|
||||
//!does not guarantee that dynamically allocated memory, will be released.
|
||||
//!Also, when deleting arrays, the Standard doesn't require calling
|
||||
//!destructors for the rest of the objects if for one of them the destructor
|
||||
//!terminated with an exception.
|
||||
//!
|
||||
//!Destroying an object:
|
||||
//!
|
||||
//!If the destructor throws, the memory will be freed and that exception
|
||||
//!will be thrown.
|
||||
//!
|
||||
//!Destroying an array:
|
||||
//!
|
||||
//!When destroying an array, if a destructor throws, the rest of
|
||||
//!destructors are called. If any of these throws, the exceptions are
|
||||
//!ignored. The name association will be erased, memory will be freed and
|
||||
//!the first exception will be thrown. This guarantees the unlocking of
|
||||
//!mutexes and other resources.
|
||||
//!
|
||||
//!For all theses reasons, classes with throwing destructors are not
|
||||
//!recommended.
|
||||
template <class T>
|
||||
bool destroy(const CharType *name)
|
||||
{ return mp_header->template destroy<T>(name); }
|
||||
|
||||
//!Destroys the unique instance of type T
|
||||
//!
|
||||
//!Calls the destructor, frees used memory and returns true.
|
||||
//!
|
||||
//!Exception Handling:
|
||||
//!
|
||||
//!When deleting a dynamically object, the Standard does not
|
||||
//!guarantee that dynamically allocated memory will be released.
|
||||
//!
|
||||
//!Destroying an object:
|
||||
//!
|
||||
//!If the destructor throws, the memory will be freed and that exception
|
||||
//!will be thrown.
|
||||
//!
|
||||
//!For all theses reasons, classes with throwing destructors are not
|
||||
//!recommended for memory.
|
||||
template <class T>
|
||||
bool destroy(const ipcdetail::unique_instance_t *const )
|
||||
{ return mp_header->template destroy<T>(unique_instance); }
|
||||
|
||||
//!Destroys the object (named, unique, or anonymous)
|
||||
//!
|
||||
//!Calls the destructor, frees used memory and returns true.
|
||||
//!
|
||||
//!Exception Handling:
|
||||
//!
|
||||
//!When deleting a dynamically object, the Standard does not
|
||||
//!guarantee that dynamically allocated memory will be released.
|
||||
//!
|
||||
//!Destroying an object:
|
||||
//!
|
||||
//!If the destructor throws, the memory will be freed and that exception
|
||||
//!will be thrown.
|
||||
//!
|
||||
//!For all theses reasons, classes with throwing destructors are not
|
||||
//!recommended for memory.
|
||||
template <class T>
|
||||
void destroy_ptr(const T *ptr)
|
||||
{ mp_header->template destroy_ptr<T>(ptr); }
|
||||
|
||||
//!Returns the name of an object created with construct/find_or_construct
|
||||
//!functions. Does not throw
|
||||
template<class T>
|
||||
static const char_type *get_instance_name(const T *ptr)
|
||||
{ return segment_manager::get_instance_name(ptr); }
|
||||
|
||||
//!Returns is the type an object created with construct/find_or_construct
|
||||
//!functions. Does not throw.
|
||||
template<class T>
|
||||
static instance_type get_instance_type(const T *ptr)
|
||||
{ return segment_manager::get_instance_type(ptr); }
|
||||
|
||||
//!Returns the length of an object created with construct/find_or_construct
|
||||
//!functions (1 if is a single element, >=1 if it's an array). Does not throw.
|
||||
template<class T>
|
||||
static size_type get_instance_length(const T *ptr)
|
||||
{ return segment_manager::get_instance_length(ptr); }
|
||||
|
||||
//!Preallocates needed index resources to optimize the
|
||||
//!creation of "num" named objects in the memory segment.
|
||||
//!Can throw boost::interprocess::bad_alloc if there is no enough memory.
|
||||
void reserve_named_objects(size_type num)
|
||||
{ mp_header->reserve_named_objects(num); }
|
||||
|
||||
//!Preallocates needed index resources to optimize the
|
||||
//!creation of "num" unique objects in the memory segment.
|
||||
//!Can throw boost::interprocess::bad_alloc if there is no enough memory.
|
||||
void reserve_unique_objects(size_type num)
|
||||
{ mp_header->reserve_unique_objects(num); }
|
||||
|
||||
//!Calls shrink_to_fit in both named and unique object indexes
|
||||
//to try to free unused memory from those indexes.
|
||||
void shrink_to_fit_indexes()
|
||||
{ mp_header->shrink_to_fit_indexes(); }
|
||||
|
||||
//!Returns the number of named objects stored
|
||||
//!in the managed segment.
|
||||
size_type get_num_named_objects()
|
||||
{ return mp_header->get_num_named_objects(); }
|
||||
|
||||
//!Returns the number of unique objects stored
|
||||
//!in the managed segment.
|
||||
size_type get_num_unique_objects()
|
||||
{ return mp_header->get_num_unique_objects(); }
|
||||
|
||||
//!Returns a constant iterator to the index storing the
|
||||
//!named allocations. NOT thread-safe. Never throws.
|
||||
const_named_iterator named_begin() const
|
||||
{ return mp_header->named_begin(); }
|
||||
|
||||
//!Returns a constant iterator to the end of the index
|
||||
//!storing the named allocations. NOT thread-safe. Never throws.
|
||||
const_named_iterator named_end() const
|
||||
{ return mp_header->named_end(); }
|
||||
|
||||
//!Returns a constant iterator to the index storing the
|
||||
//!unique allocations. NOT thread-safe. Never throws.
|
||||
const_unique_iterator unique_begin() const
|
||||
{ return mp_header->unique_begin(); }
|
||||
|
||||
//!Returns a constant iterator to the end of the index
|
||||
//!storing the unique allocations. NOT thread-safe. Never throws.
|
||||
const_unique_iterator unique_end() const
|
||||
{ return mp_header->unique_end(); }
|
||||
|
||||
//!This is the default allocator to allocate types T
|
||||
//!from this managed segment
|
||||
template<class T>
|
||||
struct allocator
|
||||
{
|
||||
typedef typename segment_manager::template allocator<T>::type type;
|
||||
};
|
||||
|
||||
//!Returns an instance of the default allocator for type T
|
||||
//!initialized that allocates memory from this segment manager.
|
||||
template<class T>
|
||||
typename allocator<T>::type
|
||||
get_allocator()
|
||||
{ return mp_header->template get_allocator<T>(); }
|
||||
|
||||
//!This is the default deleter to delete types T
|
||||
//!from this managed segment.
|
||||
template<class T>
|
||||
struct deleter
|
||||
{
|
||||
typedef typename segment_manager::template deleter<T>::type type;
|
||||
};
|
||||
|
||||
//!Returns an instance of the default allocator for type T
|
||||
//!initialized that allocates memory from this segment manager.
|
||||
template<class T>
|
||||
typename deleter<T>::type
|
||||
get_deleter()
|
||||
{ return mp_header->template get_deleter<T>(); }
|
||||
|
||||
/// @cond
|
||||
//!Tries to find a previous named allocation address. Returns a memory
|
||||
//!buffer and the object count. If not found returned pointer is 0.
|
||||
//!Never throws.
|
||||
template <class T>
|
||||
std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
|
||||
{ return mp_header->template find_no_lock<T>(name); }
|
||||
/// @endcond
|
||||
|
||||
protected:
|
||||
//!Swaps the segment manager's managed by this managed memory segment.
|
||||
//!NOT thread-safe. Never throws.
|
||||
void swap(basic_managed_memory_impl &other)
|
||||
{ std::swap(mp_header, other.mp_header); }
|
||||
|
||||
private:
|
||||
segment_manager *mp_header;
|
||||
};
|
||||
|
||||
template<class BasicManagedMemoryImpl>
|
||||
class create_open_func
|
||||
{
|
||||
public:
|
||||
create_open_func(BasicManagedMemoryImpl * const frontend, ipcdetail::create_enum_t type)
|
||||
: m_frontend(frontend), m_type(type){}
|
||||
|
||||
bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const
|
||||
{
|
||||
if(((m_type == ipcdetail::DoOpen) && created) ||
|
||||
((m_type == ipcdetail::DoCreate) && !created))
|
||||
return false;
|
||||
|
||||
if(created)
|
||||
return m_frontend->create_impl(addr, size);
|
||||
else
|
||||
return m_frontend->open_impl (addr, size);
|
||||
}
|
||||
|
||||
private:
|
||||
BasicManagedMemoryImpl *m_frontend;
|
||||
ipcdetail::create_enum_t m_type;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
|
||||
|
||||
402
test/external/boost/interprocess/detail/managed_multi_shared_memory.hpp
vendored
Normal file
402
test/external/boost/interprocess/detail/managed_multi_shared_memory.hpp
vendored
Normal file
@@ -0,0 +1,402 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
|
||||
#define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/detail/managed_memory_impl.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/interprocess/detail/multi_segment_services.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/containers/list.hpp>//list
|
||||
#include <boost/interprocess/mapped_region.hpp> //mapped_region
|
||||
#include <boost/interprocess/shared_memory_object.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/interprocess/detail/managed_open_or_create_impl.hpp> //managed_open_or_create_impl
|
||||
#include <new>
|
||||
#include <boost/interprocess/containers/string.hpp>
|
||||
#include <boost/interprocess/streams/vectorstream.hpp>
|
||||
#include <memory>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a named shared memory object allocation user class.
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
//TODO: We must somehow obtain the permissions of the first segment
|
||||
//to apply them to subsequent segments
|
||||
//-Use GetSecurityInfo?
|
||||
//-Change everything to use only a shared memory object expanded via truncate()?
|
||||
|
||||
//!A basic shared memory named object creation class. Initializes the
|
||||
//!shared memory segment. Inherits all basic functionality from
|
||||
//!basic_managed_memory_impl<CharType, MemoryAlgorithm, IndexType>
|
||||
template
|
||||
<
|
||||
class CharType,
|
||||
class MemoryAlgorithm,
|
||||
template<class IndexConfig> class IndexType
|
||||
>
|
||||
class basic_managed_multi_shared_memory
|
||||
: public ipcdetail::basic_managed_memory_impl
|
||||
<CharType, MemoryAlgorithm, IndexType>
|
||||
{
|
||||
|
||||
typedef basic_managed_multi_shared_memory
|
||||
<CharType, MemoryAlgorithm, IndexType> self_t;
|
||||
typedef ipcdetail::basic_managed_memory_impl
|
||||
<CharType, MemoryAlgorithm, IndexType> base_t;
|
||||
|
||||
typedef typename MemoryAlgorithm::void_pointer void_pointer;
|
||||
typedef typename ipcdetail::
|
||||
managed_open_or_create_impl<shared_memory_object> managed_impl;
|
||||
typedef typename void_pointer::segment_group_id segment_group_id;
|
||||
typedef typename base_t::size_type size_type;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Some internal helper structs/functors
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//!This class defines an operator() that creates a shared memory
|
||||
//!of the requested size. The rest of the parameters are
|
||||
//!passed in the constructor. The class a template parameter
|
||||
//!to be used with create_from_file/create_from_istream functions
|
||||
//!of basic_named_object classes
|
||||
|
||||
// class segment_creator
|
||||
// {
|
||||
// public:
|
||||
// segment_creator(shared_memory &shmem,
|
||||
// const char *mem_name,
|
||||
// const void *addr)
|
||||
// : m_shmem(shmem), m_mem_name(mem_name), m_addr(addr){}
|
||||
//
|
||||
// void *operator()(size_type size)
|
||||
// {
|
||||
// if(!m_shmem.create(m_mem_name, size, m_addr))
|
||||
// return 0;
|
||||
// return m_shmem.get_address();
|
||||
// }
|
||||
// private:
|
||||
// shared_memory &m_shmem;
|
||||
// const char *m_mem_name;
|
||||
// const void *m_addr;
|
||||
// };
|
||||
|
||||
class group_services
|
||||
: public multi_segment_services
|
||||
{
|
||||
public:
|
||||
typedef std::pair<void *, size_type> result_type;
|
||||
typedef basic_managed_multi_shared_memory frontend_t;
|
||||
typedef typename
|
||||
basic_managed_multi_shared_memory::void_pointer void_pointer;
|
||||
typedef typename void_pointer::segment_group_id segment_group_id;
|
||||
group_services(frontend_t *const frontend)
|
||||
: mp_frontend(frontend), m_group(0), m_min_segment_size(0){}
|
||||
|
||||
virtual std::pair<void *, size_type> create_new_segment(size_type alloc_size)
|
||||
{
|
||||
//We should allocate an extra byte so that the
|
||||
//[base_addr + alloc_size] byte belongs to this segment
|
||||
alloc_size += 1;
|
||||
|
||||
//If requested size is less than minimum, update that
|
||||
alloc_size = (m_min_segment_size > alloc_size) ?
|
||||
m_min_segment_size : alloc_size;
|
||||
if(mp_frontend->priv_new_segment(create_open_func::DoCreate,
|
||||
alloc_size, 0, permissions())){
|
||||
shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin();
|
||||
return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1);
|
||||
}
|
||||
return result_type(static_cast<void *>(0), 0);
|
||||
}
|
||||
|
||||
virtual bool update_segments ()
|
||||
{ return true; }
|
||||
|
||||
virtual ~group_services(){}
|
||||
|
||||
void set_group(segment_group_id group)
|
||||
{ m_group = group; }
|
||||
|
||||
segment_group_id get_group() const
|
||||
{ return m_group; }
|
||||
|
||||
void set_min_segment_size(size_type min_segment_size)
|
||||
{ m_min_segment_size = min_segment_size; }
|
||||
|
||||
size_type get_min_segment_size() const
|
||||
{ return m_min_segment_size; }
|
||||
|
||||
private:
|
||||
|
||||
frontend_t * const mp_frontend;
|
||||
segment_group_id m_group;
|
||||
size_type m_min_segment_size;
|
||||
};
|
||||
|
||||
//!Functor to execute atomically when opening or creating a shared memory
|
||||
//!segment.
|
||||
struct create_open_func
|
||||
{
|
||||
enum type_t { DoCreate, DoOpen, DoOpenOrCreate };
|
||||
typedef typename
|
||||
basic_managed_multi_shared_memory::void_pointer void_pointer;
|
||||
|
||||
create_open_func(self_t * const frontend,
|
||||
type_t type, size_type segment_number)
|
||||
: mp_frontend(frontend), m_type(type), m_segment_number(segment_number){}
|
||||
|
||||
bool operator()(void *addr, size_type size, bool created) const
|
||||
{
|
||||
if(((m_type == DoOpen) && created) ||
|
||||
((m_type == DoCreate) && !created))
|
||||
return false;
|
||||
segment_group_id group = mp_frontend->m_group_services.get_group();
|
||||
bool mapped = false;
|
||||
bool impl_done = false;
|
||||
|
||||
//Associate this newly created segment as the
|
||||
//segment id = 0 of this group
|
||||
void_pointer::insert_mapping
|
||||
( group
|
||||
, static_cast<char*>(addr) - managed_impl::ManagedOpenOrCreateUserOffset
|
||||
, size + managed_impl::ManagedOpenOrCreateUserOffset);
|
||||
//Check if this is the master segment
|
||||
if(!m_segment_number){
|
||||
//Create or open the Interprocess machinery
|
||||
if((impl_done = created ?
|
||||
mp_frontend->create_impl(addr, size) : mp_frontend->open_impl(addr, size))){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
|
||||
//This is the cleanup part
|
||||
//---------------
|
||||
if(impl_done){
|
||||
mp_frontend->close_impl();
|
||||
}
|
||||
if(mapped){
|
||||
bool ret = void_pointer::erase_last_mapping(group);
|
||||
BOOST_ASSERT(ret);(void)ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
self_t * const mp_frontend;
|
||||
type_t m_type;
|
||||
size_type m_segment_number;
|
||||
};
|
||||
|
||||
//!Functor to execute atomically when closing a shared memory segment.
|
||||
struct close_func
|
||||
{
|
||||
typedef typename
|
||||
basic_managed_multi_shared_memory::void_pointer void_pointer;
|
||||
|
||||
close_func(self_t * const frontend)
|
||||
: mp_frontend(frontend){}
|
||||
|
||||
void operator()(const mapped_region ®ion, bool last) const
|
||||
{
|
||||
if(last) mp_frontend->destroy_impl();
|
||||
else mp_frontend->close_impl();
|
||||
}
|
||||
self_t * const mp_frontend;
|
||||
};
|
||||
|
||||
//Friend declarations
|
||||
friend struct basic_managed_multi_shared_memory::create_open_func;
|
||||
friend struct basic_managed_multi_shared_memory::close_func;
|
||||
friend class basic_managed_multi_shared_memory::group_services;
|
||||
|
||||
typedef list<managed_impl> shmem_list_t;
|
||||
|
||||
basic_managed_multi_shared_memory *get_this_pointer()
|
||||
{ return this; }
|
||||
|
||||
public:
|
||||
|
||||
basic_managed_multi_shared_memory(create_only_t,
|
||||
const char *name,
|
||||
size_type size,
|
||||
const permissions &perm = permissions())
|
||||
: m_group_services(get_this_pointer())
|
||||
{
|
||||
priv_open_or_create(create_open_func::DoCreate,name, size, perm);
|
||||
}
|
||||
|
||||
basic_managed_multi_shared_memory(open_or_create_t,
|
||||
const char *name,
|
||||
size_type size,
|
||||
const permissions &perm = permissions())
|
||||
: m_group_services(get_this_pointer())
|
||||
{
|
||||
priv_open_or_create(create_open_func::DoOpenOrCreate, name, size, perm);
|
||||
}
|
||||
|
||||
basic_managed_multi_shared_memory(open_only_t, const char *name)
|
||||
: m_group_services(get_this_pointer())
|
||||
{
|
||||
priv_open_or_create(create_open_func::DoOpen, name, 0, permissions());
|
||||
}
|
||||
|
||||
~basic_managed_multi_shared_memory()
|
||||
{ this->priv_close(); }
|
||||
|
||||
private:
|
||||
bool priv_open_or_create(typename create_open_func::type_t type,
|
||||
const char *name,
|
||||
size_type size,
|
||||
const permissions &perm)
|
||||
{
|
||||
if(!m_shmem_list.empty())
|
||||
return false;
|
||||
typename void_pointer::segment_group_id group = 0;
|
||||
BOOST_TRY{
|
||||
m_root_name = name;
|
||||
//Insert multi segment services and get a group identifier
|
||||
group = void_pointer::new_segment_group(&m_group_services);
|
||||
size = void_pointer::round_size(size);
|
||||
m_group_services.set_group(group);
|
||||
m_group_services.set_min_segment_size(size);
|
||||
|
||||
if(group){
|
||||
if(this->priv_new_segment(type, size, 0, perm)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(const std::bad_alloc&){
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
if(group){
|
||||
void_pointer::delete_group(group);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool priv_new_segment(typename create_open_func::type_t type,
|
||||
size_type size,
|
||||
const void *addr,
|
||||
const permissions &perm)
|
||||
{
|
||||
BOOST_TRY{
|
||||
//Get the number of groups of this multi_segment group
|
||||
size_type segment_id = m_shmem_list.size();
|
||||
//Format the name of the shared memory: append segment number.
|
||||
boost::interprocess::basic_ovectorstream<boost::interprocess::string> formatter;
|
||||
//Pre-reserve string size
|
||||
size_type str_size = m_root_name.length()+10;
|
||||
if(formatter.vector().size() < str_size){
|
||||
//This can throw.
|
||||
formatter.reserve(str_size);
|
||||
}
|
||||
//Format segment's name
|
||||
formatter << m_root_name
|
||||
<< static_cast<unsigned int>(segment_id) << std::ends;
|
||||
//This functor will be executed when constructing
|
||||
create_open_func func(this, type, segment_id);
|
||||
const char *name = formatter.vector().c_str();
|
||||
//This can throw.
|
||||
managed_impl mshm;
|
||||
|
||||
switch(type){
|
||||
case create_open_func::DoCreate:
|
||||
{
|
||||
managed_impl shm(create_only, name, size, read_write, addr, func, perm);
|
||||
mshm = boost::interprocess::move(shm);
|
||||
}
|
||||
break;
|
||||
|
||||
case create_open_func::DoOpen:
|
||||
{
|
||||
managed_impl shm(open_only, name,read_write, addr, func);
|
||||
mshm = boost::interprocess::move(shm);
|
||||
}
|
||||
break;
|
||||
|
||||
case create_open_func::DoOpenOrCreate:
|
||||
{
|
||||
managed_impl shm(open_or_create, name, size, read_write, addr, func, perm);
|
||||
mshm = boost::interprocess::move(shm);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
//This can throw.
|
||||
m_shmem_list.push_back(boost::interprocess::move(mshm));
|
||||
return true;
|
||||
}
|
||||
BOOST_CATCH(const std::bad_alloc&){
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return false;
|
||||
}
|
||||
|
||||
//!Frees resources. Never throws.
|
||||
void priv_close()
|
||||
{
|
||||
if(!m_shmem_list.empty()){
|
||||
bool ret;
|
||||
//Obtain group identifier
|
||||
segment_group_id group = m_group_services.get_group();
|
||||
//Erase main segment and its resources
|
||||
shmem_list_t::iterator itbeg = m_shmem_list.begin(),
|
||||
itend = m_shmem_list.end(),
|
||||
it = itbeg;
|
||||
//(*itbeg)->close_with_func(close_func(this));
|
||||
//Delete group. All mappings are erased too.
|
||||
ret = void_pointer::delete_group(group);
|
||||
BOOST_ASSERT(ret);
|
||||
m_shmem_list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
shmem_list_t m_shmem_list;
|
||||
group_services m_group_services;
|
||||
std::string m_root_name;
|
||||
};
|
||||
|
||||
typedef basic_managed_multi_shared_memory
|
||||
< char
|
||||
, rbtree_best_fit<mutex_family, intersegment_ptr<void> >
|
||||
, iset_index>
|
||||
managed_multi_shared_memory;
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP
|
||||
|
||||
473
test/external/boost/interprocess/detail/managed_open_or_create_impl.hpp
vendored
Normal file
473
test/external/boost/interprocess/detail/managed_open_or_create_impl.hpp
vendored
Normal file
@@ -0,0 +1,473 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
|
||||
#define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/os_thread_functions.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/detail/interprocess_tester.hpp>
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
/// @cond
|
||||
namespace ipcdetail{ class interprocess_tester; }
|
||||
|
||||
|
||||
template<class DeviceAbstraction>
|
||||
struct managed_open_or_create_impl_device_id_t
|
||||
{
|
||||
typedef const char *type;
|
||||
};
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
|
||||
class xsi_shared_memory_file_wrapper;
|
||||
class xsi_key;
|
||||
|
||||
template<>
|
||||
struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper>
|
||||
{
|
||||
typedef xsi_key type;
|
||||
};
|
||||
|
||||
#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
|
||||
/// @endcond
|
||||
|
||||
namespace ipcdetail {
|
||||
|
||||
|
||||
template <bool StoreDevice, class DeviceAbstraction>
|
||||
class managed_open_or_create_impl_device_holder
|
||||
{
|
||||
public:
|
||||
DeviceAbstraction &get_device()
|
||||
{ static DeviceAbstraction dev; return dev; }
|
||||
|
||||
const DeviceAbstraction &get_device() const
|
||||
{ static DeviceAbstraction dev; return dev; }
|
||||
};
|
||||
|
||||
template <class DeviceAbstraction>
|
||||
class managed_open_or_create_impl_device_holder<true, DeviceAbstraction>
|
||||
{
|
||||
public:
|
||||
DeviceAbstraction &get_device()
|
||||
{ return dev; }
|
||||
|
||||
const DeviceAbstraction &get_device() const
|
||||
{ return dev; }
|
||||
|
||||
private:
|
||||
DeviceAbstraction dev;
|
||||
};
|
||||
|
||||
template<class DeviceAbstraction, bool FileBased = true, bool StoreDevice = true>
|
||||
class managed_open_or_create_impl
|
||||
: public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction>
|
||||
{
|
||||
//Non-copyable
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl)
|
||||
|
||||
typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t;
|
||||
typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> DevHolder;
|
||||
enum
|
||||
{
|
||||
UninitializedSegment,
|
||||
InitializingSegment,
|
||||
InitializedSegment,
|
||||
CorruptedSegment
|
||||
};
|
||||
|
||||
public:
|
||||
static const std::size_t
|
||||
ManagedOpenOrCreateUserOffset =
|
||||
ipcdetail::ct_rounded_size
|
||||
< sizeof(boost::uint32_t)
|
||||
, ::boost::alignment_of< ::boost::detail::max_align >::value >::value;
|
||||
|
||||
managed_open_or_create_impl()
|
||||
{}
|
||||
|
||||
managed_open_or_create_impl(create_only_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
( ipcdetail::DoCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
managed_open_or_create_impl(open_only_t,
|
||||
const device_id_t & id,
|
||||
mode_t mode,
|
||||
const void *addr)
|
||||
{
|
||||
priv_open_or_create
|
||||
( ipcdetail::DoOpen
|
||||
, id
|
||||
, 0
|
||||
, mode
|
||||
, addr
|
||||
, permissions()
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
|
||||
managed_open_or_create_impl(open_or_create_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
( ipcdetail::DoOpenOrCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, null_mapped_region_function());
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(create_only_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
(ipcdetail::DoCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(open_only_t,
|
||||
const device_id_t & id,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
priv_open_or_create
|
||||
( ipcdetail::DoOpen
|
||||
, id
|
||||
, 0
|
||||
, mode
|
||||
, addr
|
||||
, permissions()
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
managed_open_or_create_impl(open_or_create_t,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func,
|
||||
const permissions &perm)
|
||||
{
|
||||
priv_open_or_create
|
||||
( ipcdetail::DoOpenOrCreate
|
||||
, id
|
||||
, size
|
||||
, mode
|
||||
, addr
|
||||
, perm
|
||||
, construct_func);
|
||||
}
|
||||
|
||||
managed_open_or_create_impl(BOOST_RV_REF(managed_open_or_create_impl) moved)
|
||||
{ this->swap(moved); }
|
||||
|
||||
managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved)
|
||||
{
|
||||
managed_open_or_create_impl tmp(boost::interprocess::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~managed_open_or_create_impl()
|
||||
{}
|
||||
|
||||
std::size_t get_user_size() const
|
||||
{ return m_mapped_region.get_size() - ManagedOpenOrCreateUserOffset; }
|
||||
|
||||
void *get_user_address() const
|
||||
{ return static_cast<char*>(m_mapped_region.get_address()) + ManagedOpenOrCreateUserOffset; }
|
||||
|
||||
std::size_t get_real_size() const
|
||||
{ return m_mapped_region.get_size(); }
|
||||
|
||||
void *get_real_address() const
|
||||
{ return m_mapped_region.get_address(); }
|
||||
|
||||
void swap(managed_open_or_create_impl &other)
|
||||
{
|
||||
this->m_mapped_region.swap(other.m_mapped_region);
|
||||
}
|
||||
|
||||
bool flush()
|
||||
{ return m_mapped_region.flush(); }
|
||||
|
||||
const mapped_region &get_mapped_region() const
|
||||
{ return m_mapped_region; }
|
||||
|
||||
|
||||
DeviceAbstraction &get_device()
|
||||
{ return this->DevHolder::get_device(); }
|
||||
|
||||
const DeviceAbstraction &get_device() const
|
||||
{ return this->DevHolder::get_device(); }
|
||||
|
||||
private:
|
||||
|
||||
//These are templatized to allow explicit instantiations
|
||||
template<bool dummy>
|
||||
static void truncate_device(DeviceAbstraction &, offset_t, ipcdetail::false_)
|
||||
{} //Empty
|
||||
|
||||
template<bool dummy>
|
||||
static void truncate_device(DeviceAbstraction &dev, offset_t size, ipcdetail::true_)
|
||||
{ dev.truncate(size); }
|
||||
|
||||
|
||||
template<bool dummy>
|
||||
static bool check_offset_t_size(std::size_t , ipcdetail::false_)
|
||||
{ return true; } //Empty
|
||||
|
||||
template<bool dummy>
|
||||
static bool check_offset_t_size(std::size_t size, ipcdetail::true_)
|
||||
{ return size == std::size_t(offset_t(size)); }
|
||||
|
||||
//These are templatized to allow explicit instantiations
|
||||
template<bool dummy>
|
||||
static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t size, const permissions &perm, ipcdetail::false_)
|
||||
{
|
||||
DeviceAbstraction tmp(create_only, id, read_write, size, perm);
|
||||
tmp.swap(dev);
|
||||
}
|
||||
|
||||
template<bool dummy>
|
||||
static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t, const permissions &perm, ipcdetail::true_)
|
||||
{
|
||||
DeviceAbstraction tmp(create_only, id, read_write, perm);
|
||||
tmp.swap(dev);
|
||||
}
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
void priv_open_or_create
|
||||
(ipcdetail::create_enum_t type,
|
||||
const device_id_t & id,
|
||||
std::size_t size,
|
||||
mode_t mode, const void *addr,
|
||||
const permissions &perm,
|
||||
ConstructFunc construct_func)
|
||||
{
|
||||
typedef ipcdetail::bool_<FileBased> file_like_t;
|
||||
(void)mode;
|
||||
error_info err;
|
||||
bool created = false;
|
||||
bool ronly = false;
|
||||
bool cow = false;
|
||||
DeviceAbstraction dev;
|
||||
|
||||
if(type != ipcdetail::DoOpen && size < ManagedOpenOrCreateUserOffset){
|
||||
throw interprocess_exception(error_info(size_error));
|
||||
}
|
||||
//Check size can be represented by offset_t (used by truncate)
|
||||
if(type != ipcdetail::DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){
|
||||
throw interprocess_exception(error_info(size_error));
|
||||
}
|
||||
if(type == ipcdetail::DoOpen && mode == read_write){
|
||||
DeviceAbstraction tmp(open_only, id, read_write);
|
||||
tmp.swap(dev);
|
||||
created = false;
|
||||
}
|
||||
else if(type == ipcdetail::DoOpen && mode == read_only){
|
||||
DeviceAbstraction tmp(open_only, id, read_only);
|
||||
tmp.swap(dev);
|
||||
created = false;
|
||||
ronly = true;
|
||||
}
|
||||
else if(type == ipcdetail::DoOpen && mode == copy_on_write){
|
||||
DeviceAbstraction tmp(open_only, id, read_only);
|
||||
tmp.swap(dev);
|
||||
created = false;
|
||||
cow = true;
|
||||
}
|
||||
else if(type == ipcdetail::DoCreate){
|
||||
create_device<FileBased>(dev, id, size, perm, file_like_t());
|
||||
created = true;
|
||||
}
|
||||
else if(type == ipcdetail::DoOpenOrCreate){
|
||||
//This loop is very ugly, but brute force is sometimes better
|
||||
//than diplomacy. If someone knows how to open or create a
|
||||
//file and know if we have really created it or just open it
|
||||
//drop me a e-mail!
|
||||
bool completed = false;
|
||||
while(!completed){
|
||||
try{
|
||||
create_device<FileBased>(dev, id, size, perm, file_like_t());
|
||||
created = true;
|
||||
completed = true;
|
||||
}
|
||||
catch(interprocess_exception &ex){
|
||||
if(ex.get_error_code() != already_exists_error){
|
||||
throw;
|
||||
}
|
||||
else{
|
||||
try{
|
||||
DeviceAbstraction tmp(open_only, id, read_write);
|
||||
dev.swap(tmp);
|
||||
created = false;
|
||||
completed = true;
|
||||
}
|
||||
catch(interprocess_exception &ex){
|
||||
if(ex.get_error_code() != not_found_error){
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ipcdetail::thread_yield();
|
||||
}
|
||||
}
|
||||
|
||||
if(created){
|
||||
try{
|
||||
//If this throws, we are lost
|
||||
truncate_device<FileBased>(dev, size, file_like_t());
|
||||
|
||||
//If the following throws, we will truncate the file to 1
|
||||
mapped_region region(dev, read_write, 0, 0, addr);
|
||||
boost::uint32_t *patomic_word = 0; //avoid gcc warning
|
||||
patomic_word = static_cast<boost::uint32_t*>(region.get_address());
|
||||
boost::uint32_t previous = ipcdetail::atomic_cas32(patomic_word, InitializingSegment, UninitializedSegment);
|
||||
|
||||
if(previous == UninitializedSegment){
|
||||
try{
|
||||
construct_func(static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset, size - ManagedOpenOrCreateUserOffset, true);
|
||||
//All ok, just move resources to the external mapped region
|
||||
m_mapped_region.swap(region);
|
||||
}
|
||||
catch(...){
|
||||
ipcdetail::atomic_write32(patomic_word, CorruptedSegment);
|
||||
throw;
|
||||
}
|
||||
ipcdetail::atomic_write32(patomic_word, InitializedSegment);
|
||||
}
|
||||
else if(previous == InitializingSegment || previous == InitializedSegment){
|
||||
throw interprocess_exception(error_info(already_exists_error));
|
||||
}
|
||||
else{
|
||||
throw interprocess_exception(error_info(corrupted_error));
|
||||
}
|
||||
}
|
||||
catch(...){
|
||||
try{
|
||||
truncate_device<FileBased>(dev, 1u, file_like_t());
|
||||
}
|
||||
catch(...){
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(FileBased){
|
||||
offset_t filesize = 0;
|
||||
while(filesize == 0){
|
||||
if(!ipcdetail::get_file_size(ipcdetail::file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){
|
||||
throw interprocess_exception(error_info(system_error_code()));
|
||||
}
|
||||
ipcdetail::thread_yield();
|
||||
}
|
||||
if(filesize == 1){
|
||||
throw interprocess_exception(error_info(corrupted_error));
|
||||
}
|
||||
}
|
||||
|
||||
mapped_region region(dev, ronly ? read_only : (cow ? copy_on_write : read_write), 0, 0, addr);
|
||||
|
||||
boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address());
|
||||
boost::uint32_t value = ipcdetail::atomic_read32(patomic_word);
|
||||
|
||||
while(value == InitializingSegment || value == UninitializedSegment){
|
||||
ipcdetail::thread_yield();
|
||||
value = ipcdetail::atomic_read32(patomic_word);
|
||||
}
|
||||
|
||||
if(value != InitializedSegment)
|
||||
throw interprocess_exception(error_info(corrupted_error));
|
||||
|
||||
construct_func( static_cast<char*>(region.get_address()) + ManagedOpenOrCreateUserOffset
|
||||
, region.get_size() - ManagedOpenOrCreateUserOffset
|
||||
, false);
|
||||
//All ok, just move resources to the external mapped region
|
||||
m_mapped_region.swap(region);
|
||||
}
|
||||
if(StoreDevice){
|
||||
this->DevHolder::get_device() = boost::interprocess::move(dev);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ipcdetail::interprocess_tester;
|
||||
void dont_close_on_destruction()
|
||||
{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_mapped_region); }
|
||||
|
||||
mapped_region m_mapped_region;
|
||||
};
|
||||
|
||||
template<class DeviceAbstraction>
|
||||
inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x
|
||||
,managed_open_or_create_impl<DeviceAbstraction> &y)
|
||||
{ x.swap(y); }
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL
|
||||
110
test/external/boost/interprocess/detail/math_functions.hpp
vendored
Normal file
110
test/external/boost/interprocess/detail/math_functions.hpp
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Stephen Cleary 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2007-2009.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// This file is a slightly modified file from Boost.Pool
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP
|
||||
|
||||
#include <climits>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
// Greatest common divisor and least common multiple
|
||||
|
||||
//
|
||||
// gcd is an algorithm that calculates the greatest common divisor of two
|
||||
// integers, using Euclid's algorithm.
|
||||
//
|
||||
// Pre: A > 0 && B > 0
|
||||
// Recommended: A > B
|
||||
template <typename Integer>
|
||||
inline Integer gcd(Integer A, Integer B)
|
||||
{
|
||||
do
|
||||
{
|
||||
const Integer tmp(B);
|
||||
B = A % B;
|
||||
A = tmp;
|
||||
} while (B != 0);
|
||||
|
||||
return A;
|
||||
}
|
||||
|
||||
//
|
||||
// lcm is an algorithm that calculates the least common multiple of two
|
||||
// integers.
|
||||
//
|
||||
// Pre: A > 0 && B > 0
|
||||
// Recommended: A > B
|
||||
template <typename Integer>
|
||||
inline Integer lcm(const Integer & A, const Integer & B)
|
||||
{
|
||||
Integer ret = A;
|
||||
ret /= gcd(A, B);
|
||||
ret *= B;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
inline Integer log2_ceil(const Integer & A)
|
||||
{
|
||||
Integer i = 0;
|
||||
Integer power_of_2 = 1;
|
||||
|
||||
while(power_of_2 < A){
|
||||
power_of_2 <<= 1;
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
template <typename Integer>
|
||||
inline Integer upper_power_of_2(const Integer & A)
|
||||
{
|
||||
Integer power_of_2 = 1;
|
||||
|
||||
while(power_of_2 < A){
|
||||
power_of_2 <<= 1;
|
||||
}
|
||||
return power_of_2;
|
||||
}
|
||||
|
||||
//This function uses binary search to discover the
|
||||
//highest set bit of the integer
|
||||
inline std::size_t floor_log2 (std::size_t x)
|
||||
{
|
||||
const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
|
||||
const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
|
||||
BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
|
||||
|
||||
std::size_t n = x;
|
||||
std::size_t log2 = 0;
|
||||
|
||||
for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
|
||||
std::size_t tmp = n >> shift;
|
||||
if (tmp)
|
||||
log2 += shift, n = tmp;
|
||||
}
|
||||
|
||||
return log2;
|
||||
}
|
||||
|
||||
} // namespace ipcdetail
|
||||
} // namespace interprocess
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
40
test/external/boost/interprocess/detail/min_max.hpp
vendored
Normal file
40
test/external/boost/interprocess/detail/min_max.hpp
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
template<class T>
|
||||
const T &max_value(const T &a, const T &b)
|
||||
{ return a > b ? a : b; }
|
||||
|
||||
template<class T>
|
||||
const T &min_value(const T &a, const T &b)
|
||||
{ return a < b ? a : b; }
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP
|
||||
|
||||
28
test/external/boost/interprocess/detail/move.hpp
vendored
Normal file
28
test/external/boost/interprocess/detail/move.hpp
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2010-2011.
|
||||
// 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/move for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! \file
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MOVE_HPP
|
||||
|
||||
#include <boost/move/move.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
using ::boost::move;
|
||||
using ::boost::forward;
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP
|
||||
152
test/external/boost/interprocess/detail/mpl.hpp
vendored
Normal file
152
test/external/boost/interprocess/detail/mpl.hpp
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_MPL_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template <class T, T val>
|
||||
struct integral_constant
|
||||
{
|
||||
static const T value = val;
|
||||
typedef integral_constant<T,val> type;
|
||||
};
|
||||
|
||||
template< bool C_ >
|
||||
struct bool_ : integral_constant<bool, C_>
|
||||
{
|
||||
static const bool value = C_;
|
||||
};
|
||||
|
||||
typedef bool_<true> true_;
|
||||
typedef bool_<false> false_;
|
||||
|
||||
typedef true_ true_type;
|
||||
typedef false_ false_type;
|
||||
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{
|
||||
char padding[8];
|
||||
};
|
||||
|
||||
template <bool B, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct enable_if_c<false, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
template <class Cond, class T = void>
|
||||
struct disable_if : public enable_if_c<!Cond::value, T> {};
|
||||
|
||||
template <class T, class U>
|
||||
class is_convertible
|
||||
{
|
||||
typedef char true_t;
|
||||
class false_t { char dummy[2]; };
|
||||
static true_t dispatch(U);
|
||||
static false_t dispatch(...);
|
||||
static T trigger();
|
||||
public:
|
||||
enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
|
||||
};
|
||||
|
||||
template<
|
||||
bool C
|
||||
, typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_c
|
||||
{
|
||||
typedef T1 type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T1
|
||||
, typename T2
|
||||
>
|
||||
struct if_c<false,T1,T2>
|
||||
{
|
||||
typedef T2 type;
|
||||
};
|
||||
|
||||
template<
|
||||
typename T1
|
||||
, typename T2
|
||||
, typename T3
|
||||
>
|
||||
struct if_
|
||||
{
|
||||
typedef typename if_c<0 != T1::value, T2, T3>::type type;
|
||||
};
|
||||
|
||||
|
||||
template <class Pair>
|
||||
struct select1st
|
||||
// : public std::unary_function<Pair, typename Pair::first_type>
|
||||
{
|
||||
template<class OtherPair>
|
||||
const typename Pair::first_type& operator()(const OtherPair& x) const
|
||||
{ return x.first; }
|
||||
|
||||
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
// identity is an extension: it is not part of the standard.
|
||||
template <class T>
|
||||
struct identity
|
||||
// : public std::unary_function<T,T>
|
||||
{
|
||||
typedef T type;
|
||||
const T& operator()(const T& x) const
|
||||
{ return x; }
|
||||
};
|
||||
|
||||
template<std::size_t S>
|
||||
struct ls_zeros
|
||||
{
|
||||
static const std::size_t value = (S & std::size_t(1)) ? 0 : (1u + ls_zeros<(S >> 1u)>::value);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ls_zeros<0>
|
||||
{
|
||||
static const std::size_t value = 0;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ls_zeros<1>
|
||||
{
|
||||
static const std::size_t value = 0;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP
|
||||
|
||||
46
test/external/boost/interprocess/detail/multi_segment_services.hpp
vendored
Normal file
46
test/external/boost/interprocess/detail/multi_segment_services.hpp
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
|
||||
#define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
|
||||
/*!\file
|
||||
Describes a named shared memory allocation user class.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
class multi_segment_services
|
||||
{
|
||||
public:
|
||||
virtual std::pair<void *, std::size_t> create_new_segment(std::size_t mem) = 0;
|
||||
virtual bool update_segments () = 0;
|
||||
virtual ~multi_segment_services() = 0;
|
||||
};
|
||||
|
||||
inline multi_segment_services::~multi_segment_services()
|
||||
{}
|
||||
|
||||
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP
|
||||
349
test/external/boost/interprocess/detail/named_proxy.hpp
vendored
Normal file
349
test/external/boost/interprocess/detail/named_proxy.hpp
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
||||
#define BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <new>
|
||||
#include <iterator>
|
||||
#include <boost/interprocess/detail/in_place_interface.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#include <boost/interprocess/detail/preprocessor.hpp>
|
||||
#else
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/interprocess/detail/variadic_templates_tools.hpp>
|
||||
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
//!\file
|
||||
//!Describes a proxy class that implements named allocation syntax.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
template<class T, bool is_iterator, class ...Args>
|
||||
struct CtorNArg : public placement_destroy<T>
|
||||
{
|
||||
typedef ipcdetail::bool_<is_iterator> IsIterator;
|
||||
typedef CtorNArg<T, is_iterator, Args...> self_t;
|
||||
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
|
||||
|
||||
self_t& operator++()
|
||||
{
|
||||
this->do_increment(IsIterator(), index_tuple_t());
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_t operator++(int) { return ++*this; *this; }
|
||||
|
||||
CtorNArg(Args && ...args)
|
||||
: args_(args...)
|
||||
{}
|
||||
|
||||
virtual void construct_n(void *mem
|
||||
, std::size_t num
|
||||
, std::size_t &constructed)
|
||||
{
|
||||
T* memory = static_cast<T*>(mem);
|
||||
for(constructed = 0; constructed < num; ++constructed){
|
||||
this->construct(memory++, IsIterator(), index_tuple_t());
|
||||
this->do_increment(IsIterator(), index_tuple_t());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<int ...IdxPack>
|
||||
void construct(void *mem, ipcdetail::true_, const index_tuple<IdxPack...>&)
|
||||
{ new((void*)mem)T(*boost::interprocess::forward<Args>(get<IdxPack>(args_))...); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void construct(void *mem, ipcdetail::false_, const index_tuple<IdxPack...>&)
|
||||
{ new((void*)mem)T(boost::interprocess::forward<Args>(get<IdxPack>(args_))...); }
|
||||
|
||||
template<int ...IdxPack>
|
||||
void do_increment(ipcdetail::true_, const index_tuple<IdxPack...>&)
|
||||
{
|
||||
this->expansion_helper(++get<IdxPack>(args_)...);
|
||||
}
|
||||
|
||||
template<class ...ExpansionArgs>
|
||||
void expansion_helper(ExpansionArgs &&...)
|
||||
{}
|
||||
|
||||
template<int ...IdxPack>
|
||||
void do_increment(ipcdetail::false_, const index_tuple<IdxPack...>&)
|
||||
{}
|
||||
|
||||
tuple<Args&...> args_;
|
||||
};
|
||||
|
||||
//!Describes a proxy class that implements named
|
||||
//!allocation syntax.
|
||||
template
|
||||
< class SegmentManager //segment manager to construct the object
|
||||
, class T //type of object to build
|
||||
, bool is_iterator //passing parameters are normal object or iterators?
|
||||
>
|
||||
class named_proxy
|
||||
{
|
||||
typedef typename SegmentManager::char_type char_type;
|
||||
const char_type * mp_name;
|
||||
SegmentManager * mp_mngr;
|
||||
mutable std::size_t m_num;
|
||||
const bool m_find;
|
||||
const bool m_dothrow;
|
||||
|
||||
public:
|
||||
named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
||||
: mp_name(name), mp_mngr(mngr), m_num(1)
|
||||
, m_find(find), m_dothrow(dothrow)
|
||||
{}
|
||||
|
||||
template<class ...Args>
|
||||
T *operator()(Args &&...args) const
|
||||
{
|
||||
CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...>
|
||||
(boost::interprocess::forward<Args>(args)...);
|
||||
return mp_mngr->template
|
||||
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
||||
}
|
||||
|
||||
//This operator allows --> named_new("Name")[3]; <-- syntax
|
||||
const named_proxy &operator[](std::size_t num) const
|
||||
{ m_num *= num; return *this; }
|
||||
};
|
||||
|
||||
#else //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
//!Function object that makes placement new
|
||||
//!without arguments
|
||||
template<class T>
|
||||
struct Ctor0Arg : public placement_destroy<T>
|
||||
{
|
||||
typedef Ctor0Arg self_t;
|
||||
|
||||
Ctor0Arg(){}
|
||||
|
||||
self_t& operator++() { return *this; }
|
||||
self_t operator++(int) { return *this; }
|
||||
|
||||
void construct(void *mem)
|
||||
{ new((void*)mem)T; }
|
||||
|
||||
virtual void construct_n(void *mem, std::size_t num, std::size_t &constructed)
|
||||
{
|
||||
T* memory = static_cast<T*>(mem);
|
||||
for(constructed = 0; constructed < num; ++constructed)
|
||||
new((void*)memory++)T;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// What the macro should generate (n == 2):
|
||||
//
|
||||
// template<class T, bool is_iterator, class P1, class P2>
|
||||
// struct Ctor2Arg
|
||||
// : public placement_destroy<T>
|
||||
// {
|
||||
// typedef ipcdetail::bool_<is_iterator> IsIterator;
|
||||
// typedef Ctor2Arg self_t;
|
||||
//
|
||||
// void do_increment(ipcdetail::false_)
|
||||
// { ++m_p1; ++m_p2; }
|
||||
//
|
||||
// void do_increment(ipcdetail::true_){}
|
||||
//
|
||||
// self_t& operator++()
|
||||
// {
|
||||
// this->do_increment(IsIterator());
|
||||
// return *this;
|
||||
// }
|
||||
//
|
||||
// self_t operator++(int) { return ++*this; *this; }
|
||||
//
|
||||
// Ctor2Arg(const P1 &p1, const P2 &p2)
|
||||
// : p1((P1 &)p_1), p2((P2 &)p_2) {}
|
||||
//
|
||||
// void construct(void *mem)
|
||||
// { new((void*)object)T(m_p1, m_p2); }
|
||||
//
|
||||
// virtual void construct_n(void *mem
|
||||
// , std::size_t num
|
||||
// , std::size_t &constructed)
|
||||
// {
|
||||
// T* memory = static_cast<T*>(mem);
|
||||
// for(constructed = 0; constructed < num; ++constructed){
|
||||
// this->construct(memory++, IsIterator());
|
||||
// this->do_increment(IsIterator());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// void construct(void *mem, ipcdetail::true_)
|
||||
// { new((void*)mem)T(*m_p1, *m_p2); }
|
||||
//
|
||||
// void construct(void *mem, ipcdetail::false_)
|
||||
// { new((void*)mem)T(m_p1, m_p2); }
|
||||
//
|
||||
// P1 &m_p1; P2 &m_p2;
|
||||
// };
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
//Note:
|
||||
//We define template parameters as const references to
|
||||
//be able to bind temporaries. After that we will un-const them.
|
||||
//This cast is ugly but it is necessary until "perfect forwarding"
|
||||
//is achieved in C++0x. Meanwhile, if we want to be able to
|
||||
//bind lvalues with non-const references, we have to be ugly
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<class T, bool is_iterator, BOOST_PP_ENUM_PARAMS(n, class P) > \
|
||||
struct BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
||||
: public placement_destroy<T> \
|
||||
{ \
|
||||
typedef ipcdetail::bool_<is_iterator> IsIterator; \
|
||||
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) self_t; \
|
||||
\
|
||||
void do_increment(ipcdetail::true_) \
|
||||
{ BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INC, _); } \
|
||||
\
|
||||
void do_increment(ipcdetail::false_){} \
|
||||
\
|
||||
self_t& operator++() \
|
||||
{ \
|
||||
this->do_increment(IsIterator()); \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
self_t operator++(int) { return ++*this; *this; } \
|
||||
\
|
||||
BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
||||
( BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_LIST, _) ) \
|
||||
: BOOST_PP_ENUM(n, BOOST_INTERPROCESS_AUX_PARAM_INIT, _) {} \
|
||||
\
|
||||
virtual void construct_n(void *mem \
|
||||
, std::size_t num \
|
||||
, std::size_t &constructed) \
|
||||
{ \
|
||||
T* memory = static_cast<T*>(mem); \
|
||||
for(constructed = 0; constructed < num; ++constructed){ \
|
||||
this->construct(memory++, IsIterator()); \
|
||||
this->do_increment(IsIterator()); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
void construct(void *mem, ipcdetail::true_) \
|
||||
{ \
|
||||
new((void*)mem) T \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD, _)); \
|
||||
} \
|
||||
\
|
||||
void construct(void *mem, ipcdetail::false_) \
|
||||
{ \
|
||||
new((void*)mem) T \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_MEMBER_FORWARD, _)); \
|
||||
} \
|
||||
\
|
||||
BOOST_PP_REPEAT(n, BOOST_INTERPROCESS_AUX_PARAM_DEFINE, _) \
|
||||
}; \
|
||||
//!
|
||||
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS)
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
//!Describes a proxy class that implements named
|
||||
//!allocation syntax.
|
||||
template
|
||||
< class SegmentManager //segment manager to construct the object
|
||||
, class T //type of object to build
|
||||
, bool is_iterator //passing parameters are normal object or iterators?
|
||||
>
|
||||
class named_proxy
|
||||
{
|
||||
typedef typename SegmentManager::char_type char_type;
|
||||
const char_type * mp_name;
|
||||
SegmentManager * mp_mngr;
|
||||
mutable std::size_t m_num;
|
||||
const bool m_find;
|
||||
const bool m_dothrow;
|
||||
|
||||
public:
|
||||
named_proxy(SegmentManager *mngr, const char_type *name, bool find, bool dothrow)
|
||||
: mp_name(name), mp_mngr(mngr), m_num(1)
|
||||
, m_find(find), m_dothrow(dothrow)
|
||||
{}
|
||||
|
||||
//!makes a named allocation and calls the
|
||||
//!default constructor
|
||||
T *operator()() const
|
||||
{
|
||||
Ctor0Arg<T> ctor_obj;
|
||||
return mp_mngr->template
|
||||
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
||||
}
|
||||
//!
|
||||
|
||||
#define BOOST_PP_LOCAL_MACRO(n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class P)> \
|
||||
T *operator()(BOOST_PP_ENUM (n, BOOST_INTERPROCESS_PP_PARAM_LIST, _)) const\
|
||||
{ \
|
||||
typedef BOOST_PP_CAT(BOOST_PP_CAT(Ctor, n), Arg) \
|
||||
<T, is_iterator, BOOST_PP_ENUM_PARAMS(n, P)> \
|
||||
ctor_obj_t; \
|
||||
ctor_obj_t ctor_obj \
|
||||
(BOOST_PP_ENUM(n, BOOST_INTERPROCESS_PP_PARAM_FORWARD, _)); \
|
||||
return mp_mngr->template generic_construct<T> \
|
||||
(mp_name, m_num, m_find, m_dothrow, ctor_obj); \
|
||||
} \
|
||||
//!
|
||||
|
||||
#define BOOST_PP_LOCAL_LIMITS ( 1, BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS )
|
||||
#include BOOST_PP_LOCAL_ITERATE()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// What the macro should generate (n == 2)
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// template <class P1, class P2>
|
||||
// T *operator()(P1 &p1, P2 &p2) const
|
||||
// {
|
||||
// typedef Ctor2Arg
|
||||
// <T, is_iterator, P1, P2>
|
||||
// ctor_obj_t;
|
||||
// ctor_obj_t ctor_obj(p1, p2);
|
||||
//
|
||||
// return mp_mngr->template generic_construct<T>
|
||||
// (mp_name, m_num, m_find, m_dothrow, ctor_obj);
|
||||
// }
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//This operator allows --> named_new("Name")[3]; <-- syntax
|
||||
const named_proxy &operator[](std::size_t num) const
|
||||
{ m_num *= num; return *this; }
|
||||
};
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP
|
||||
690
test/external/boost/interprocess/detail/os_file_functions.hpp
vendored
Normal file
690
test/external/boost/interprocess/detail/os_file_functions.hpp
vendored
Normal file
@@ -0,0 +1,690 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/permissions.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
# include <boost/interprocess/detail/win32_api.hpp>
|
||||
#else
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <fcntl.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# include <errno.h>
|
||||
# include <cstdio>
|
||||
# include <dirent.h>
|
||||
# if 0
|
||||
# include <sys/file.h>
|
||||
# endif
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef void * file_handle_t;
|
||||
typedef long long offset_t;
|
||||
typedef struct mapping_handle_impl_t{
|
||||
void * handle;
|
||||
bool is_shm;
|
||||
} mapping_handle_t;
|
||||
|
||||
typedef enum { read_only = winapi::generic_read
|
||||
, read_write = winapi::generic_read | winapi::generic_write
|
||||
, copy_on_write
|
||||
, read_private
|
||||
, invalid_mode = 0xffff
|
||||
} mode_t;
|
||||
|
||||
typedef enum { file_begin = winapi::file_begin
|
||||
, file_end = winapi::file_end
|
||||
, file_current = winapi::file_current
|
||||
} file_pos_t;
|
||||
|
||||
namespace ipcdetail{
|
||||
|
||||
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
|
||||
{
|
||||
mapping_handle_t ret;
|
||||
ret.handle = hnd;
|
||||
ret.is_shm = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
|
||||
{
|
||||
mapping_handle_t ret;
|
||||
ret.handle = hnd;
|
||||
ret.is_shm = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
|
||||
{ return hnd.handle; }
|
||||
|
||||
inline bool create_directory(const char *path)
|
||||
{ return winapi::create_directory(path); }
|
||||
|
||||
inline const char *get_temporary_path()
|
||||
{ return std::getenv("TMP"); }
|
||||
|
||||
|
||||
inline file_handle_t create_new_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
( name, (unsigned int)mode, winapi::create_new, attr
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions());
|
||||
}
|
||||
|
||||
inline file_handle_t create_or_open_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
( name, (unsigned int)mode, winapi::open_always, attr
|
||||
, (winapi::interprocess_security_attributes*)perm.get_permissions());
|
||||
}
|
||||
|
||||
inline file_handle_t open_existing_file
|
||||
(const char *name, mode_t mode, bool temporary = false)
|
||||
{
|
||||
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
|
||||
return winapi::create_file
|
||||
(name, (unsigned int)mode, winapi::open_existing, attr, 0);
|
||||
}
|
||||
|
||||
inline bool delete_file(const char *name)
|
||||
{ return winapi::unlink_file(name); }
|
||||
|
||||
inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
||||
{
|
||||
offset_t filesize;
|
||||
if(!winapi::get_file_size(hnd, filesize))
|
||||
return false;
|
||||
|
||||
if(size > (std::numeric_limits<offset_t>::max)()){
|
||||
winapi::set_last_error(winapi::error_file_too_large);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(size > (unsigned long long)filesize){
|
||||
if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
|
||||
return false;
|
||||
}
|
||||
//We will write zeros in the end of the file
|
||||
//since set_end_of_file does not guarantee this
|
||||
for(std::size_t remaining = size - filesize, write_size = 0
|
||||
;remaining > 0
|
||||
;remaining -= write_size){
|
||||
const std::size_t DataSize = 512;
|
||||
static char data [DataSize];
|
||||
write_size = DataSize < remaining ? DataSize : remaining;
|
||||
unsigned long written;
|
||||
winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0);
|
||||
if(written != write_size){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
|
||||
return false;
|
||||
}
|
||||
if(!winapi::set_end_of_file(hnd)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool get_file_size(file_handle_t hnd, offset_t &size)
|
||||
{ return winapi::get_file_size(hnd, size); }
|
||||
|
||||
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
|
||||
{ return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
|
||||
|
||||
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
|
||||
{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
|
||||
|
||||
inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
|
||||
{
|
||||
unsigned long written;
|
||||
return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0);
|
||||
}
|
||||
|
||||
inline file_handle_t invalid_file()
|
||||
{ return winapi::invalid_handle_value; }
|
||||
|
||||
inline bool close_file(file_handle_t hnd)
|
||||
{ return 0 != winapi::close_handle(hnd); }
|
||||
|
||||
inline bool acquire_file_lock(file_handle_t hnd)
|
||||
{
|
||||
static winapi::interprocess_overlapped overlapped;
|
||||
const unsigned long len = 0xffffffff;
|
||||
// winapi::interprocess_overlapped overlapped;
|
||||
// std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return winapi::lock_file_ex
|
||||
(hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
const unsigned long len = 0xffffffff;
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
if(!winapi::lock_file_ex
|
||||
(hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately,
|
||||
0, len, len, &overlapped)){
|
||||
return winapi::get_last_error() == winapi::error_lock_violation ?
|
||||
acquired = false, true : false;
|
||||
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock(file_handle_t hnd)
|
||||
{
|
||||
const unsigned long len = 0xffffffff;
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
|
||||
}
|
||||
|
||||
inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
||||
{
|
||||
const unsigned long len = 0xffffffff;
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
const unsigned long len = 0xffffffff;
|
||||
winapi::interprocess_overlapped overlapped;
|
||||
std::memset(&overlapped, 0, sizeof(overlapped));
|
||||
if(!winapi::lock_file_ex
|
||||
(hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){
|
||||
return winapi::get_last_error() == winapi::error_lock_violation ?
|
||||
acquired = false, true : false;
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock_sharable(file_handle_t hnd)
|
||||
{ return release_file_lock(hnd); }
|
||||
|
||||
inline bool delete_subdirectories_recursive
|
||||
(const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
|
||||
{
|
||||
bool bSubdirectory = false; // Flag, indicating whether
|
||||
// subdirectories have been found
|
||||
void * hFile; // Handle to directory
|
||||
std::string strFilePath; // Filepath
|
||||
std::string strPattern; // Pattern
|
||||
winapi::win32_find_data_t FileInformation; // File information
|
||||
|
||||
//Find all files and directories
|
||||
strPattern = refcstrRootDirectory + "\\*.*";
|
||||
hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
|
||||
if(hFile != winapi::invalid_handle_value){
|
||||
do{
|
||||
//If it's not "." or ".." or the pointed root_level dont_delete_this erase it
|
||||
if(FileInformation.cFileName[0] != '.' &&
|
||||
!(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
|
||||
strFilePath.erase();
|
||||
strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
|
||||
|
||||
//If it's a directory, go recursive
|
||||
if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
|
||||
// Delete subdirectory
|
||||
if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1))
|
||||
return false;
|
||||
}
|
||||
//If it's a file, just delete it
|
||||
else{
|
||||
// Set file attributes
|
||||
//if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
|
||||
//return winapi::get_last_error();
|
||||
// Delete file
|
||||
winapi::delete_file(strFilePath.c_str());
|
||||
}
|
||||
}
|
||||
//Go to the next file
|
||||
} while(winapi::find_next_file(hFile, &FileInformation) == 1);
|
||||
|
||||
// Close handle
|
||||
winapi::find_close(hFile);
|
||||
|
||||
//See if the loop has ended with an error or just because we've traversed all the files
|
||||
if(winapi::get_last_error() != winapi::error_no_more_files){
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Erase empty subdirectories or original refcstrRootDirectory
|
||||
if(!bSubdirectory && count)
|
||||
{
|
||||
// Set directory attributes
|
||||
//if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
|
||||
//return ::GetLastError();
|
||||
// Delete directory
|
||||
if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
|
||||
inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
||||
{
|
||||
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
|
||||
}
|
||||
|
||||
|
||||
template<class Function>
|
||||
inline bool for_each_file_in_dir(const char *dir, Function f)
|
||||
{
|
||||
void * hFile; // Handle to directory
|
||||
winapi::win32_find_data_t FileInformation; // File information
|
||||
|
||||
//Get base directory
|
||||
std::string str(dir);
|
||||
const std::size_t base_root_dir_len = str.size();
|
||||
|
||||
//Find all files and directories
|
||||
str += "\\*.*";
|
||||
hFile = winapi::find_first_file(str.c_str(), &FileInformation);
|
||||
if(hFile != winapi::invalid_handle_value){
|
||||
do{ //Now loop every file
|
||||
str.erase(base_root_dir_len);
|
||||
//If it's not "." or ".." skip it
|
||||
if(FileInformation.cFileName[0] != '.'){
|
||||
str += "\\"; str += FileInformation.cFileName;
|
||||
//If it's a file, apply erase logic
|
||||
if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
|
||||
f(str.c_str(), FileInformation.cFileName);
|
||||
}
|
||||
}
|
||||
//Go to the next file
|
||||
} while(winapi::find_next_file(hFile, &FileInformation) == 1);
|
||||
|
||||
// Close handle and see if the loop has ended with an error
|
||||
winapi::find_close(hFile);
|
||||
if(winapi::get_last_error() != winapi::error_no_more_files){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef int file_handle_t;
|
||||
typedef off_t offset_t;
|
||||
|
||||
typedef struct mapping_handle_impl_t
|
||||
{
|
||||
file_handle_t handle;
|
||||
bool is_xsi;
|
||||
} mapping_handle_t;
|
||||
|
||||
typedef enum { read_only = O_RDONLY
|
||||
, read_write = O_RDWR
|
||||
, copy_on_write
|
||||
, read_private
|
||||
, invalid_mode = 0xffff
|
||||
} mode_t;
|
||||
|
||||
typedef enum { file_begin = SEEK_SET
|
||||
, file_end = SEEK_END
|
||||
, file_current = SEEK_CUR
|
||||
} file_pos_t;
|
||||
|
||||
namespace ipcdetail{
|
||||
|
||||
inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
|
||||
{
|
||||
mapping_handle_t ret;
|
||||
ret.handle = hnd;
|
||||
ret.is_xsi = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
|
||||
{ return hnd.handle; }
|
||||
|
||||
inline bool create_directory(const char *path)
|
||||
{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
|
||||
|
||||
inline const char *get_temporary_path()
|
||||
{
|
||||
const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP" };
|
||||
const int names_size = sizeof(names)/sizeof(names[0]);
|
||||
struct stat data;
|
||||
for(int i = 0; i != names_size; ++i){
|
||||
if(::stat(names[i], &data) == 0){
|
||||
return names[i];
|
||||
}
|
||||
}
|
||||
return "/tmp";
|
||||
}
|
||||
|
||||
inline file_handle_t create_new_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
|
||||
if(ret >= 0){
|
||||
::fchmod(ret, perm.get_permissions());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t create_or_open_file
|
||||
(const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
int ret = -1;
|
||||
//We need a loop to change permissions correctly using fchmod, since
|
||||
//with "O_CREAT only" ::open we don't know if we've created or opened the file.
|
||||
while(1){
|
||||
ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
|
||||
if(ret >= 0){
|
||||
::fchmod(ret, perm.get_permissions());
|
||||
break;
|
||||
}
|
||||
else if(errno == EEXIST){
|
||||
if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline file_handle_t open_existing_file
|
||||
(const char *name, mode_t mode, bool temporary = false)
|
||||
{
|
||||
(void)temporary;
|
||||
return ::open(name, (int)mode);
|
||||
}
|
||||
|
||||
inline bool delete_file(const char *name)
|
||||
{ return ::unlink(name) == 0; }
|
||||
|
||||
inline bool truncate_file (file_handle_t hnd, std::size_t size)
|
||||
{
|
||||
if(off_t(size) < 0){
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
return 0 == ::ftruncate(hnd, size);
|
||||
}
|
||||
|
||||
inline bool get_file_size(file_handle_t hnd, offset_t &size)
|
||||
{
|
||||
struct stat data;
|
||||
bool ret = 0 == ::fstat(hnd, &data);
|
||||
if(ret){
|
||||
size = data.st_size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
|
||||
{ return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
|
||||
|
||||
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
|
||||
{
|
||||
off = ::lseek(hnd, 0, SEEK_CUR);
|
||||
return off != ((off_t)-1);
|
||||
}
|
||||
|
||||
inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
|
||||
{ return (ssize_t(numdata)) == ::write(hnd, data, numdata); }
|
||||
|
||||
inline file_handle_t invalid_file()
|
||||
{ return -1; }
|
||||
|
||||
inline bool close_file(file_handle_t hnd)
|
||||
{ return ::close(hnd) == 0; }
|
||||
|
||||
inline bool acquire_file_lock(file_handle_t hnd)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
return -1 != ::fcntl(hnd, F_SETLKW, &lock);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
int ret = ::fcntl(hnd, F_SETLK, &lock);
|
||||
if(ret == -1){
|
||||
return (errno == EAGAIN || errno == EACCES) ?
|
||||
acquired = false, true : false;
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock(file_handle_t hnd)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_UNLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
return -1 != ::fcntl(hnd, F_SETLK, &lock);
|
||||
}
|
||||
|
||||
inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
||||
{
|
||||
struct ::flock lock;
|
||||
lock.l_type = F_RDLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
return -1 != ::fcntl(hnd, F_SETLKW, &lock);
|
||||
}
|
||||
|
||||
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
struct flock lock;
|
||||
lock.l_type = F_RDLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
int ret = ::fcntl(hnd, F_SETLK, &lock);
|
||||
if(ret == -1){
|
||||
return (errno == EAGAIN || errno == EACCES) ?
|
||||
acquired = false, true : false;
|
||||
}
|
||||
return (acquired = true);
|
||||
}
|
||||
|
||||
inline bool release_file_lock_sharable(file_handle_t hnd)
|
||||
{ return release_file_lock(hnd); }
|
||||
|
||||
#if 0
|
||||
inline bool acquire_file_lock(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_EX); }
|
||||
|
||||
inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
|
||||
acquired = ret == 0;
|
||||
return (acquired || errno == EWOULDBLOCK);
|
||||
}
|
||||
|
||||
inline bool release_file_lock(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_UN); }
|
||||
|
||||
inline bool acquire_file_lock_sharable(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_SH); }
|
||||
|
||||
inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
|
||||
{
|
||||
int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
|
||||
acquired = ret == 0;
|
||||
return (acquired || errno == EWOULDBLOCK);
|
||||
}
|
||||
|
||||
inline bool release_file_lock_sharable(file_handle_t hnd)
|
||||
{ return 0 == ::flock(hnd, LOCK_UN); }
|
||||
#endif
|
||||
|
||||
inline bool delete_subdirectories_recursive
|
||||
(const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
||||
{
|
||||
DIR *d = opendir(refcstrRootDirectory.c_str());
|
||||
if(!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dir_close
|
||||
{
|
||||
DIR *d_;
|
||||
dir_close(DIR *d) : d_(d) {}
|
||||
~dir_close() { ::closedir(d_); }
|
||||
} dc(d); (void)dc;
|
||||
|
||||
struct ::dirent *de;
|
||||
struct ::stat st;
|
||||
std::string fn;
|
||||
|
||||
while((de=::readdir(d))) {
|
||||
if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
|
||||
|| (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
|
||||
continue;
|
||||
}
|
||||
if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
|
||||
continue;
|
||||
}
|
||||
fn = refcstrRootDirectory;
|
||||
fn += '/';
|
||||
fn += de->d_name;
|
||||
|
||||
if(std::remove(fn.c_str())) {
|
||||
if(::stat(fn.c_str(), & st)) {
|
||||
return false;
|
||||
}
|
||||
if(S_ISDIR(st.st_mode)) {
|
||||
if(!delete_subdirectories_recursive(fn, 0) ){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::remove(refcstrRootDirectory.c_str()) ? false : true;
|
||||
}
|
||||
|
||||
template<class Function>
|
||||
inline bool for_each_file_in_dir(const char *dir, Function f)
|
||||
{
|
||||
std::string refcstrRootDirectory(dir);
|
||||
|
||||
DIR *d = opendir(refcstrRootDirectory.c_str());
|
||||
if(!d) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct dir_close
|
||||
{
|
||||
DIR *d_;
|
||||
dir_close(DIR *d) : d_(d) {}
|
||||
~dir_close() { ::closedir(d_); }
|
||||
} dc(d); (void)dc;
|
||||
|
||||
struct ::dirent *de;
|
||||
struct ::stat st;
|
||||
std::string fn;
|
||||
|
||||
while((de=::readdir(d))) {
|
||||
if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
|
||||
|| (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
|
||||
continue;
|
||||
}
|
||||
fn = refcstrRootDirectory;
|
||||
fn += '/';
|
||||
fn += de->d_name;
|
||||
|
||||
if(::stat(fn.c_str(), & st)) {
|
||||
return false;
|
||||
}
|
||||
//If it's a file, apply erase logic
|
||||
if(!S_ISDIR(st.st_mode)) {
|
||||
f(fn.c_str(), de->d_name);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
|
||||
inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
|
||||
{
|
||||
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
|
||||
}
|
||||
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
inline bool open_or_create_directory(const char *dir_name)
|
||||
{
|
||||
//If fails, check that it's because it already exists
|
||||
if(!create_directory(dir_name)){
|
||||
error_info info(system_error_code());
|
||||
if(info.get_error_code() != already_exists_error){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
|
||||
201
test/external/boost/interprocess/detail/os_thread_functions.hpp
vendored
Normal file
201
test/external/boost/interprocess/detail/os_thread_functions.hpp
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/streams/bufferstream.hpp>
|
||||
#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
|
||||
|
||||
#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>
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail{
|
||||
|
||||
#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef unsigned long OS_process_id_t;
|
||||
typedef unsigned long OS_thread_id_t;
|
||||
typedef OS_thread_id_t OS_systemwide_thread_id_t;
|
||||
|
||||
//process
|
||||
inline OS_process_id_t get_current_process_id()
|
||||
{ return winapi::get_current_process_id(); }
|
||||
|
||||
inline OS_process_id_t get_invalid_process_id()
|
||||
{ return OS_process_id_t(0); }
|
||||
|
||||
//thread
|
||||
inline OS_thread_id_t get_current_thread_id()
|
||||
{ return winapi::get_current_thread_id(); }
|
||||
|
||||
inline OS_thread_id_t get_invalid_thread_id()
|
||||
{ return OS_thread_id_t(0xffffffff); }
|
||||
|
||||
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
||||
{ return id1 == id2; }
|
||||
|
||||
inline void thread_yield()
|
||||
{ winapi::sched_yield(); }
|
||||
|
||||
//systemwide thread
|
||||
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
|
||||
{
|
||||
return get_current_thread_id();
|
||||
}
|
||||
|
||||
inline void systemwide_thread_id_copy
|
||||
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
|
||||
{
|
||||
to = from;
|
||||
}
|
||||
|
||||
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
|
||||
{
|
||||
return equal_thread_id(id1, id2);
|
||||
}
|
||||
|
||||
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
||||
{
|
||||
return get_invalid_thread_id();
|
||||
}
|
||||
|
||||
inline long double get_current_process_creation_time()
|
||||
{
|
||||
winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
|
||||
|
||||
get_process_times
|
||||
( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
|
||||
|
||||
typedef long double ldouble_t;
|
||||
const ldouble_t resolution = (100.0l/1000000000.0l);
|
||||
return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
|
||||
CreationTime.dwLowDateTime*resolution;
|
||||
}
|
||||
|
||||
|
||||
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef pthread_t OS_thread_id_t;
|
||||
typedef pid_t OS_process_id_t;
|
||||
|
||||
struct OS_systemwide_thread_id_t
|
||||
{
|
||||
OS_systemwide_thread_id_t()
|
||||
: pid(), tid()
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t(pid_t p, pthread_t t)
|
||||
: pid(p), tid(t)
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t(const OS_systemwide_thread_id_t &x)
|
||||
: pid(x.pid), tid(x.tid)
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t(const volatile OS_systemwide_thread_id_t &x)
|
||||
: pid(x.pid), tid(x.tid)
|
||||
{}
|
||||
|
||||
OS_systemwide_thread_id_t & operator=(const OS_systemwide_thread_id_t &x)
|
||||
{ pid = x.pid; tid = x.tid; return *this; }
|
||||
|
||||
OS_systemwide_thread_id_t & operator=(const volatile OS_systemwide_thread_id_t &x)
|
||||
{ pid = x.pid; tid = x.tid; return *this; }
|
||||
|
||||
void operator=(const OS_systemwide_thread_id_t &x) volatile
|
||||
{ pid = x.pid; tid = x.tid; }
|
||||
|
||||
pid_t pid;
|
||||
pthread_t tid;
|
||||
};
|
||||
|
||||
inline void systemwide_thread_id_copy
|
||||
(const volatile OS_systemwide_thread_id_t &from, volatile OS_systemwide_thread_id_t &to)
|
||||
{
|
||||
to.pid = from.pid;
|
||||
to.tid = from.tid;
|
||||
}
|
||||
|
||||
//process
|
||||
inline OS_process_id_t get_current_process_id()
|
||||
{ return ::getpid(); }
|
||||
|
||||
inline OS_process_id_t get_invalid_process_id()
|
||||
{ return pid_t(0); }
|
||||
|
||||
//thread
|
||||
inline OS_thread_id_t get_current_thread_id()
|
||||
{ return ::pthread_self(); }
|
||||
|
||||
inline OS_thread_id_t get_invalid_thread_id()
|
||||
{
|
||||
static pthread_t invalid_id;
|
||||
return invalid_id;
|
||||
}
|
||||
|
||||
inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2)
|
||||
{ return 0 != pthread_equal(id1, id2); }
|
||||
|
||||
inline void thread_yield()
|
||||
{ ::sched_yield(); }
|
||||
|
||||
//systemwide thread
|
||||
inline OS_systemwide_thread_id_t get_current_systemwide_thread_id()
|
||||
{
|
||||
return OS_systemwide_thread_id_t(::getpid(), ::pthread_self());
|
||||
}
|
||||
|
||||
inline bool equal_systemwide_thread_id(const OS_systemwide_thread_id_t &id1, const OS_systemwide_thread_id_t &id2)
|
||||
{
|
||||
return (0 != pthread_equal(id1.tid, id2.tid)) && (id1.pid == id2.pid);
|
||||
}
|
||||
|
||||
inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id()
|
||||
{
|
||||
return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
|
||||
}
|
||||
|
||||
inline long double get_current_process_creation_time()
|
||||
{ return 0.0L; }
|
||||
|
||||
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
|
||||
|
||||
inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
|
||||
{
|
||||
bufferstream bstream(pid_str, sizeof(pid_str));
|
||||
bstream << pid << std::ends;
|
||||
}
|
||||
|
||||
inline void get_pid_str(pid_str_t &pid_str)
|
||||
{ get_pid_str(pid_str, get_current_process_id()); }
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP
|
||||
74
test/external/boost/interprocess/detail/pointer_type.hpp
vendored
Normal file
74
test/external/boost/interprocess/detail/pointer_type.hpp
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
struct two {char _[2];};
|
||||
|
||||
namespace pointer_type_imp {
|
||||
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(typename U::pointer* = 0);
|
||||
|
||||
} //namespace pointer_type_imp {
|
||||
|
||||
template <class T>
|
||||
struct has_pointer_type
|
||||
{
|
||||
static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
|
||||
};
|
||||
|
||||
namespace pointer_type_imp {
|
||||
|
||||
template <class T, class D, bool = has_pointer_type<D>::value>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename D::pointer type;
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
struct pointer_type<T, D, false>
|
||||
{
|
||||
typedef T* type;
|
||||
};
|
||||
|
||||
} //namespace pointer_type_imp {
|
||||
|
||||
template <class T, class D>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename pointer_type_imp::pointer_type<T,
|
||||
typename ipcdetail::remove_reference<D>::type>::type type;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP
|
||||
|
||||
42
test/external/boost/interprocess/detail/posix_time_types_wrk.hpp
vendored
Normal file
42
test/external/boost/interprocess/detail/posix_time_types_wrk.hpp
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
|
||||
#define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
|
||||
|
||||
//workaround to avoid winsock redefines when using date-time
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifndef WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef _WIN32
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/date_time/posix_time/conversion.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
typedef boost::date_time::microsec_clock<boost::posix_time::ptime> microsec_clock;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef _WIN32
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP
|
||||
|
||||
137
test/external/boost/interprocess/detail/preprocessor.hpp
vendored
Normal file
137
test/external/boost/interprocess/detail/preprocessor.hpp
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include "config_begin.hpp"
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#error "This file is not needed when perfect forwarding is available"
|
||||
#endif
|
||||
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
|
||||
#define BOOST_INTERPROCESS_MAX_CONSTRUCTOR_PARAMETERS 10
|
||||
|
||||
//Note:
|
||||
//We define template parameters as const references to
|
||||
//be able to bind temporaries. After that we will un-const them.
|
||||
//This cast is ugly but it is necessary until "perfect forwarding"
|
||||
//is achieved in C++0x. Meanwhile, if we want to be able to
|
||||
//bind rvalues with non-const references, we have to be ugly
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
|
||||
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
#define BOOST_INTERPROCESS_PARAM(U, u) \
|
||||
U && u \
|
||||
//!
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_PARAM(U, u) \
|
||||
const U & u \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
|
||||
#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
|
||||
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (BOOST_INTERPROCESS_MOVE_NAMESPACE::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
|
||||
//!
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
|
||||
//!
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
|
||||
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_INC(z, n, data) \
|
||||
BOOST_PP_CAT(++m_p, n) \
|
||||
//!
|
||||
|
||||
#ifndef BOOST_NO_RVALUE_REFERENCES
|
||||
|
||||
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
|
||||
#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
|
||||
#else
|
||||
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
|
||||
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
|
||||
//!
|
||||
#endif
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
|
||||
::boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
|
||||
//!
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
#include <boost/container/detail/stored_ref.hpp>
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
|
||||
::boost::container::containers_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \
|
||||
//!
|
||||
|
||||
#else
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
|
||||
::boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
|
||||
//!
|
||||
|
||||
#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
|
||||
|
||||
#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
|
||||
BOOST_PP_CAT(*m_p, n) \
|
||||
//!
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#else
|
||||
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#error "This file is not needed when perfect forwarding is available"
|
||||
#endif
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP
|
||||
33
test/external/boost/interprocess/detail/ptime_wrk.hpp
vendored
Normal file
33
test/external/boost/interprocess/detail/ptime_wrk.hpp
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
|
||||
#define BOOST_INTERPROCESS_PTIME_WRK_HPP
|
||||
|
||||
//workaround to avoid winsock redefines when using date-time
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifndef WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef _WIN32
|
||||
|
||||
#include <boost/date_time/posix_time/ptime.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef BOOST_INTERPROCESS_WIN32_LEAN_AND_MEAN
|
||||
#endif //#ifdef _WIN32
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP
|
||||
|
||||
439
test/external/boost/interprocess/detail/robust_emulation.hpp
vendored
Normal file
439
test/external/boost/interprocess/detail/robust_emulation.hpp
vendored
Normal file
@@ -0,0 +1,439 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2010-2010. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
|
||||
#define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
|
||||
|
||||
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
|
||||
#include <boost/interprocess/detail/intermodule_singleton.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
namespace ipcdetail{
|
||||
|
||||
namespace robust_emulation_helpers {
|
||||
|
||||
template<class T>
|
||||
class mutex_traits
|
||||
{
|
||||
public:
|
||||
static void take_ownership(T &t)
|
||||
{ t.take_ownership(); }
|
||||
};
|
||||
|
||||
inline void remove_if_can_lock_file(const char *file_path)
|
||||
{
|
||||
file_handle_t fhnd = open_existing_file(file_path, read_write);
|
||||
|
||||
if(fhnd != invalid_file()){
|
||||
bool acquired;
|
||||
if(try_acquire_file_lock(fhnd, acquired) && acquired){
|
||||
delete_file(file_path);
|
||||
}
|
||||
close_file(fhnd);
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *robust_lock_subdir_path()
|
||||
{ return "robust"; }
|
||||
|
||||
inline const char *robust_lock_prefix()
|
||||
{ return "lck"; }
|
||||
|
||||
inline void robust_lock_path(std::string &s)
|
||||
{
|
||||
tmp_folder(s);
|
||||
s += "/";
|
||||
s += robust_lock_subdir_path();
|
||||
}
|
||||
|
||||
inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid)
|
||||
{
|
||||
file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath
|
||||
(robust_lock_subdir_path(), robust_lock_prefix(), pid, s);
|
||||
}
|
||||
|
||||
//This class will be a intermodule_singleton. The constructor will create
|
||||
//a lock file, the destructor will erase it.
|
||||
//
|
||||
//We should take in care that another process might be erasing unlocked
|
||||
//files while creating this one, so there are some race conditions we must
|
||||
//take in care to guarantee some robustness.
|
||||
class robust_mutex_lock_file
|
||||
{
|
||||
file_handle_t fd;
|
||||
std::string fname;
|
||||
public:
|
||||
robust_mutex_lock_file()
|
||||
{
|
||||
permissions p;
|
||||
p.set_unrestricted();
|
||||
//Remove old lock files of other processes
|
||||
remove_old_robust_lock_files();
|
||||
//Create path and obtain lock file path for this process
|
||||
create_and_get_robust_lock_file_path(fname, get_current_process_id());
|
||||
|
||||
//Now try to open or create the lock file
|
||||
fd = create_or_open_file(fname.c_str(), read_write, p);
|
||||
//If we can't open or create it, then something unrecoverable has happened
|
||||
if(fd == invalid_file()){
|
||||
throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file");
|
||||
}
|
||||
|
||||
//Now we must take in care a race condition with another process
|
||||
//calling "remove_old_robust_lock_files()". No other threads from this
|
||||
//process will be creating the lock file because intermodule_singleton
|
||||
//guarantees this. So let's loop acquiring the lock and checking if we
|
||||
//can't exclusively create the file (if the file is erased by another process
|
||||
//then this exclusive open would fail). If the file can't be exclusively created
|
||||
//then we have correctly open/create and lock the file. If the file can
|
||||
//be exclusively created, then close previous locked file and try again.
|
||||
while(1){
|
||||
bool acquired;
|
||||
if(!try_acquire_file_lock(fd, acquired) || !acquired ){
|
||||
throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock");
|
||||
}
|
||||
//Creating exclusively must fail with already_exists_error
|
||||
//to make sure we've locked the file and no one has
|
||||
//deleted it between creation and locking
|
||||
file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p);
|
||||
if(fd2 != invalid_file()){
|
||||
close_file(fd);
|
||||
fd = fd2;
|
||||
continue;
|
||||
}
|
||||
//If exclusive creation fails with expected error go ahead
|
||||
else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist
|
||||
//Leak descriptor to mantain the file locked until the process dies
|
||||
break;
|
||||
}
|
||||
//If exclusive creation fails with unexpected error throw an unrecoverable error
|
||||
else{
|
||||
close_file(fd);
|
||||
throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~robust_mutex_lock_file()
|
||||
{
|
||||
//The destructor is guaranteed by intermodule_singleton to be
|
||||
//executed serialized between all threads from current process,
|
||||
//so we just need to close and unlink the file.
|
||||
close_file(fd);
|
||||
//If some other process deletes the file before us after
|
||||
//closing it there should not be any problem.
|
||||
delete_file(fname.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
//This functor is execute for all files in the lock file directory
|
||||
class other_process_lock_remover
|
||||
{
|
||||
public:
|
||||
void operator()(const char *filepath, const char *filename)
|
||||
{
|
||||
std::string pid_str;
|
||||
//If the lock file is not our own lock file, then try to do the cleanup
|
||||
if(!file_locking_helpers::check_if_filename_complies_with_pid
|
||||
(filename, robust_lock_prefix(), get_current_process_id(), pid_str)){
|
||||
remove_if_can_lock_file(filepath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
bool remove_old_robust_lock_files()
|
||||
{
|
||||
std::string refcstrRootDirectory;
|
||||
robust_lock_path(refcstrRootDirectory);
|
||||
return for_each_file_in_dir(refcstrRootDirectory.c_str(), other_process_lock_remover());
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace robust_emulation_helpers {
|
||||
|
||||
//This is the mutex class. Mutex should follow mutex concept
|
||||
//with an additonal "take_ownership()" function to take ownership of the
|
||||
//mutex when robust_emulation_mutex determines the previous owner was dead.
|
||||
template<class Mutex>
|
||||
class robust_emulation_mutex
|
||||
{
|
||||
public:
|
||||
static const boost::uint32_t correct_state = 0;
|
||||
static const boost::uint32_t fixing_state = 1;
|
||||
static const boost::uint32_t broken_state = 2;
|
||||
|
||||
typedef robust_emulation_helpers::mutex_traits<Mutex> mutex_traits_t;
|
||||
|
||||
robust_emulation_mutex();
|
||||
void lock();
|
||||
bool try_lock();
|
||||
bool timed_lock(const boost::posix_time::ptime &abs_time);
|
||||
void unlock();
|
||||
void consistent();
|
||||
bool previous_owner_dead();
|
||||
|
||||
private:
|
||||
static const unsigned int spin_threshold = 100u;
|
||||
bool lock_own_unique_file();
|
||||
bool robust_check();
|
||||
bool check_if_owner_dead_and_take_ownership_atomically();
|
||||
bool is_owner_dead(boost::uint32_t owner);
|
||||
void owner_to_filename(boost::uint32_t owner, std::string &s);
|
||||
//The real mutex
|
||||
Mutex mtx;
|
||||
//The pid of the owner
|
||||
volatile boost::uint32_t owner;
|
||||
//The state of the mutex (correct, fixing, broken)
|
||||
volatile boost::uint32_t state;
|
||||
};
|
||||
|
||||
template<class Mutex>
|
||||
inline robust_emulation_mutex<Mutex>::robust_emulation_mutex()
|
||||
: mtx(), owner(get_invalid_process_id()), state(correct_state)
|
||||
{}
|
||||
|
||||
template<class Mutex>
|
||||
inline void robust_emulation_mutex<Mutex>::lock()
|
||||
{
|
||||
//If the mutex is broken (recovery didn't call consistent()),
|
||||
//then throw an exception
|
||||
if(atomic_read32(&this->state) == broken_state){
|
||||
throw interprocess_exception(lock_error, "Broken id");
|
||||
}
|
||||
|
||||
//This function provokes intermodule_singleton instantiation
|
||||
if(!this->lock_own_unique_file()){
|
||||
throw interprocess_exception(lock_error, "Broken id");
|
||||
}
|
||||
|
||||
//Now the logic. Try to lock, if successful mark the owner
|
||||
//if it fails, start recovery logic
|
||||
unsigned int spin_count = 0;
|
||||
while(1){
|
||||
if (mtx.try_lock()){
|
||||
atomic_write32(&this->owner, get_current_process_id());
|
||||
break;
|
||||
}
|
||||
else{
|
||||
//Do the dead owner checking each spin_threshold lock tries
|
||||
ipcdetail::thread_yield();
|
||||
++spin_count;
|
||||
if(spin_count > spin_threshold){
|
||||
//Check if owner dead and take ownership if possible
|
||||
if(!this->robust_check()){
|
||||
spin_count = 0;
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::try_lock()
|
||||
{
|
||||
//Same as lock() but without spinning
|
||||
if(atomic_read32(&this->state) == broken_state){
|
||||
throw interprocess_exception(lock_error, "Broken id");
|
||||
}
|
||||
|
||||
if(!this->lock_own_unique_file()){
|
||||
throw interprocess_exception(lock_error, "Broken id");
|
||||
}
|
||||
|
||||
if (mtx.try_lock()){
|
||||
atomic_write32(&this->owner, get_current_process_id());
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
if(!this->robust_check()){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::timed_lock
|
||||
(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Same as lock() but with an additional timeout
|
||||
if(abs_time == boost::posix_time::pos_infin){
|
||||
this->lock();
|
||||
return true;
|
||||
}
|
||||
//Obtain current count and target time
|
||||
boost::posix_time::ptime now = microsec_clock::universal_time();
|
||||
|
||||
if(now >= abs_time)
|
||||
return this->try_lock();
|
||||
|
||||
do{
|
||||
if(this->try_lock()){
|
||||
break;
|
||||
}
|
||||
now = microsec_clock::universal_time();
|
||||
|
||||
if(now >= abs_time){
|
||||
return this->try_lock();
|
||||
}
|
||||
// relinquish current time slice
|
||||
ipcdetail::thread_yield();
|
||||
}while (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline void robust_emulation_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s)
|
||||
{
|
||||
robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner);
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::robust_check()
|
||||
{
|
||||
//If the old owner was dead, and we've acquired ownership, mark
|
||||
//the mutex as 'fixing'. This means that a "consistent()" is needed
|
||||
//to avoid marking the mutex as "broken" when the mutex is unlocked.
|
||||
if(!this->check_if_owner_dead_and_take_ownership_atomically()){
|
||||
return false;
|
||||
}
|
||||
atomic_write32(&this->state, fixing_state);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::check_if_owner_dead_and_take_ownership_atomically()
|
||||
{
|
||||
boost::uint32_t cur_owner = get_current_process_id();
|
||||
boost::uint32_t old_owner = atomic_read32(&this->owner), old_owner2;
|
||||
//The cas loop guarantees that only one thread from this or another process
|
||||
//will succeed taking ownership
|
||||
do{
|
||||
//Check if owner is dead
|
||||
if(!this->is_owner_dead(old_owner)){
|
||||
return false;
|
||||
}
|
||||
//If it's dead, try to mark this process as the owner in the owner field
|
||||
old_owner2 = old_owner;
|
||||
old_owner = atomic_cas32(&this->owner, cur_owner, old_owner);
|
||||
}while(old_owner2 != old_owner);
|
||||
//If success, we fix mutex internals to assure our ownership
|
||||
mutex_traits_t::take_ownership(mtx);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::is_owner_dead(boost::uint32_t owner)
|
||||
{
|
||||
//If owner is an invalid id, then it's clear it's dead
|
||||
if(owner == (boost::uint32_t)get_invalid_process_id()){
|
||||
return true;
|
||||
}
|
||||
|
||||
//Obtain the lock filename of the owner field
|
||||
std::string file;
|
||||
this->owner_to_filename(owner, file);
|
||||
|
||||
//Now the logic is to open and lock it
|
||||
file_handle_t fhnd = open_existing_file(file.c_str(), read_write);
|
||||
|
||||
if(fhnd != invalid_file()){
|
||||
//If we can open the file, lock it.
|
||||
bool acquired;
|
||||
if(try_acquire_file_lock(fhnd, acquired) && acquired){
|
||||
//If locked, just delete the file
|
||||
delete_file(file.c_str());
|
||||
close_file(fhnd);
|
||||
return true;
|
||||
}
|
||||
//If not locked, the owner is suppossed to be still alive
|
||||
close_file(fhnd);
|
||||
}
|
||||
else{
|
||||
//If the lock file does not exist then the owner is dead (a previous cleanup)
|
||||
//function has deleted the file. If there is another reason, then this is
|
||||
//an unrecoverable error
|
||||
if(error_info(system_error_code()).get_error_code() == not_found_error){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline void robust_emulation_mutex<Mutex>::consistent()
|
||||
{
|
||||
//This function supposes the previous state was "fixing"
|
||||
//and the current process holds the mutex
|
||||
if(atomic_read32(&this->state) != fixing_state &&
|
||||
atomic_read32(&this->owner) != (boost::uint32_t)get_current_process_id()){
|
||||
throw interprocess_exception(lock_error, "Broken id");
|
||||
}
|
||||
//If that's the case, just update mutex state
|
||||
atomic_write32(&this->state, correct_state);
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::previous_owner_dead()
|
||||
{
|
||||
//Notifies if a owner recovery has been performed in the last lock()
|
||||
return atomic_read32(&this->state) == fixing_state;
|
||||
};
|
||||
|
||||
template<class Mutex>
|
||||
inline void robust_emulation_mutex<Mutex>::unlock()
|
||||
{
|
||||
//If in "fixing" state, unlock and mark the mutex as unrecoverable
|
||||
//so next locks will fail and all threads will be notified that the
|
||||
//data protected by the mutex was not recoverable.
|
||||
if(atomic_read32(&this->state) == fixing_state){
|
||||
atomic_write32(&this->state, broken_state);
|
||||
}
|
||||
//Write an invalid owner to minimize pid reuse possibility
|
||||
atomic_write32(&this->owner, get_invalid_process_id());
|
||||
mtx.unlock();
|
||||
}
|
||||
|
||||
template<class Mutex>
|
||||
inline bool robust_emulation_mutex<Mutex>::lock_own_unique_file()
|
||||
{
|
||||
//This function forces instantiation of the singleton
|
||||
robust_emulation_helpers::robust_mutex_lock_file* dummy =
|
||||
&ipcdetail::intermodule_singleton
|
||||
<robust_emulation_helpers::robust_mutex_lock_file>::get();
|
||||
return dummy != 0;
|
||||
}
|
||||
|
||||
} //namespace ipcdetail{
|
||||
} //namespace interprocess{
|
||||
} //namespace boost{
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif
|
||||
511
test/external/boost/interprocess/detail/segment_manager_helper.hpp
vendored
Normal file
511
test/external/boost/interprocess/detail/segment_manager_helper.hpp
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
|
||||
#define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/in_place_interface.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
#include <string> //char_traits
|
||||
#include <new> //std::nothrow
|
||||
#include <utility> //std::pair
|
||||
#include <boost/assert.hpp> //BOOST_ASSERT
|
||||
#include <functional> //unary_function
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
#include <exception>
|
||||
#endif
|
||||
|
||||
//!\file
|
||||
//!Describes the object placed in a memory segment that provides
|
||||
//!named object allocation capabilities.
|
||||
|
||||
namespace boost{
|
||||
namespace interprocess{
|
||||
|
||||
template<class MemoryManager>
|
||||
class segment_manager_base;
|
||||
|
||||
//!An integer that describes the type of the
|
||||
//!instance constructed in memory
|
||||
enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type };
|
||||
|
||||
namespace ipcdetail{
|
||||
|
||||
template<class MemoryAlgorithm>
|
||||
class mem_algo_deallocator
|
||||
{
|
||||
void * m_ptr;
|
||||
MemoryAlgorithm & m_algo;
|
||||
|
||||
public:
|
||||
mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo)
|
||||
: m_ptr(ptr), m_algo(algo)
|
||||
{}
|
||||
|
||||
void release()
|
||||
{ m_ptr = 0; }
|
||||
|
||||
~mem_algo_deallocator()
|
||||
{ if(m_ptr) m_algo.deallocate(m_ptr); }
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template<class size_type>
|
||||
struct block_header
|
||||
{
|
||||
size_type m_value_bytes;
|
||||
unsigned short m_num_char;
|
||||
unsigned char m_value_alignment;
|
||||
unsigned char m_alloc_type_sizeof_char;
|
||||
|
||||
block_header(size_type value_bytes
|
||||
,size_type value_alignment
|
||||
,unsigned char alloc_type
|
||||
,std::size_t sizeof_char
|
||||
,std::size_t num_char
|
||||
)
|
||||
: m_value_bytes(value_bytes)
|
||||
, m_num_char((unsigned short)num_char)
|
||||
, m_value_alignment((unsigned char)value_alignment)
|
||||
, m_alloc_type_sizeof_char
|
||||
( (alloc_type << 5u) |
|
||||
((unsigned char)sizeof_char & 0x1F) )
|
||||
{};
|
||||
|
||||
|
||||
template<class T>
|
||||
block_header &operator= (const T& )
|
||||
{ return *this; }
|
||||
|
||||
size_type total_size() const
|
||||
{
|
||||
if(alloc_type() != anonymous_type){
|
||||
return name_offset() + (m_num_char+1)*sizeof_char();
|
||||
}
|
||||
else{
|
||||
return this->value_offset() + m_value_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
size_type value_bytes() const
|
||||
{ return m_value_bytes; }
|
||||
|
||||
template<class Header>
|
||||
size_type total_size_with_header() const
|
||||
{
|
||||
return get_rounded_size
|
||||
( size_type(sizeof(Header))
|
||||
, size_type(::boost::alignment_of<block_header<size_type> >::value))
|
||||
+ total_size();
|
||||
}
|
||||
|
||||
unsigned char alloc_type() const
|
||||
{ return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; }
|
||||
|
||||
unsigned char sizeof_char() const
|
||||
{ return m_alloc_type_sizeof_char & (unsigned char)0x1F; }
|
||||
|
||||
template<class CharType>
|
||||
CharType *name() const
|
||||
{
|
||||
return const_cast<CharType*>(reinterpret_cast<const CharType*>
|
||||
(reinterpret_cast<const char*>(this) + name_offset()));
|
||||
}
|
||||
|
||||
unsigned short name_length() const
|
||||
{ return m_num_char; }
|
||||
|
||||
size_type name_offset() const
|
||||
{
|
||||
return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char()));
|
||||
}
|
||||
|
||||
void *value() const
|
||||
{
|
||||
return const_cast<char*>((reinterpret_cast<const char*>(this) + this->value_offset()));
|
||||
}
|
||||
|
||||
size_type value_offset() const
|
||||
{
|
||||
return get_rounded_size(size_type(sizeof(block_header<size_type>)), size_type(m_value_alignment));
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool less_comp(const block_header<size_type> &b) const
|
||||
{
|
||||
return m_num_char < b.m_num_char ||
|
||||
(m_num_char < b.m_num_char &&
|
||||
std::char_traits<CharType>::compare
|
||||
(name<CharType>(), b.name<CharType>(), m_num_char) < 0);
|
||||
}
|
||||
|
||||
template<class CharType>
|
||||
bool equal_comp(const block_header<size_type> &b) const
|
||||
{
|
||||
return m_num_char == b.m_num_char &&
|
||||
std::char_traits<CharType>::compare
|
||||
(name<CharType>(), b.name<CharType>(), m_num_char) == 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static block_header<size_type> *block_header_from_value(T *value)
|
||||
{ return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value); }
|
||||
|
||||
static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
|
||||
{
|
||||
block_header * hdr =
|
||||
const_cast<block_header*>
|
||||
(reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) -
|
||||
get_rounded_size(sizeof(block_header), algn)));
|
||||
(void)sz;
|
||||
//Some sanity checks
|
||||
BOOST_ASSERT(hdr->m_value_alignment == algn);
|
||||
BOOST_ASSERT(hdr->m_value_bytes % sz == 0);
|
||||
return hdr;
|
||||
}
|
||||
|
||||
template<class Header>
|
||||
static block_header<size_type> *from_first_header(Header *header)
|
||||
{
|
||||
block_header<size_type> * hdr =
|
||||
reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) +
|
||||
get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
|
||||
//Some sanity checks
|
||||
return hdr;
|
||||
}
|
||||
|
||||
template<class Header>
|
||||
static Header *to_first_header(block_header<size_type> *bheader)
|
||||
{
|
||||
Header * hdr =
|
||||
reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) -
|
||||
get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value)));
|
||||
//Some sanity checks
|
||||
return hdr;
|
||||
}
|
||||
};
|
||||
|
||||
inline void array_construct(void *mem, std::size_t num, ipcdetail::in_place_interface &table)
|
||||
{
|
||||
//Try constructors
|
||||
std::size_t constructed = 0;
|
||||
BOOST_TRY{
|
||||
table.construct_n(mem, num, constructed);
|
||||
}
|
||||
//If there is an exception call destructors and erase index node
|
||||
BOOST_CATCH(...){
|
||||
std::size_t destroyed = 0;
|
||||
table.destroy_n(mem, constructed, destroyed);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
|
||||
template<class CharT>
|
||||
struct intrusive_compare_key
|
||||
{
|
||||
typedef CharT char_type;
|
||||
|
||||
intrusive_compare_key(const CharT *str, std::size_t len)
|
||||
: mp_str(str), m_len(len)
|
||||
{}
|
||||
|
||||
const CharT * mp_str;
|
||||
std::size_t m_len;
|
||||
};
|
||||
|
||||
//!This struct indicates an anonymous object creation
|
||||
//!allocation
|
||||
template<instance_type type>
|
||||
class instance_t
|
||||
{
|
||||
instance_t(){}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct char_if_void
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct char_if_void<void>
|
||||
{
|
||||
typedef char type;
|
||||
};
|
||||
|
||||
typedef instance_t<anonymous_type> anonymous_instance_t;
|
||||
typedef instance_t<unique_type> unique_instance_t;
|
||||
|
||||
|
||||
template<class Hook, class CharType, class SizeType>
|
||||
struct intrusive_value_type_impl
|
||||
: public Hook
|
||||
{
|
||||
private:
|
||||
//Non-copyable
|
||||
intrusive_value_type_impl(const intrusive_value_type_impl &);
|
||||
intrusive_value_type_impl& operator=(const intrusive_value_type_impl &);
|
||||
|
||||
public:
|
||||
typedef CharType char_type;
|
||||
typedef SizeType size_type;
|
||||
|
||||
intrusive_value_type_impl(){}
|
||||
|
||||
enum { BlockHdrAlignment = ::boost::alignment_of<block_header<size_type> >::value };
|
||||
|
||||
block_header<size_type> *get_block_header() const
|
||||
{
|
||||
return const_cast<block_header<size_type>*>
|
||||
(reinterpret_cast<const block_header<size_type> *>(reinterpret_cast<const char*>(this) +
|
||||
::boost::interprocess::ipcdetail::get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
|
||||
}
|
||||
|
||||
bool operator <(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
|
||||
{ return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header()); }
|
||||
|
||||
bool operator ==(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
|
||||
{ return (this->get_block_header())->template equal_comp<CharType>(*other.get_block_header()); }
|
||||
|
||||
static intrusive_value_type_impl *get_intrusive_value_type(block_header<size_type> *hdr)
|
||||
{
|
||||
return reinterpret_cast<intrusive_value_type_impl *>(reinterpret_cast<char*>(hdr) -
|
||||
get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
|
||||
}
|
||||
|
||||
CharType *name() const
|
||||
{ return get_block_header()->template name<CharType>(); }
|
||||
|
||||
unsigned short name_length() const
|
||||
{ return get_block_header()->name_length(); }
|
||||
|
||||
void *value() const
|
||||
{ return get_block_header()->value(); }
|
||||
};
|
||||
|
||||
template<class CharType>
|
||||
class char_ptr_holder
|
||||
{
|
||||
public:
|
||||
char_ptr_holder(const CharType *name)
|
||||
: m_name(name)
|
||||
{}
|
||||
|
||||
char_ptr_holder(const ipcdetail::anonymous_instance_t *)
|
||||
: m_name(static_cast<CharType*>(0))
|
||||
{}
|
||||
|
||||
char_ptr_holder(const ipcdetail::unique_instance_t *)
|
||||
: m_name(reinterpret_cast<CharType*>(-1))
|
||||
{}
|
||||
|
||||
operator const CharType *()
|
||||
{ return m_name; }
|
||||
|
||||
private:
|
||||
const CharType *m_name;
|
||||
};
|
||||
|
||||
//!The key of the the named allocation information index. Stores an offset pointer
|
||||
//!to a null terminated string and the length of the string to speed up sorting
|
||||
template<class CharT, class VoidPointer>
|
||||
struct index_key
|
||||
{
|
||||
typedef typename boost::
|
||||
pointer_to_other<VoidPointer, const CharT>::type const_char_ptr_t;
|
||||
typedef CharT char_type;
|
||||
typedef typename std::iterator_traits<const_char_ptr_t>::difference_type difference_type;
|
||||
typedef typename boost::make_unsigned<difference_type>::type size_type;
|
||||
|
||||
private:
|
||||
//Offset pointer to the object's name
|
||||
const_char_ptr_t mp_str;
|
||||
//Length of the name buffer (null NOT included)
|
||||
size_type m_len;
|
||||
public:
|
||||
|
||||
//!Constructor of the key
|
||||
index_key (const char_type *name, size_type length)
|
||||
: mp_str(name), m_len(length) {}
|
||||
|
||||
//!Less than function for index ordering
|
||||
bool operator < (const index_key & right) const
|
||||
{
|
||||
return (m_len < right.m_len) ||
|
||||
(m_len == right.m_len &&
|
||||
std::char_traits<char_type>::compare
|
||||
(ipcdetail::get_pointer(mp_str)
|
||||
,ipcdetail::get_pointer(right.mp_str), m_len) < 0);
|
||||
}
|
||||
|
||||
//!Equal to function for index ordering
|
||||
bool operator == (const index_key & right) const
|
||||
{
|
||||
return m_len == right.m_len &&
|
||||
std::char_traits<char_type>::compare
|
||||
(ipcdetail::get_pointer(mp_str),
|
||||
ipcdetail::get_pointer(right.mp_str), m_len) == 0;
|
||||
}
|
||||
|
||||
void name(const CharT *name)
|
||||
{ mp_str = name; }
|
||||
|
||||
void name_length(size_type len)
|
||||
{ m_len = len; }
|
||||
|
||||
const CharT *name() const
|
||||
{ return ipcdetail::get_pointer(mp_str); }
|
||||
|
||||
size_type name_length() const
|
||||
{ return m_len; }
|
||||
};
|
||||
|
||||
//!The index_data stores a pointer to a buffer and the element count needed
|
||||
//!to know how many destructors must be called when calling destroy
|
||||
template<class VoidPointer>
|
||||
struct index_data
|
||||
{
|
||||
typedef VoidPointer void_pointer;
|
||||
void_pointer m_ptr;
|
||||
index_data(void *ptr) : m_ptr(ptr){}
|
||||
|
||||
void *value() const
|
||||
{ return static_cast<void*>(ipcdetail::get_pointer(m_ptr)); }
|
||||
};
|
||||
|
||||
template<class MemoryAlgorithm>
|
||||
struct segment_manager_base_type
|
||||
{ typedef segment_manager_base<MemoryAlgorithm> type; };
|
||||
|
||||
template<class CharT, class MemoryAlgorithm>
|
||||
struct index_config
|
||||
{
|
||||
typedef typename MemoryAlgorithm::void_pointer void_pointer;
|
||||
typedef CharT char_type;
|
||||
typedef ipcdetail::index_key<CharT, void_pointer> key_type;
|
||||
typedef ipcdetail::index_data<void_pointer> mapped_type;
|
||||
typedef typename segment_manager_base_type
|
||||
<MemoryAlgorithm>::type segment_manager_base;
|
||||
|
||||
template<class HeaderBase>
|
||||
struct intrusive_value_type
|
||||
{ typedef ipcdetail::intrusive_value_type_impl<HeaderBase, CharT, typename segment_manager_base::size_type> type; };
|
||||
|
||||
typedef intrusive_compare_key<CharT> intrusive_compare_key_type;
|
||||
};
|
||||
|
||||
template<class Iterator, bool intrusive>
|
||||
class segment_manager_iterator_value_adaptor
|
||||
{
|
||||
typedef typename Iterator::value_type iterator_val_t;
|
||||
typedef typename iterator_val_t::char_type char_type;
|
||||
|
||||
public:
|
||||
segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
|
||||
: m_val(&val)
|
||||
{}
|
||||
|
||||
const char_type *name() const
|
||||
{ return m_val->name(); }
|
||||
|
||||
unsigned short name_length() const
|
||||
{ return m_val->name_length(); }
|
||||
|
||||
const void *value() const
|
||||
{ return m_val->value(); }
|
||||
|
||||
const typename Iterator::value_type *m_val;
|
||||
};
|
||||
|
||||
|
||||
template<class Iterator>
|
||||
class segment_manager_iterator_value_adaptor<Iterator, false>
|
||||
{
|
||||
typedef typename Iterator::value_type iterator_val_t;
|
||||
typedef typename iterator_val_t::first_type first_type;
|
||||
typedef typename iterator_val_t::second_type second_type;
|
||||
typedef typename first_type::char_type char_type;
|
||||
typedef typename first_type::size_type size_type;
|
||||
|
||||
public:
|
||||
segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
|
||||
: m_val(&val)
|
||||
{}
|
||||
|
||||
const char_type *name() const
|
||||
{ return m_val->first.name(); }
|
||||
|
||||
size_type name_length() const
|
||||
{ return m_val->first.name_length(); }
|
||||
|
||||
const void *value() const
|
||||
{
|
||||
return reinterpret_cast<block_header<size_type>*>
|
||||
(ipcdetail::get_pointer(m_val->second.m_ptr))->value();
|
||||
}
|
||||
|
||||
const typename Iterator::value_type *m_val;
|
||||
};
|
||||
|
||||
template<class Iterator, bool intrusive>
|
||||
struct segment_manager_iterator_transform
|
||||
: std::unary_function< typename Iterator::value_type
|
||||
, segment_manager_iterator_value_adaptor<Iterator, intrusive> >
|
||||
{
|
||||
typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type;
|
||||
|
||||
result_type operator()(const typename Iterator::value_type &arg) const
|
||||
{ return result_type(arg); }
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
//These pointers are the ones the user will use to
|
||||
//indicate previous allocation types
|
||||
static const ipcdetail::anonymous_instance_t * anonymous_instance = 0;
|
||||
static const ipcdetail::unique_instance_t * unique_instance = 0;
|
||||
|
||||
namespace ipcdetail_really_deep_namespace {
|
||||
|
||||
//Otherwise, gcc issues a warning of previously defined
|
||||
//anonymous_instance and unique_instance
|
||||
struct dummy
|
||||
{
|
||||
dummy()
|
||||
{
|
||||
(void)anonymous_instance;
|
||||
(void)unique_instance;
|
||||
}
|
||||
};
|
||||
|
||||
} //detail_really_deep_namespace
|
||||
|
||||
}} //namespace boost { namespace interprocess
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
|
||||
|
||||
173
test/external/boost/interprocess/detail/tmp_dir_helpers.hpp
vendored
Normal file
173
test/external/boost/interprocess/detail/tmp_dir_helpers.hpp
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2007-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/errors.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <string>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
//#define BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME
|
||||
//#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
//#include <boost/interprocess/detail/win32_api.hpp>
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
|
||||
//#include <sys/sysctl.h>
|
||||
//#if defined(CTL_KERN) && defined (KERN_BOOTTIME)
|
||||
//#define BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME
|
||||
//#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
#if defined (BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME)
|
||||
inline void get_bootstamp(std::string &s, bool add = false)
|
||||
{
|
||||
std::string bootstamp;
|
||||
winapi::get_last_bootup_time(bootstamp);
|
||||
if(add){
|
||||
s += bootstamp;
|
||||
}
|
||||
else{
|
||||
s = bootstamp;
|
||||
}
|
||||
}
|
||||
#elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)
|
||||
inline void get_bootstamp(std::string &s, bool add = false)
|
||||
{
|
||||
// FreeBSD specific: sysctl "kern.boottime"
|
||||
int request[2] = { CTL_KERN, KERN_BOOTTIME };
|
||||
struct ::timeval result;
|
||||
std::size_t result_len = sizeof result;
|
||||
|
||||
if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0)
|
||||
return;
|
||||
|
||||
char bootstamp_str[256];
|
||||
|
||||
const char Characters [] =
|
||||
{ '0', '1', '2', '3', '4', '5', '6', '7'
|
||||
, '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
std::size_t char_counter = 0;
|
||||
long long fields[2] = { result.tv_sec, result.tv_usec };
|
||||
for(std::size_t field = 0; field != 2; ++field){
|
||||
for(std::size_t i = 0; i != sizeof(long long); ++i){
|
||||
const char *ptr = (const char *)&fields[field];
|
||||
bootstamp_str[char_counter++] = Characters[(ptr[i]&0xF0)>>4];
|
||||
bootstamp_str[char_counter++] = Characters[(ptr[i]&0x0F)];
|
||||
}
|
||||
}
|
||||
bootstamp_str[char_counter] = 0;
|
||||
if(add){
|
||||
s += bootstamp_str;
|
||||
}
|
||||
else{
|
||||
s = bootstamp_str;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void get_tmp_base_dir(std::string &tmp_name)
|
||||
{
|
||||
#if defined (BOOST_INTERPROCESS_WINDOWS)
|
||||
winapi::get_shared_documents_folder(tmp_name);
|
||||
if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){
|
||||
tmp_name = get_temporary_path();
|
||||
}
|
||||
#else
|
||||
tmp_name = get_temporary_path();
|
||||
#endif
|
||||
if(tmp_name.empty()){
|
||||
error_info err = system_error_code();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
//Remove final null.
|
||||
tmp_name += "/boost_interprocess";
|
||||
}
|
||||
|
||||
inline void tmp_folder(std::string &tmp_name)
|
||||
{
|
||||
get_tmp_base_dir(tmp_name);
|
||||
#ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
tmp_name += "/";
|
||||
get_bootstamp(tmp_name, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void tmp_filename(const char *filename, std::string &tmp_name)
|
||||
{
|
||||
tmp_folder(tmp_name);
|
||||
tmp_name += "/";
|
||||
tmp_name += filename;
|
||||
}
|
||||
|
||||
inline void create_tmp_and_clean_old(std::string &tmp_name)
|
||||
{
|
||||
//First get the temp directory
|
||||
std::string root_tmp_name;
|
||||
get_tmp_base_dir(root_tmp_name);
|
||||
|
||||
//If fails, check that it's because already exists
|
||||
if(!create_directory(root_tmp_name.c_str())){
|
||||
error_info info(system_error_code());
|
||||
if(info.get_error_code() != already_exists_error){
|
||||
throw interprocess_exception(info);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
|
||||
tmp_folder(tmp_name);
|
||||
|
||||
//If fails, check that it's because already exists
|
||||
if(!create_directory(tmp_name.c_str())){
|
||||
error_info info(system_error_code());
|
||||
if(info.get_error_code() != already_exists_error){
|
||||
throw interprocess_exception(info);
|
||||
}
|
||||
}
|
||||
//Now erase all old directories created in the previous boot sessions
|
||||
std::string subdir = tmp_name;
|
||||
subdir.erase(0, root_tmp_name.size()+1);
|
||||
delete_subdirectories(root_tmp_name, subdir.c_str());
|
||||
#else
|
||||
tmp_name = root_tmp_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
|
||||
{
|
||||
create_tmp_and_clean_old(tmp_name);
|
||||
tmp_name += "/";
|
||||
tmp_name += filename;
|
||||
}
|
||||
|
||||
inline void add_leading_slash(const char *name, std::string &new_name)
|
||||
{
|
||||
if(name[0] != '/'){
|
||||
new_name = '/';
|
||||
}
|
||||
new_name += name;
|
||||
}
|
||||
|
||||
} //namespace boost{
|
||||
} //namespace interprocess {
|
||||
} //namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP
|
||||
195
test/external/boost/interprocess/detail/transform_iterator.hpp
vendored
Normal file
195
test/external/boost/interprocess/detail/transform_iterator.hpp
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
|
||||
#include <iterator>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
template <class PseudoReference>
|
||||
struct operator_arrow_proxy
|
||||
{
|
||||
operator_arrow_proxy(const PseudoReference &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
PseudoReference* operator->() const { return &m_value; }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
mutable PseudoReference m_value;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct operator_arrow_proxy<T&>
|
||||
{
|
||||
operator_arrow_proxy(T &px)
|
||||
: m_value(px)
|
||||
{}
|
||||
|
||||
T* operator->() const { return const_cast<T*>(&m_value); }
|
||||
// This function is needed for MWCW and BCC, which won't call operator->
|
||||
// again automatically per 13.3.1.2 para 8
|
||||
// operator T*() const { return &m_value; }
|
||||
T &m_value;
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunction>
|
||||
class transform_iterator
|
||||
: public UnaryFunction
|
||||
, public std::iterator
|
||||
< typename Iterator::iterator_category
|
||||
, typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type
|
||||
, typename Iterator::difference_type
|
||||
, operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
, typename UnaryFunction::result_type>
|
||||
{
|
||||
public:
|
||||
explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
|
||||
: UnaryFunction(f), m_it(it)
|
||||
{}
|
||||
|
||||
explicit transform_iterator()
|
||||
: UnaryFunction(), m_it()
|
||||
{}
|
||||
|
||||
//Constructors
|
||||
transform_iterator& operator++()
|
||||
{ increment(); return *this; }
|
||||
|
||||
transform_iterator operator++(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
increment();
|
||||
return result;
|
||||
}
|
||||
|
||||
transform_iterator& operator--()
|
||||
{ decrement(); return *this; }
|
||||
|
||||
transform_iterator operator--(int)
|
||||
{
|
||||
transform_iterator result (*this);
|
||||
decrement();
|
||||
return result;
|
||||
}
|
||||
|
||||
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i.equal(i2); }
|
||||
|
||||
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i == i2); }
|
||||
|
||||
friend bool operator< (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i < i2; }
|
||||
|
||||
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2 < i; }
|
||||
|
||||
friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i > i2); }
|
||||
|
||||
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return !(i < i2); }
|
||||
|
||||
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
|
||||
{ return i2.distance_to(i); }
|
||||
|
||||
//Arithmetic
|
||||
transform_iterator& operator+=(typename Iterator::difference_type off)
|
||||
{ this->advance(off); return *this; }
|
||||
|
||||
transform_iterator operator+(typename Iterator::difference_type off) const
|
||||
{
|
||||
transform_iterator other(*this);
|
||||
other.advance(off);
|
||||
return other;
|
||||
}
|
||||
|
||||
friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
|
||||
{ return right + off; }
|
||||
|
||||
transform_iterator& operator-=(typename Iterator::difference_type off)
|
||||
{ this->advance(-off); return *this; }
|
||||
|
||||
transform_iterator operator-(typename Iterator::difference_type off) const
|
||||
{ return *this + (-off); }
|
||||
|
||||
typename UnaryFunction::result_type operator*() const
|
||||
{ return dereference(); }
|
||||
|
||||
typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const
|
||||
{ return UnaryFunction::operator()(m_it[off]); }
|
||||
|
||||
operator_arrow_proxy<typename UnaryFunction::result_type>
|
||||
operator->() const
|
||||
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
|
||||
|
||||
Iterator & base()
|
||||
{ return m_it; }
|
||||
|
||||
const Iterator & base() const
|
||||
{ return m_it; }
|
||||
|
||||
private:
|
||||
Iterator m_it;
|
||||
|
||||
void increment()
|
||||
{ ++m_it; }
|
||||
|
||||
void decrement()
|
||||
{ --m_it; }
|
||||
|
||||
bool equal(const transform_iterator &other) const
|
||||
{ return m_it == other.m_it; }
|
||||
|
||||
bool less(const transform_iterator &other) const
|
||||
{ return other.m_it < m_it; }
|
||||
|
||||
typename UnaryFunction::result_type dereference() const
|
||||
{ return UnaryFunction::operator()(*m_it); }
|
||||
|
||||
void advance(typename Iterator::difference_type n)
|
||||
{ std::advance(m_it, n); }
|
||||
|
||||
typename Iterator::difference_type distance_to(const transform_iterator &other)const
|
||||
{ return std::distance(other.m_it, m_it); }
|
||||
};
|
||||
|
||||
template <class Iterator, class UnaryFunc>
|
||||
transform_iterator<Iterator, UnaryFunc>
|
||||
make_transform_iterator(Iterator it, UnaryFunc fun)
|
||||
{
|
||||
return transform_iterator<Iterator, UnaryFunc>(it, fun);
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP
|
||||
|
||||
122
test/external/boost/interprocess/detail/type_traits.hpp
vendored
Normal file
122
test/external/boost/interprocess/detail/type_traits.hpp
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// (C) Copyright John Maddock 2000.
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
struct nat{};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct remove_reference<T&>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_reference
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_reference<T&>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_pointer<T*>
|
||||
{
|
||||
enum { value = true };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct add_reference
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct add_reference<T&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_reference<void>
|
||||
{
|
||||
typedef nat &type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_reference<const void>
|
||||
{
|
||||
typedef const nat &type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct add_const_reference
|
||||
{ typedef const T &type; };
|
||||
|
||||
template <class T>
|
||||
struct add_const_reference<T&>
|
||||
{ typedef T& type; };
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same
|
||||
{
|
||||
typedef char yes_type;
|
||||
struct no_type
|
||||
{
|
||||
char padding[8];
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
static yes_type is_same_tester(V*, V*);
|
||||
static no_type is_same_tester(...);
|
||||
|
||||
static T *t;
|
||||
static U *u;
|
||||
|
||||
static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u));
|
||||
};
|
||||
|
||||
} // namespace ipcdetail
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
174
test/external/boost/interprocess/detail/utilities.hpp
vendored
Normal file
174
test/external/boost/interprocess/detail/utilities.hpp
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009.
|
||||
// (C) Copyright Gennaro Prota 2003 - 2004.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <boost/type_traits/has_trivial_destructor.hpp>
|
||||
#include <boost/interprocess/detail/min_max.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <boost/interprocess/detail/transform_iterator.hpp>
|
||||
#include <boost/interprocess/detail/mpl.hpp>
|
||||
#include <boost/interprocess/containers/version_type.hpp>
|
||||
#include <boost/interprocess/detail/move.hpp>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<class SmartPtr>
|
||||
struct smart_ptr_type
|
||||
{
|
||||
typedef typename SmartPtr::value_type value_type;
|
||||
typedef value_type *pointer;
|
||||
static pointer get (const SmartPtr &smartptr)
|
||||
{ return smartptr.get();}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct smart_ptr_type<T*>
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef value_type *pointer;
|
||||
static pointer get (pointer ptr)
|
||||
{ return ptr;}
|
||||
};
|
||||
|
||||
//!Overload for smart pointers to avoid ADL problems with get_pointer
|
||||
template<class Ptr>
|
||||
inline typename smart_ptr_type<Ptr>::pointer
|
||||
get_pointer(const Ptr &ptr)
|
||||
{ return smart_ptr_type<Ptr>::get(ptr); }
|
||||
|
||||
//!To avoid ADL problems with swap
|
||||
template <class T>
|
||||
inline void do_swap(T& x, T& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(x, y);
|
||||
}
|
||||
|
||||
//Rounds "orig_size" by excess to round_to bytes
|
||||
template<class SizeType>
|
||||
inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to)
|
||||
{
|
||||
return ((orig_size-1)/round_to+1)*round_to;
|
||||
}
|
||||
|
||||
//Truncates "orig_size" to a multiple of "multiple" bytes.
|
||||
template<class SizeType>
|
||||
inline SizeType get_truncated_size(SizeType orig_size, SizeType multiple)
|
||||
{
|
||||
return orig_size/multiple*multiple;
|
||||
}
|
||||
|
||||
//Rounds "orig_size" by excess to round_to bytes. round_to must be power of two
|
||||
template<class SizeType>
|
||||
inline SizeType get_rounded_size_po2(SizeType orig_size, SizeType round_to)
|
||||
{
|
||||
return ((orig_size-1)&(~(round_to-1))) + round_to;
|
||||
}
|
||||
|
||||
//Truncates "orig_size" to a multiple of "multiple" bytes. multiple must be power of two
|
||||
template<class SizeType>
|
||||
inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple)
|
||||
{
|
||||
return (orig_size & (~(multiple-1)));
|
||||
}
|
||||
|
||||
template <std::size_t OrigSize, std::size_t RoundTo>
|
||||
struct ct_rounded_size
|
||||
{
|
||||
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
|
||||
};
|
||||
|
||||
// Gennaro Prota wrote this. Thanks!
|
||||
template <int p, int n = 4>
|
||||
struct ct_max_pow2_less
|
||||
{
|
||||
enum { c = 2*n < p };
|
||||
|
||||
static const std::size_t value =
|
||||
c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ct_max_pow2_less<0, 0>
|
||||
{
|
||||
static const std::size_t value = 0;
|
||||
};
|
||||
|
||||
} //namespace ipcdetail {
|
||||
|
||||
//!Trait class to detect if an index is a node
|
||||
//!index. This allows more efficient operations
|
||||
//!when deallocating named objects.
|
||||
template <class Index>
|
||||
struct is_node_index
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
//!Trait class to detect if an index is an intrusive
|
||||
//!index. This will embed the derivation hook in each
|
||||
//!allocation header, to provide memory for the intrusive
|
||||
//!container.
|
||||
template <class Index>
|
||||
struct is_intrusive_index
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template <typename T> T*
|
||||
addressof(T& v)
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
//Anti-exception node eraser
|
||||
template<class Cont>
|
||||
class value_eraser
|
||||
{
|
||||
public:
|
||||
value_eraser(Cont & cont, typename Cont::iterator it)
|
||||
: m_cont(cont), m_index_it(it), m_erase(true){}
|
||||
~value_eraser()
|
||||
{ if(m_erase) m_cont.erase(m_index_it); }
|
||||
|
||||
void release() { m_erase = false; }
|
||||
|
||||
private:
|
||||
Cont &m_cont;
|
||||
typename Cont::iterator m_index_it;
|
||||
bool m_erase;
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP
|
||||
|
||||
153
test/external/boost/interprocess/detail/variadic_templates_tools.hpp
vendored
Normal file
153
test/external/boost/interprocess/detail/variadic_templates_tools.hpp
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2008-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/type_traits.hpp>
|
||||
#include <cstddef> //std::size_t
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace ipcdetail {
|
||||
|
||||
template<typename... Values>
|
||||
class tuple;
|
||||
|
||||
template<> class tuple<>
|
||||
{};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
class tuple<Head, Tail...>
|
||||
: private tuple<Tail...>
|
||||
{
|
||||
typedef tuple<Tail...> inherited;
|
||||
|
||||
public:
|
||||
tuple() { }
|
||||
|
||||
// implicit copy-constructor is okay
|
||||
// Construct tuple from separate arguments.
|
||||
tuple(typename add_const_reference<Head>::type v,
|
||||
typename add_const_reference<Tail>::type... vtail)
|
||||
: inherited(vtail...), m_head(v)
|
||||
{}
|
||||
|
||||
// Construct tuple from another tuple.
|
||||
template<typename... VValues>
|
||||
tuple(const tuple<VValues...>& other)
|
||||
: m_head(other.head()), inherited(other.tail())
|
||||
{}
|
||||
|
||||
template<typename... VValues>
|
||||
tuple& operator=(const tuple<VValues...>& other)
|
||||
{
|
||||
m_head = other.head();
|
||||
tail() = other.tail();
|
||||
return this;
|
||||
}
|
||||
|
||||
typename add_reference<Head>::type head() { return m_head; }
|
||||
typename add_reference<const Head>::type head() const { return m_head; }
|
||||
|
||||
inherited& tail() { return *this; }
|
||||
const inherited& tail() const { return *this; }
|
||||
|
||||
protected:
|
||||
Head m_head;
|
||||
};
|
||||
|
||||
|
||||
template<typename... Values>
|
||||
tuple<Values&&...> tie_forward(Values&&... values)
|
||||
{ return tuple<Values&&...>(values...); }
|
||||
|
||||
template<int I, typename Tuple>
|
||||
struct tuple_element;
|
||||
|
||||
template<int I, typename Head, typename... Tail>
|
||||
struct tuple_element<I, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
|
||||
};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
struct tuple_element<0, tuple<Head, Tail...> >
|
||||
{
|
||||
typedef Head type;
|
||||
};
|
||||
|
||||
template<int I, typename Tuple>
|
||||
class get_impl;
|
||||
|
||||
template<int I, typename Head, typename... Values>
|
||||
class get_impl<I, tuple<Head, Values...> >
|
||||
{
|
||||
typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
|
||||
typedef get_impl<I-1, tuple<Values...> > Next;
|
||||
|
||||
public:
|
||||
typedef typename add_reference<Element>::type type;
|
||||
typedef typename add_const_reference<Element>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
|
||||
};
|
||||
|
||||
template<typename Head, typename... Values>
|
||||
class get_impl<0, tuple<Head, Values...> >
|
||||
{
|
||||
public:
|
||||
typedef typename add_reference<Head>::type type;
|
||||
typedef typename add_const_reference<Head>::type const_type;
|
||||
static type get(tuple<Head, Values...>& t) { return t.head(); }
|
||||
static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
|
||||
};
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
template<int I, typename... Values>
|
||||
typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
|
||||
{ return get_impl<I, tuple<Values...> >::get(t); }
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
|
||||
// be used to "unpack" into comma-separated values
|
||||
// in a function call.
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
template<int... Indexes>
|
||||
struct index_tuple{};
|
||||
|
||||
template<std::size_t Num, typename Tuple = index_tuple<> >
|
||||
struct build_number_seq;
|
||||
|
||||
template<std::size_t Num, int... Indexes>
|
||||
struct build_number_seq<Num, index_tuple<Indexes...> >
|
||||
: build_number_seq<Num - 1, index_tuple<Indexes..., sizeof...(Indexes)> >
|
||||
{};
|
||||
|
||||
template<int... Indexes>
|
||||
struct build_number_seq<0, index_tuple<Indexes...> >
|
||||
{ typedef index_tuple<Indexes...> type; };
|
||||
|
||||
|
||||
}}} //namespace boost { namespace interprocess { namespace ipcdetail {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
|
||||
1736
test/external/boost/interprocess/detail/win32_api.hpp
vendored
Normal file
1736
test/external/boost/interprocess/detail/win32_api.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
148
test/external/boost/interprocess/detail/workaround.hpp
vendored
Normal file
148
test/external/boost/interprocess/detail/workaround.hpp
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
|
||||
#if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
|
||||
|
||||
#define BOOST_INTERPROCESS_WINDOWS
|
||||
|
||||
/*
|
||||
#if !defined(_MSC_EXTENSIONS)
|
||||
#error "Turn on Microsoft language extensions (_MSC_EXTENSIONS) to be able to call Windows API functions"
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
#if !(defined BOOST_INTERPROCESS_WINDOWS)
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#if ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0)
|
||||
//Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it.
|
||||
//Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work.
|
||||
# if !defined(__CYGWIN__) && !defined(__APPLE__)
|
||||
# define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_BARRIERS - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_BARRIERS
|
||||
# endif
|
||||
|
||||
#if ((_POSIX_SEMAPHORES - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
# if defined(__CYGWIN__)
|
||||
#define BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK
|
||||
# endif
|
||||
//Some platforms have a limited (name length) named semaphore support
|
||||
#elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__)
|
||||
# define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
#endif
|
||||
|
||||
#if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\
|
||||
((defined _V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\
|
||||
((defined _V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\
|
||||
((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\
|
||||
((defined _XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\
|
||||
((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\
|
||||
((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\
|
||||
((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))
|
||||
#define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T
|
||||
#else
|
||||
#endif
|
||||
|
||||
//Check for XSI shared memory objects. They are available in nearly all UNIX platforms
|
||||
#if !defined(__QNXNTO__)
|
||||
# define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_SHARED_MEMORY_OBJECTS - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
#else
|
||||
//VMS and MACOS don't define it but the have shm_open/close interface
|
||||
# if defined(__vms)
|
||||
# if __CRTL_VER >= 70200000
|
||||
# define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
# endif
|
||||
//Mac OS has some non-conformant features like names limited to SHM_NAME_MAX
|
||||
# elif defined (__APPLE__)
|
||||
// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
// # define BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS_NO_GROW
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//Now check if we have only XSI shared memory
|
||||
#if defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS) &&\
|
||||
!defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS)
|
||||
//# define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS_ONLY
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_TIMEOUTS - 0) > 0)
|
||||
# define BOOST_INTERPROCESS_POSIX_TIMEOUTS
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS
|
||||
//Some systems have filesystem-based resources, so the
|
||||
//portable "/shmname" format does not work due to permission issues
|
||||
//For those systems we need to form a path to a temporary directory:
|
||||
// hp-ux tru64 vms freebsd
|
||||
#if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7))
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
|
||||
#elif defined(__FreeBSD__)
|
||||
#define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES
|
||||
#if defined(__osf__) || defined(__vms)
|
||||
#define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SEMAPHORES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ((_POSIX_VERSION + 0)>= 200112L || (_XOPEN_VERSION + 0)>= 500)
|
||||
#define BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
|
||||
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
|
||||
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
|
||||
#endif
|
||||
|
||||
//Now declare some Boost.Interprocess features depending on the implementation
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
|
||||
|
||||
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES) && !defined(BOOST_INTERPROCESS_POSIX_SEMAPHORES_NO_UNLINK)
|
||||
|
||||
#define BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES
|
||||
#define BOOST_INTERPROCESS_NAMED_SEMAPHORE_USES_POSIX_SEMAPHORES
|
||||
|
||||
#endif
|
||||
|
||||
// Timeout duration use if BOOST_INTERPROCESS_ENABLE_TIMEOUT_WHEN_LOCKING is set
|
||||
#ifndef BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS
|
||||
#define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP
|
||||
392
test/external/boost/interprocess/detail/xsi_shared_memory_device.hpp
vendored
Normal file
392
test/external/boost/interprocess/detail/xsi_shared_memory_device.hpp
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2009-2010. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
|
||||
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if defined(BOOST_INTERPROCESS_WINDOWS)
|
||||
#error "This header can't be used in Windows operating systems"
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
|
||||
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||
#include <boost/interprocess/sync/xsi/xsi_named_mutex.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <cstddef>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
//!\file
|
||||
//!Describes a class representing a native xsi shared memory.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
class xsi_shared_memory_device
|
||||
{
|
||||
/// @cond
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
|
||||
xsi_shared_memory_device();
|
||||
|
||||
xsi_shared_memory_device(create_only_t, const char *name, mode_t mode, std::size_t size)
|
||||
{ this->priv_open_or_create_name_only(ipcdetail::DoCreate, name, mode, size); }
|
||||
|
||||
xsi_shared_memory_device(open_or_create_t, const char *name, mode_t mode, std::size_t size)
|
||||
{ this->priv_open_or_create_name_only(ipcdetail::DoOpenOrCreate, name, mode, size); }
|
||||
|
||||
xsi_shared_memory_device(open_only_t, const char *name, mode_t mode)
|
||||
{ this->priv_open_or_create_name_only(ipcdetail::DoOpen, name, mode, 0); }
|
||||
|
||||
xsi_shared_memory_device(create_only_t, const char *filepath, boost::uint8_t id, mode_t mode, std::size_t size)
|
||||
{ this->priv_open_or_create_name_id(ipcdetail::DoCreate, name, id, mode, size); }
|
||||
|
||||
xsi_shared_memory_device(open_or_create_t, const char *filepath, boost::uint8_t id, mode_t mode, std::size_t size)
|
||||
{ this->priv_open_or_create_name_id(ipcdetail::DoOpenOrCreate, id, name, mode, size); }
|
||||
|
||||
xsi_shared_memory_device(open_only_t, const char *filepath, boost::uint8_t id, mode_t mode)
|
||||
{ this->priv_open_or_create_name_id(ipcdetail::DoOpen, name, id, mode, 0); }
|
||||
|
||||
xsi_shared_memory_device(BOOST_RV_REF(xsi_shared_memory_device) moved)
|
||||
{ this->swap(moved); }
|
||||
|
||||
xsi_shared_memory_device &operator=(BOOST_RV_REF(xsi_shared_memory_device) moved)
|
||||
{
|
||||
xsi_shared_memory_device tmp(boost::interprocess::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps two xsi_shared_memory_device. Does not throw
|
||||
void swap(xsi_shared_memory_device &other);
|
||||
|
||||
//!Destroys *this. The shared memory won't be destroyed, just
|
||||
//!this connection to it. Use remove() to destroy the shared memory.
|
||||
~xsi_shared_memory_device();
|
||||
|
||||
//!Returns the name of the
|
||||
//!shared memory.
|
||||
const char *get_name() const;
|
||||
|
||||
//!Returns the shared memory ID that
|
||||
//!identifies the shared memory
|
||||
int get_shmid() const;
|
||||
|
||||
//!Returns access
|
||||
//!permissions
|
||||
mode_t get_mode() const;
|
||||
|
||||
//!Returns the mapping handle.
|
||||
//!Never throws
|
||||
mapping_handle_t get_mapping_handle() const;
|
||||
|
||||
//!Erases a XSI shared memory object identified by shmname
|
||||
//!from the system.
|
||||
//!Returns false on error. Never throws
|
||||
static bool remove(const char *shmname);
|
||||
|
||||
//!Erases the XSI shared memory object identified by shmid
|
||||
//!from the system.
|
||||
//!Returns false on error. Never throws
|
||||
static bool remove(int shmid);
|
||||
|
||||
/// @cond
|
||||
private:
|
||||
template<int Dummy>
|
||||
struct info_constants_t
|
||||
{
|
||||
static const std::size_t MaxName = 32;
|
||||
static const std::size_t FirstID = 2;
|
||||
static const std::size_t LastID = 256;
|
||||
static const std::size_t NumID = LastID - FirstID;
|
||||
};
|
||||
|
||||
struct info_t
|
||||
{
|
||||
struct names_t
|
||||
{
|
||||
char buf[info_constants_t<0>::MaxName];
|
||||
} names[info_constants_t<0>::NumID];
|
||||
};
|
||||
|
||||
static void priv_obtain_index(mapped_region &m, xsi_named_mutex &m, std::string &path);
|
||||
static bool priv_remove_dead_memory(info_t *info, const char *path);
|
||||
|
||||
bool priv_open_or_create_name_only( ipcdetail::create_enum_t type
|
||||
, const char *shmname
|
||||
, mode_t mode
|
||||
, std::size_t size);
|
||||
bool priv_open_or_create_name_id( ipcdetail::create_enum_t type
|
||||
, const char *shmname
|
||||
, boost::uint8_t id
|
||||
, mode_t mode
|
||||
, std::size_t size);
|
||||
xsi_shared_memory m_shm;
|
||||
mode_t m_mode;
|
||||
std::string m_name;
|
||||
/// @endcond
|
||||
};
|
||||
|
||||
template<int Dummy>
|
||||
const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::MaxName;
|
||||
|
||||
template<int Dummy>
|
||||
const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::FirstID;
|
||||
|
||||
template<int Dummy>
|
||||
const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::LastID;
|
||||
|
||||
template<int Dummy>
|
||||
const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::NumID;
|
||||
|
||||
/// @cond
|
||||
|
||||
inline xsi_shared_memory_device::xsi_shared_memory_device()
|
||||
: m_shm(), m_mode(invalid_mode), m_name()
|
||||
{}
|
||||
|
||||
inline xsi_shared_memory_device::~xsi_shared_memory_device()
|
||||
{}
|
||||
|
||||
inline const char *xsi_shared_memory_device::get_name() const
|
||||
{ return m_name.c_str(); }
|
||||
|
||||
inline void xsi_shared_memory_device::swap(xsi_shared_memory_device &other)
|
||||
{
|
||||
m_shm.swap(other.m_shm);
|
||||
std::swap(m_mode, other.m_mode);
|
||||
m_name.swap(other.m_name);
|
||||
}
|
||||
|
||||
inline mapping_handle_t xsi_shared_memory_device::get_mapping_handle() const
|
||||
{ return m_shm.get_mapping_handle(); }
|
||||
|
||||
inline mode_t xsi_shared_memory_device::get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
inline int xsi_shared_memory::get_shmid() const
|
||||
{ return m_shm.get_shmid(); }
|
||||
|
||||
inline void xsi_shared_memory_device::priv_obtain_index
|
||||
(mapped_region ®, xsi_named_mutex &mut, std::string &path)
|
||||
{
|
||||
const char *const filename = "xsi_shm_emulation_file";
|
||||
permissions p;
|
||||
p.set_unrestricted();
|
||||
std::string xsi_shm_emulation_file_path;
|
||||
ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, xsi_shm_emulation_file_path);
|
||||
ipcdetail::create_or_open_file(xsi_shm_emulation_file_path.c_str(), read_write, p);
|
||||
const std::size_t MemSize = sizeof(info_t);
|
||||
|
||||
xsi_shared_memory index_shm(open_or_create, xsi_shm_emulation_file_path.c_str(), 1, MemSize, 0666);
|
||||
mapped_region r(index_shm, read_write, 0, MemSize, 0);
|
||||
xsi_named_mutex m(open_or_create, xsi_shm_emulation_file_path.c_str(), 2, 0666);
|
||||
reg = boost::interprocess::move(r);
|
||||
mut = boost::interprocess::move(m);
|
||||
path.swap(xsi_shm_emulation_file_path);
|
||||
}
|
||||
|
||||
inline bool xsi_shared_memory_device::priv_remove_dead_memory
|
||||
(xsi_shared_memory_device::info_t *info, const char *path)
|
||||
{
|
||||
bool removed = false;
|
||||
for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
|
||||
if(info->names[i].buf[0]){
|
||||
try{
|
||||
xsi_shared_memory temp( open_only, path, i+info_constants_t<0>::FirstID, 0600);
|
||||
}
|
||||
catch(interprocess_exception &e){
|
||||
if(e.get_error_code() == not_found_error){
|
||||
std::memset(info->names[i].buf, 0, info_constants_t<0>::MaxName);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
inline bool xsi_shared_memory_device::priv_open_or_create_name_id
|
||||
(ipcdetail::create_enum_t type, const char *filepath, mode_t mode, std::size_t size)
|
||||
{
|
||||
//Set accesses
|
||||
if (mode != read_write && mode != read_only){
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
int perm = (mode == read_only) ? (0444) : (0666);
|
||||
|
||||
if(type == ipcdetail::DoOpen){
|
||||
if(!found){
|
||||
error_info err = not_found_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
xsi_shared_memory temp(open_only, filepath, id, perm);
|
||||
m_shm = boost::interprocess::move(temp);
|
||||
}
|
||||
else if(type == ipcdetail::DoCreate){
|
||||
//Try to reuse slot
|
||||
xsi_shared_memory temp(create_only, filepath, id, size, perm);
|
||||
std::strcpy(info->names[target_entry].buf, shmname);
|
||||
m_shm = boost::interprocess::move(temp);
|
||||
}
|
||||
else{ // if(type == ipcdetail::DoOpenOrCreate){
|
||||
xsi_shared_memory temp(open_or_create, filepath, id, size, perm);
|
||||
m_shm = boost::interprocess::move(temp);
|
||||
}
|
||||
|
||||
m_mode = mode;
|
||||
m_name.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool xsi_shared_memory_device::priv_open_or_create_name_only
|
||||
(ipcdetail::create_enum_t type, const char *shmname, mode_t mode, std::size_t size)
|
||||
{
|
||||
//Set accesses
|
||||
if (mode != read_write && mode != read_only){
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
if (std::strlen(shmname) >= (info_constants_t<0>::MaxName)){
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
{
|
||||
//Obtain index and index lock
|
||||
mapped_region region;
|
||||
xsi_named_mutex mut;
|
||||
std::string xsi_shm_emulation_file_path;
|
||||
priv_obtain_index(region, mut, xsi_shm_emulation_file_path);
|
||||
info_t *info = static_cast<info_t *>(region.get_address());
|
||||
scoped_lock<xsi_named_mutex> lock(mut);
|
||||
|
||||
//Find the correct entry or the first empty index
|
||||
bool found = false;
|
||||
int target_entry = -1;
|
||||
int tries = 2;
|
||||
while(tries--){
|
||||
for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
|
||||
if(target_entry < 0 && !info->names[i].buf[0]){
|
||||
target_entry = static_cast<int>(i);
|
||||
}
|
||||
else if(0 == std::strcmp(info->names[i].buf, shmname)){
|
||||
found = true;
|
||||
target_entry = static_cast<int>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(target_entry < 0){
|
||||
if(!tries || !priv_remove_dead_memory(info, xsi_shm_emulation_file_path.c_str())){
|
||||
error_info err = out_of_resource_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Now handle the result
|
||||
int perm = (mode == read_only) ? (0444) : (0666);
|
||||
if(type == ipcdetail::DoOpen){
|
||||
if(!found){
|
||||
error_info err = not_found_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
xsi_shared_memory temp( open_only, xsi_shm_emulation_file_path.c_str()
|
||||
, target_entry+info_constants_t<0>::FirstID, perm);
|
||||
m_shm = boost::interprocess::move(temp);
|
||||
}
|
||||
else{
|
||||
|
||||
if(type == ipcdetail::DoCreate){
|
||||
//Try to reuse slot
|
||||
xsi_shared_memory temp( create_only, xsi_shm_emulation_file_path.c_str()
|
||||
, target_entry+info_constants_t<0>::FirstID, size, perm);
|
||||
std::strcpy(info->names[target_entry].buf, shmname);
|
||||
m_shm = boost::interprocess::move(temp);
|
||||
}
|
||||
else{ // if(type == ipcdetail::DoOpenOrCreate){
|
||||
xsi_shared_memory temp( open_or_create, xsi_shm_emulation_file_path.c_str()
|
||||
, target_entry+info_constants_t<0>::FirstID, size, perm);
|
||||
if(!found){
|
||||
std::memset(info->names[target_entry].buf, 0, info_constants_t<0>::MaxName);
|
||||
std::strcpy(info->names[target_entry].buf, shmname);
|
||||
}
|
||||
m_shm = boost::interprocess::move(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mode = mode;
|
||||
m_name = shmname;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool xsi_shared_memory_device::remove(const char *shmname)
|
||||
{
|
||||
try{
|
||||
//Obtain index and index lockss
|
||||
mapped_region region;
|
||||
xsi_named_mutex mut;
|
||||
std::string xsi_shm_emulation_file_path;
|
||||
priv_obtain_index(region, mut, xsi_shm_emulation_file_path);
|
||||
scoped_lock<xsi_named_mutex> lock(mut);
|
||||
info_t *info = static_cast<info_t *>(region.get_address());
|
||||
|
||||
//Now check and remove
|
||||
bool removed = false;
|
||||
|
||||
for(std::size_t i = 0; i != info_constants_t<0>::NumID; ++i){
|
||||
if(0 == std::strcmp(info->names[i].buf, name)){
|
||||
xsi_shared_memory temp( open_only, xsi_shm_emulation_file_path.c_str()
|
||||
, i+info_constants_t<0>::FirstID);
|
||||
if(!xsi_shared_memory::remove(temp.get_shmid()) && (system_error_code() != invalid_argument)){
|
||||
return false;
|
||||
}
|
||||
std::memset(info->names[i].buf, 0, info_constants_t<0>::MaxName);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool xsi_shared_memory_device::remove(int shmid)
|
||||
{ return xsi_shared_memory::remove(shmid); }
|
||||
|
||||
///@endcond
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP
|
||||
80
test/external/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
vendored
Normal file
80
test/external/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztanaga 2009-2010. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/interprocess for documentation.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
|
||||
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
|
||||
#error "This header can't be used in operating systems without XSI (System V) shared memory support"
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
|
||||
#include <boost/interprocess/xsi_shared_memory.hpp>
|
||||
|
||||
//!\file
|
||||
//!Describes a class representing a pseudo-file implemented on top of xsi shared memory.
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
class xsi_shared_memory_file_wrapper
|
||||
: public xsi_shared_memory
|
||||
{
|
||||
/// @cond
|
||||
BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper)
|
||||
/// @endcond
|
||||
public:
|
||||
|
||||
xsi_shared_memory_file_wrapper() : xsi_shared_memory() {}
|
||||
|
||||
xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions())
|
||||
: xsi_shared_memory(create_only_t(), key, size, perm.get_permissions())
|
||||
{}
|
||||
|
||||
xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions())
|
||||
: xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions())
|
||||
{}
|
||||
|
||||
xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t mode, const permissions& perm = permissions())
|
||||
: xsi_shared_memory(open_only_t(), key)
|
||||
{}
|
||||
|
||||
xsi_shared_memory_file_wrapper(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved)
|
||||
{ this->swap(moved); }
|
||||
|
||||
xsi_shared_memory_file_wrapper &operator=(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved)
|
||||
{
|
||||
xsi_shared_memory_file_wrapper tmp(boost::interprocess::move(moved));
|
||||
this->swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//!Swaps two xsi_shared_memory_file_wrapper. Does not throw
|
||||
void swap(xsi_shared_memory_file_wrapper &other)
|
||||
{ this->xsi_shared_memory::swap(other); }
|
||||
};
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP
|
||||
Reference in New Issue
Block a user