mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 04:12:13 +00:00
Removed unused files
[SVN r35626]
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,974 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 1994
|
||||
* Hewlett-Packard Company
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Hewlett-Packard Company makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1996
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This file comes from SGI's stl_vector.h file. Modified by Ion Gaztañaga.
|
||||
// Renaming, isolating and porting to generic algorithms. Pointer typedef
|
||||
// set to allocator::pointer to allow placing it in shared memory.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BOOST_SHMEM_VECTOR_HPP
|
||||
#define BOOST_SHMEM_VECTOR_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/*!This struct deallocates and allocated memory */
|
||||
template <class A>
|
||||
struct vector_alloc_holder : public A
|
||||
{
|
||||
typedef typename A::pointer pointer;
|
||||
|
||||
//Constructor, does not throw
|
||||
vector_alloc_holder(const A &a)
|
||||
: A(a), m_start(0), m_finish(0), m_end(0)
|
||||
{}
|
||||
|
||||
//Destructor
|
||||
~vector_alloc_holder()
|
||||
{ this->priv_deallocate(); }
|
||||
|
||||
pointer m_start;
|
||||
pointer m_finish;
|
||||
pointer m_end;
|
||||
|
||||
private:
|
||||
void priv_deallocate()
|
||||
{
|
||||
if(!m_start) return;
|
||||
this->deallocate(m_start, m_end - m_start);
|
||||
m_end = m_start;
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
|
||||
//vector class
|
||||
template <class T, class A>
|
||||
class vector : private detail::vector_alloc_holder<A>
|
||||
{
|
||||
typedef vector<T, A> self_t;
|
||||
typedef detail::vector_alloc_holder<A> base_t;
|
||||
typedef detail::scoped_array_deallocator<A> dealloc_t;
|
||||
|
||||
public:
|
||||
//STL container typedefs
|
||||
typedef T value_type;
|
||||
typedef A allocator_type;
|
||||
typedef typename A::pointer pointer;
|
||||
typedef typename A::const_pointer const_pointer;
|
||||
typedef typename A::reference reference;
|
||||
typedef typename A::const_reference const_reference;
|
||||
typedef typename A::size_type size_type;
|
||||
typedef typename A::difference_type difference_type;
|
||||
//This shouldn't be needed but VC6.0 needs this
|
||||
typedef typename A::pointer vec_ptr;
|
||||
typedef typename A::const_pointer vec_cptr;
|
||||
typedef typename A::reference vec_ref;
|
||||
typedef typename A::const_reference vec_cref;
|
||||
typedef typename A::difference_type vec_diff;
|
||||
|
||||
private:
|
||||
typedef range_from_ref_iterator<const T, difference_type> range_from_ref_it;
|
||||
|
||||
public:
|
||||
//Vector const_iterator
|
||||
class const_iterator
|
||||
: public boost::iterator<std::random_access_iterator_tag,
|
||||
value_type, vec_diff,
|
||||
vec_cptr, vec_cref >
|
||||
{
|
||||
private:
|
||||
vec_ptr get_ptr() const { return m_ptr; }
|
||||
|
||||
protected:
|
||||
vec_ptr m_ptr;
|
||||
explicit const_iterator(vec_ptr ptr) : m_ptr(ptr){}
|
||||
|
||||
public:
|
||||
friend class vector<T, A>;
|
||||
typedef vec_diff difference_type;
|
||||
|
||||
//Constructors
|
||||
const_iterator() : m_ptr(0){}
|
||||
|
||||
//Pointer like operators
|
||||
const_reference operator*() const
|
||||
{ return *m_ptr; }
|
||||
|
||||
const_pointer operator->() const
|
||||
{ return m_ptr; }
|
||||
|
||||
const_reference operator[](difference_type off) const
|
||||
{ return m_ptr[off]; }
|
||||
|
||||
//Increment / Decrement
|
||||
const_iterator& operator++()
|
||||
{ ++m_ptr; return *this; }
|
||||
|
||||
const_iterator operator++(int)
|
||||
{ vec_ptr tmp = m_ptr; ++*this; return const_iterator(tmp); }
|
||||
|
||||
const_iterator& operator--()
|
||||
{ --m_ptr; return *this; }
|
||||
|
||||
const_iterator operator--(int)
|
||||
{ vec_ptr tmp = m_ptr; --*this; return const_iterator(tmp); }
|
||||
|
||||
//Arithmetic
|
||||
const_iterator& operator+=(difference_type off)
|
||||
{ m_ptr += off; return *this; }
|
||||
|
||||
const_iterator operator+(difference_type off) const
|
||||
{ return const_iterator(m_ptr+off); }
|
||||
|
||||
friend const_iterator operator+(difference_type off, const const_iterator& right)
|
||||
{ return const_iterator(off + right.m_ptr); }
|
||||
|
||||
const_iterator& operator-=(difference_type off)
|
||||
{ m_ptr -= off; return *this; }
|
||||
|
||||
const_iterator operator-(difference_type off) const
|
||||
{ return const_iterator(m_ptr-off); }
|
||||
|
||||
difference_type operator-(const const_iterator& right) const
|
||||
{ return m_ptr - right.m_ptr; }
|
||||
|
||||
//Comparison operators
|
||||
bool operator== (const const_iterator& r) const
|
||||
{ return m_ptr == r.m_ptr; }
|
||||
|
||||
bool operator!= (const const_iterator& r) const
|
||||
{ return m_ptr != r.m_ptr; }
|
||||
|
||||
bool operator< (const const_iterator& r) const
|
||||
{ return m_ptr < r.m_ptr; }
|
||||
|
||||
bool operator<= (const const_iterator& r) const
|
||||
{ return m_ptr <= r.m_ptr; }
|
||||
|
||||
bool operator> (const const_iterator& r) const
|
||||
{ return m_ptr > r.m_ptr; }
|
||||
|
||||
bool operator>= (const const_iterator& r) const
|
||||
{ return m_ptr >= r.m_ptr; }
|
||||
};
|
||||
|
||||
//Vector iterator
|
||||
class iterator : public const_iterator
|
||||
{
|
||||
protected:
|
||||
explicit iterator(vec_ptr ptr) : const_iterator(ptr){}
|
||||
|
||||
public:
|
||||
friend class vector<T, A>;
|
||||
typedef vec_ptr pointer;
|
||||
typedef vec_ref reference;
|
||||
|
||||
//Constructors
|
||||
iterator(){}
|
||||
|
||||
//Pointer like operators
|
||||
reference operator*() const
|
||||
{ return *this->m_ptr; }
|
||||
|
||||
pointer operator->() const
|
||||
{ return this->m_ptr; }
|
||||
|
||||
reference operator[](difference_type off) const
|
||||
{return this->m_ptr[off];}
|
||||
|
||||
//Increment / Decrement
|
||||
iterator& operator++()
|
||||
{ ++this->m_ptr; return *this; }
|
||||
|
||||
iterator operator++(int)
|
||||
{ pointer tmp = this->m_ptr; ++*this; return iterator(tmp); }
|
||||
|
||||
iterator& operator--()
|
||||
{ --this->m_ptr; return *this; }
|
||||
|
||||
iterator operator--(int)
|
||||
{ iterator tmp = *this; --*this; return iterator(tmp); }
|
||||
|
||||
// Arithmetic
|
||||
iterator& operator+=(difference_type off)
|
||||
{ this->m_ptr += off; return *this; }
|
||||
|
||||
iterator operator+(difference_type off) const
|
||||
{ return iterator(this->m_ptr+off); }
|
||||
|
||||
friend iterator operator+(difference_type off, const iterator& right)
|
||||
{ return iterator(off + right.m_ptr); }
|
||||
|
||||
iterator& operator-=(difference_type off)
|
||||
{ this->m_ptr -= off; return *this; }
|
||||
|
||||
iterator operator-(difference_type off) const
|
||||
{ return iterator(this->m_ptr-off); }
|
||||
|
||||
difference_type operator-(const const_iterator& right) const
|
||||
{ return *((const_iterator*)this) - right; }
|
||||
};
|
||||
|
||||
//Reverse iterators
|
||||
typedef typename boost::reverse_iterator<iterator>
|
||||
reverse_iterator;
|
||||
typedef typename boost::reverse_iterator<const_iterator>
|
||||
const_reverse_iterator;
|
||||
|
||||
public:
|
||||
|
||||
//Constructor
|
||||
explicit vector(const A& a = A())
|
||||
: base_t(a)
|
||||
{}
|
||||
|
||||
//Construct and fill with n equal objects
|
||||
vector(size_type n, const T& value = T(),
|
||||
const allocator_type& a = allocator_type())
|
||||
: base_t(a)
|
||||
{
|
||||
if(n){
|
||||
//If there is an exception, the base class will
|
||||
//deallocate the memory
|
||||
this->m_start = this->allocate(n, 0);
|
||||
this->m_end = this->m_start + n;
|
||||
this->m_finish = this->m_start;
|
||||
this->priv_uninitialized_fill_n(this->m_start, n, value, *this);
|
||||
this->m_finish = this->m_end;
|
||||
}
|
||||
}
|
||||
|
||||
//Copy constructor
|
||||
vector(const vector<T, A>& x)
|
||||
: base_t(x.get_allocator())
|
||||
{
|
||||
size_type n = x.size();
|
||||
if(n){
|
||||
this->m_start = this->allocate(x.size(), 0);
|
||||
this->m_end = this->m_start + x.size();
|
||||
this->m_finish = this->m_start;
|
||||
this->priv_uninitialized_copy(x.m_start, x.m_finish, this->m_start, *this);
|
||||
this->m_finish = this->m_end;
|
||||
}
|
||||
}
|
||||
|
||||
//Construct from iterator range
|
||||
template <class InIt>
|
||||
vector(InIt first, InIt last,
|
||||
const allocator_type& a = allocator_type())
|
||||
: base_t(a)
|
||||
{
|
||||
const bool aux_boolean = boost::is_integral<InIt>::value;
|
||||
typedef boost::mpl::bool_<aux_boolean> Result;
|
||||
this->priv_initialize_aux(first, last, Result());
|
||||
}
|
||||
|
||||
//Destructor
|
||||
~vector()
|
||||
{ this->priv_destroy_all(); }
|
||||
|
||||
//Functions: begin, rbegin, end, rend
|
||||
iterator begin()
|
||||
{ return iterator(this->m_start); }
|
||||
|
||||
iterator end()
|
||||
{ return iterator(this->m_finish); }
|
||||
|
||||
const_iterator begin() const
|
||||
{ return const_iterator(this->m_start); }
|
||||
|
||||
const_iterator end() const
|
||||
{ return const_iterator(this->m_finish); }
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{ return reverse_iterator(this->end()); }
|
||||
|
||||
reverse_iterator rend()
|
||||
{ return reverse_iterator(this->begin()); }
|
||||
|
||||
const_reverse_iterator rbegin()const
|
||||
{ return const_reverse_iterator(this->end());}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{ return const_reverse_iterator(this->begin()); }
|
||||
|
||||
//Functions: front, back
|
||||
reference front()
|
||||
{ return *this->m_start; }
|
||||
|
||||
const_reference front() const
|
||||
{ return *this->m_start; }
|
||||
|
||||
reference back()
|
||||
{ return *(this->m_finish - 1); }
|
||||
|
||||
const_reference back() const
|
||||
{ return *(this->m_finish - 1); }
|
||||
|
||||
//Functions: size, max_size, capacity, empty
|
||||
size_type size() const
|
||||
{ return size_type(this->m_finish - this->m_start); }
|
||||
|
||||
size_type max_size() const
|
||||
{ return allocator_type::max_size(); }
|
||||
|
||||
size_type capacity() const
|
||||
{ return size_type(this->m_end - this->m_start); }
|
||||
|
||||
bool empty() const
|
||||
{ return this->m_start == this->m_finish; }
|
||||
|
||||
//Functions: operator [], at
|
||||
reference operator[](size_type n)
|
||||
{ return this->m_start[n]; }
|
||||
|
||||
const_reference operator[](size_type n) const
|
||||
{ return this->m_start[n]; }
|
||||
|
||||
reference at(size_type n)
|
||||
{ this->priv_check_range(n); return this->m_start[n]; }
|
||||
|
||||
const_reference at(size_type n) const
|
||||
{ this->priv_check_range(n); return this->m_start[n]; }
|
||||
|
||||
//Functions: get_allocator, reserve
|
||||
allocator_type get_allocator() const
|
||||
{ return allocator_type(*this); }
|
||||
|
||||
void reserve(size_type n)
|
||||
{
|
||||
if (capacity() < n){
|
||||
//Allocate new size, copy data and free old buffer
|
||||
const size_type old_size = size();
|
||||
pointer tmp = this->priv_allocate_and_copy(n, this->m_start, this->m_finish);
|
||||
this->priv_destroy_and_deallocate();
|
||||
this->m_start = tmp;
|
||||
this->m_finish = tmp + old_size;
|
||||
this->m_end = this->m_start + n;
|
||||
}
|
||||
}
|
||||
|
||||
//Assignment
|
||||
vector<T, A>& operator=(const vector<T, A>& x)
|
||||
{
|
||||
if (&x != this){
|
||||
const size_type xlen = x.size();
|
||||
|
||||
if (xlen > this->capacity()){
|
||||
//There is no memory to hold values from x. Allocate a new buffer,
|
||||
//copy data from x, and destroy and deallocate previous values
|
||||
pointer tmp = this->priv_allocate_and_copy(xlen, x.m_start, x.m_finish);
|
||||
this->priv_destroy_and_deallocate();
|
||||
this->m_start = tmp;
|
||||
this->m_end = this->m_start + xlen;
|
||||
}
|
||||
else if (size() >= xlen){
|
||||
//There is enough memory but current buffer has more objects than x.
|
||||
//Copy all objects from x and destroy the remaining objects
|
||||
pointer i = std::copy(x.m_start, x.m_finish, this->m_start);
|
||||
this->priv_destroy_range(i, this->m_finish);
|
||||
}
|
||||
else {
|
||||
//There is enough memory but current buffer has less objects than x.
|
||||
//Copy the first this->size() objects from x and initialize the
|
||||
//rest of the buffer with remaining x objects
|
||||
std::copy(x.m_start, x.m_start + size(), this->m_start);
|
||||
this->priv_uninitialized_copy(x.m_start + size(), x.m_finish, this->m_finish, *this);
|
||||
}
|
||||
this->m_finish = this->m_start + xlen;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void assign(size_type n, const value_type& val = T())
|
||||
{
|
||||
this->assign(range_from_ref_it(val, n)
|
||||
,range_from_ref_it());
|
||||
/*
|
||||
if (n > this->capacity()){
|
||||
//There is not enough memory, create a temporal vector and swap
|
||||
vector<T, A> tmp(n, val, static_cast<const allocator_type&>(*this));
|
||||
tmp.swap(*this);
|
||||
}
|
||||
else if (n > size()){
|
||||
//There is enough memory, but we have less objects. Assign current
|
||||
//objects and initialize the rest.
|
||||
std::fill(this->m_start, this->m_finish, val);
|
||||
size_t rest = n - size();
|
||||
this->priv_uninitialized_fill_n(this->m_finish, rest, val, *this);
|
||||
this->m_finish += rest;
|
||||
}
|
||||
else{
|
||||
//There is enough memory, but we have more objects. Assign the first
|
||||
//n objects and destroy the rest
|
||||
std::fill_n(this->m_start, n, val);
|
||||
this->erase(iterator(this->m_start + n), iterator(this->m_finish));
|
||||
}*/
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void assign(InIt first, InIt last)
|
||||
{
|
||||
//Dispatch depending on integer/iterator
|
||||
const bool aux_boolean = boost::is_integral<InIt>::value;
|
||||
typedef boost::mpl::bool_<aux_boolean> Result;
|
||||
this->priv_assign_dispatch(first, last, Result());
|
||||
}
|
||||
|
||||
void push_back(const T& x = T())
|
||||
{
|
||||
if (this->m_finish != this->m_end){
|
||||
//There is more memory, just construct a new object at the end
|
||||
this->construct(this->m_finish, x);
|
||||
++this->m_finish;
|
||||
}
|
||||
else{
|
||||
//No enough memory, insert a new object at the end
|
||||
this->insert(this->end(), static_cast<size_type>(1), x);
|
||||
}
|
||||
}
|
||||
|
||||
void swap(vector<T, A>& x)
|
||||
{
|
||||
allocator_type &this_al = *this, &other_al = x;
|
||||
//Just swap pointers
|
||||
detail::do_swap(this->m_start, x.m_start);
|
||||
detail::do_swap(this->m_finish, x.m_finish);
|
||||
detail::do_swap(this->m_end, x.m_end);
|
||||
|
||||
if (this_al != other_al){
|
||||
detail::do_swap(this_al, other_al);
|
||||
}
|
||||
}
|
||||
|
||||
iterator insert(iterator position, const T& x = T())
|
||||
{
|
||||
//Just call more general insert(pos, size, value) and return iterator
|
||||
size_type n = position - begin();
|
||||
this->insert(position, (size_type)1, x);
|
||||
return iterator(this->m_start + n);
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void insert(iterator pos, InIt first, InIt last)
|
||||
{
|
||||
//Dispatch depending on integer/iterator
|
||||
const bool aux_boolean = boost::is_integral<InIt>::value;
|
||||
typedef boost::mpl::bool_<aux_boolean> Result;
|
||||
this->priv_insert_dispatch(pos, first, last, Result());
|
||||
}
|
||||
|
||||
void insert (iterator position, size_type n, const T& x)
|
||||
{
|
||||
this->insert(position
|
||||
,range_from_ref_it(x, n)
|
||||
,range_from_ref_it());
|
||||
/*
|
||||
if (n != 0){
|
||||
if (size_type(this->m_end - this->m_finish) >= n){
|
||||
//There is enough memory
|
||||
const size_type elems_after = this->end() - position;
|
||||
pointer old_finish = this->m_finish;
|
||||
|
||||
if (elems_after > n){
|
||||
//New elements can be just copied.
|
||||
//Move to uninitialized memory last objects
|
||||
this->priv_uninitialized_copy(this->m_finish - n, this->m_finish,
|
||||
this->m_finish, *this);
|
||||
this->m_finish += n;
|
||||
//Copy previous to last objects to the initialized end
|
||||
std::copy_backward(position.get_ptr(), old_finish - n,
|
||||
old_finish);
|
||||
//Insert new objects in the position
|
||||
std::fill(position.get_ptr(), position.get_ptr() + n, x);
|
||||
}
|
||||
else {
|
||||
//The new elements don't fit in the [position, end()) range. Copy
|
||||
//to the beginning of the unallocated zone the last new elements.
|
||||
this->priv_uninitialized_fill_n(this->m_finish, n - elems_after, x, *this);
|
||||
this->m_finish += n - elems_after;
|
||||
//Copy old [position, end()) elements to the uninitialized memory
|
||||
this->priv_uninitialized_copy(position.get_ptr(), old_finish,
|
||||
this->m_finish, *this);
|
||||
this->m_finish += elems_after;
|
||||
//Insert first new elements in position
|
||||
std::fill(position.get_ptr(), old_finish, x);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//There is not enough memory, allocate a new buffer
|
||||
size_type old_size = size();
|
||||
size_type len = old_size + ((old_size/2 > n) ? old_size/2 : n);
|
||||
pointer new_start = this->allocate(len, 0);
|
||||
|
||||
scoped_ptr<T, dealloc_t> scoped_alloc(new_start, dealloc_t(*this, len));
|
||||
pointer new_finish = new_start;
|
||||
//Initialize [begin(), position) old buffer to the start of the new buffer
|
||||
new_finish = this->priv_uninitialized_copy(this->m_start, position.get_ptr(),
|
||||
new_start, *this);
|
||||
//Initialize new n objects, starting from previous point
|
||||
this->priv_uninitialized_fill_n(new_finish, n, x, *this);
|
||||
new_finish = new_finish + n;
|
||||
//Initialize from the rest of the old buffer, starting from previous point
|
||||
new_finish = this->priv_uninitialized_copy(position.get_ptr(), this->m_finish,
|
||||
new_finish, *this);
|
||||
//New data is in the new buffer, release scoped deallocation
|
||||
scoped_alloc.release();
|
||||
//Destroy and deallocate old elements
|
||||
this->priv_destroy_and_deallocate();
|
||||
this->m_start = new_start;
|
||||
this->m_finish = new_finish;
|
||||
this->m_end = new_start + len;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
//Destroy last element
|
||||
--this->m_finish;
|
||||
this->destroy(this->m_finish);
|
||||
}
|
||||
|
||||
// Return type of erase(const_iterator):
|
||||
// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1753.html#130
|
||||
|
||||
iterator erase(const_iterator position)
|
||||
{
|
||||
if (position + 1 != end()){
|
||||
//If not the last element, copy left [position, end()) elements
|
||||
std::copy((position + 1).get_ptr(), this->m_finish, position.get_ptr());
|
||||
}
|
||||
--this->m_finish;
|
||||
//Destroy last element
|
||||
this->destroy(this->m_finish);
|
||||
return iterator(position.get_ptr());
|
||||
}
|
||||
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
//Overwrite [last, end()) elements to first
|
||||
pointer i = std::copy(last.get_ptr(), this->m_finish, first.get_ptr());
|
||||
//Destroy remaining objects
|
||||
this->priv_destroy_range(i, this->m_finish);
|
||||
this->m_finish = this->m_finish - (last - first);
|
||||
return iterator(first.get_ptr());
|
||||
}
|
||||
|
||||
void resize(size_type new_size, const T& x = T())
|
||||
{
|
||||
if (new_size < size())
|
||||
//Destroy last elements
|
||||
this->erase(iterator(this->m_start + new_size), iterator(this->m_finish));
|
||||
else
|
||||
//Insert new elements at the end
|
||||
this->insert(iterator(this->m_finish), new_size - size(), x);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{ this->priv_destroy_all(); }
|
||||
|
||||
private:
|
||||
|
||||
void priv_destroy_all()
|
||||
{
|
||||
if(!this->m_start)
|
||||
return;
|
||||
|
||||
pointer start = this->m_start;
|
||||
|
||||
for(;start != this->m_finish; ++start)
|
||||
this->destroy(start);
|
||||
|
||||
this->m_finish = this->m_start;
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void priv_range_initialize(InIt first,
|
||||
InIt last, std::input_iterator_tag)
|
||||
{
|
||||
//Just insert all elements at the end
|
||||
std::copy(first, last, std::back_inserter(*this));
|
||||
}
|
||||
|
||||
template <class FwdIt>
|
||||
void priv_range_initialize(FwdIt first,
|
||||
FwdIt last, std::forward_iterator_tag)
|
||||
{
|
||||
//Calculate distance, allocate and copy
|
||||
size_type n = 0;
|
||||
n = std::distance(first, last);
|
||||
this->m_start = this->allocate(n, 0);
|
||||
|
||||
scoped_ptr<T, dealloc_t> scoped_alloc(this->m_start, dealloc_t(*this, n));
|
||||
this->m_end = this->m_start + n;
|
||||
this->m_finish = this->priv_uninitialized_copy(first, last, this->m_start, *this);
|
||||
scoped_alloc.release();
|
||||
}
|
||||
|
||||
template <class FwdIt>
|
||||
void priv_range_insert(iterator position, FwdIt first,
|
||||
FwdIt last, std::forward_iterator_tag)
|
||||
{
|
||||
if (first != last){
|
||||
size_type n = 0;
|
||||
n = std::distance(first, last);
|
||||
if (size_type(this->m_end - this->m_finish) >= n){
|
||||
//There is enough memory
|
||||
const size_type elems_after = this->m_finish - position.get_ptr();
|
||||
pointer old_finish = this->m_finish;
|
||||
if (elems_after > n){
|
||||
//New elements can be just copied.
|
||||
//Move to unitialized memory last objects
|
||||
this->priv_uninitialized_copy(this->m_finish - n, this->m_finish,
|
||||
this->m_finish, *this);
|
||||
this->m_finish += n;
|
||||
//Copy previous to last objects to the initialized end
|
||||
std::copy_backward(position.get_ptr(), old_finish - n, old_finish);
|
||||
//Insert new objects in the position
|
||||
std::copy(first, last, position.get_ptr());
|
||||
}
|
||||
else {
|
||||
//The new elements don't fit in the [position, end()) range. Copy
|
||||
//to the beginning of the unalocated zone the last new elements.
|
||||
FwdIt mid = first;
|
||||
std::advance(mid, elems_after);
|
||||
this->priv_uninitialized_copy(mid, last, this->m_finish, *this);
|
||||
this->m_finish += n - elems_after;
|
||||
//Copy old [position, end()) elements to the unitialized memory
|
||||
this->priv_uninitialized_copy(position.get_ptr(), old_finish,
|
||||
this->m_finish, *this);
|
||||
this->m_finish += elems_after;
|
||||
//Copy first new elements in position
|
||||
std::copy(first, mid, position.get_ptr());
|
||||
}
|
||||
}
|
||||
else {
|
||||
//There is not enough memory, allocate a new buffer
|
||||
const size_type old_size = size();
|
||||
const size_type len = old_size + ((old_size/2 > n) ? old_size/2 : n);
|
||||
pointer new_start = this->allocate(len, 0);
|
||||
scoped_ptr<T, dealloc_t> scoped_alloc(new_start, dealloc_t(*this, len));
|
||||
pointer new_finish = new_start;
|
||||
BOOST_TRY{
|
||||
//Initialize with [begin(), position) old buffer
|
||||
//the start of the new buffer
|
||||
new_finish = this->priv_uninitialized_copy
|
||||
(this->m_start, position.get_ptr(), new_start, *this);
|
||||
//Initialize new objects, starting from previous point
|
||||
new_finish = this->priv_uninitialized_copy
|
||||
(first, last, new_finish, *this);
|
||||
//Initialize from the rest of the old buffer,
|
||||
//starting from previous point
|
||||
new_finish = this->priv_uninitialized_copy
|
||||
(position.get_ptr(), this->m_finish, new_finish, *this);
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
this->priv_destroy_range(new_start, new_finish);
|
||||
this->deallocate(new_start, len);
|
||||
BOOST_RETHROW
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
scoped_alloc.release();
|
||||
//Destroy and deallocate old elements
|
||||
this->priv_destroy_and_deallocate();
|
||||
this->m_start = new_start;
|
||||
this->m_finish = new_finish;
|
||||
this->m_end = new_start + len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void priv_range_insert(iterator pos,
|
||||
InIt first, InIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
//Insert range before the pos position
|
||||
std::copy(std::inserter(*this, pos), first, last);
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void priv_assign_aux(InIt first, InIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
//Overwrite all elements we can from [first, last)
|
||||
iterator cur = begin();
|
||||
for ( ; first != last && cur != end(); ++cur, ++first){
|
||||
*cur = *first;
|
||||
}
|
||||
|
||||
if (first == last){
|
||||
//There are no more elements in the secuence, erase remaining
|
||||
this->erase(cur, end());
|
||||
}
|
||||
else{
|
||||
//There are more elements in the range, insert the remaining ones
|
||||
this->insert(end(), first, last);
|
||||
}
|
||||
}
|
||||
|
||||
template <class FwdIt>
|
||||
void priv_assign_aux(FwdIt first, FwdIt last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
size_type len = 0;
|
||||
len = std::distance(first, last);
|
||||
|
||||
if (len > capacity()){
|
||||
//There is no enough memory, allocate and copy new buffer
|
||||
pointer tmp = this->priv_allocate_and_copy(len, first, last);
|
||||
//Destroy and deallocate old buffer
|
||||
this->priv_destroy_and_deallocate();
|
||||
this->m_start = tmp;
|
||||
this->m_end = this->m_finish = this->m_start + len;
|
||||
}
|
||||
else if (size() >= len){
|
||||
//There is memory, but there are more old elements than new ones
|
||||
//Overwrite old elements with new ones
|
||||
pointer new_finish = std::copy(first, last, this->m_start);
|
||||
//Destroy remaining old elements
|
||||
this->priv_destroy_range(new_finish, this->m_finish);
|
||||
this->m_finish = new_finish;
|
||||
}
|
||||
else {
|
||||
//There is memory, but there are less old elements than new ones
|
||||
//Overwrite old elements with new ones
|
||||
FwdIt mid = first;
|
||||
std::advance(mid, size());
|
||||
std::copy(first, mid, this->m_start);
|
||||
//Initialize the remaining new elements in the unitialized memory
|
||||
this->m_finish = this->priv_uninitialized_copy(mid, last, this->m_finish, *this);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
void priv_assign_dispatch(Integer n, Integer val, boost::mpl::true_)
|
||||
{ this->assign((size_type) n, (T) val); }
|
||||
|
||||
template <class InIt>
|
||||
void priv_assign_dispatch(InIt first, InIt last,
|
||||
boost::mpl::false_)
|
||||
{
|
||||
//Dispatch depending on integer/iterator
|
||||
typedef typename
|
||||
std::iterator_traits<InIt>::iterator_category ItCat;
|
||||
this->priv_assign_aux(first, last, ItCat());
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
void priv_insert_dispatch( iterator pos, Integer n,
|
||||
Integer val, boost::mpl::true_)
|
||||
{ this->insert(pos, (size_type)n, (T)val); }
|
||||
|
||||
template <class InIt>
|
||||
void priv_insert_dispatch(iterator pos, InIt first,
|
||||
InIt last, boost::mpl::false_)
|
||||
{
|
||||
//Dispatch depending on integer/iterator
|
||||
typedef typename
|
||||
std::iterator_traits<InIt>::iterator_category ItCat;
|
||||
this->priv_range_insert(pos, first, last, ItCat());
|
||||
}
|
||||
|
||||
void priv_destroy_range(pointer p, pointer p2)
|
||||
{ for(;p != p2; ++p) this->destroy(p); }
|
||||
|
||||
template <class Integer>
|
||||
void priv_initialize_aux(Integer n, Integer value, boost::mpl::true_)
|
||||
{
|
||||
//Allocate and initialize integer vector buffer
|
||||
this->m_start = this->allocate(n, 0);
|
||||
scoped_ptr<T, dealloc_t> scoped_alloc(this->m_start, dealloc_t(*this, n));
|
||||
this->m_end = this->m_start + n;
|
||||
this->m_finish = this->m_start;
|
||||
this->priv_uninitialized_fill_n(this->m_start, n, value, *this);
|
||||
this->m_finish = this->m_start + n;
|
||||
scoped_alloc.release();
|
||||
}
|
||||
|
||||
template <class InIt>
|
||||
void priv_initialize_aux(InIt first, InIt last,
|
||||
boost::mpl::false_)
|
||||
{
|
||||
//Dispatch depending on integer/iterator
|
||||
typedef typename
|
||||
std::iterator_traits<InIt>::iterator_category ItCat;
|
||||
this->priv_range_initialize(first, last, ItCat());
|
||||
}
|
||||
|
||||
void priv_destroy_and_deallocate()
|
||||
{
|
||||
//If there is allocated memory, destroy and deallocate
|
||||
if(this->m_start != 0){
|
||||
this->priv_destroy_range(this->m_start, this->m_finish);
|
||||
this->deallocate(this->m_start, this->m_end - this->m_start);
|
||||
}
|
||||
}
|
||||
|
||||
template <class FwdIt>
|
||||
pointer priv_allocate_and_copy(size_type n, FwdIt first,
|
||||
FwdIt last)
|
||||
{
|
||||
//Allocate n element buffer and initialize from range
|
||||
pointer result = this->allocate(n, 0);
|
||||
scoped_ptr<T, dealloc_t> scoped_alloc(result, dealloc_t(*this, n));
|
||||
this->priv_uninitialized_copy(first, last, result, *this);
|
||||
scoped_alloc.release();
|
||||
return result;
|
||||
}
|
||||
|
||||
void priv_check_range(size_type n) const
|
||||
{
|
||||
//If n is out of range, throw an out_of_range exception
|
||||
if (n >= size())
|
||||
throw std::out_of_range("vector::at");
|
||||
}
|
||||
|
||||
template<class InIt, class FwdIt, class alloc> inline
|
||||
FwdIt priv_uninitialized_copy(InIt first, InIt last,
|
||||
FwdIt dest, alloc& al)
|
||||
{
|
||||
//Save initial destination position
|
||||
FwdIt dest_init = dest;
|
||||
|
||||
BOOST_TRY{
|
||||
//Try to build objects
|
||||
for (; first != last; ++dest, ++first){
|
||||
al.construct(dest, *first);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
//Call destructors
|
||||
for (; dest_init != dest; ++dest_init){
|
||||
al.destroy(dest_init);
|
||||
}
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
return (dest);
|
||||
}
|
||||
|
||||
template<class FwdIt, class Count, class Alloc> inline
|
||||
void priv_uninitialized_fill_n(FwdIt first, Count count,
|
||||
const T& val, Alloc& al)
|
||||
{
|
||||
//Save initial position
|
||||
FwdIt init = first;
|
||||
|
||||
BOOST_TRY{
|
||||
//Construct objects
|
||||
for (; count--; ++first){
|
||||
al.construct(first, val);
|
||||
}
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
//Call destructors
|
||||
for (; init != first; ++init){
|
||||
al.destroy(init);
|
||||
}
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
inline bool
|
||||
operator==(const vector<T, A>& x, const vector<T, A>& y)
|
||||
{
|
||||
//Check first size and each element if needed
|
||||
return x.size() == y.size() &&
|
||||
std::equal(x.begin(), x.end(), y.begin());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
inline bool
|
||||
operator!=(const vector<T, A>& x, const vector<T, A>& y)
|
||||
{
|
||||
//Check first size and each element if needed
|
||||
return x.size() != y.size() ||
|
||||
!std::equal(x.begin(), x.end(), y.begin());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
inline bool
|
||||
operator<(const vector<T, A>& x, const vector<T, A>& y)
|
||||
{
|
||||
return std::lexicographical_compare(x.begin(), x.end(),
|
||||
y.begin(), y.end());
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
inline void swap(vector<T, A>& x, vector<T, A>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SHMEM_VECTOR_HPP
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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_GLOBAL_LOCK_HPP
|
||||
#define BOOST_INTERPROCESS_DETAIL_GLOBAL_LOCK_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
# include <boost/interprocess/sync/win32/win32_sync_primitives.hpp>
|
||||
#else
|
||||
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <fcntl.h> //O_CREAT, O_*...
|
||||
# include <unistd.h> //ftruncate, close
|
||||
# include <semaphore.h> //sem_t* family, SEM_VALUE_MAX
|
||||
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class global_lock
|
||||
{
|
||||
public:
|
||||
global_lock();
|
||||
bool acquire();
|
||||
~global_lock();
|
||||
void release();
|
||||
private:
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
void *m_mut;
|
||||
#else
|
||||
sem_t *m_sem;
|
||||
#endif
|
||||
bool m_acquired;
|
||||
};
|
||||
|
||||
inline global_lock::~global_lock()
|
||||
{ this->release(); }
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline global_lock::global_lock()
|
||||
: m_mut(0), m_acquired(false){}
|
||||
|
||||
inline bool global_lock::acquire()
|
||||
{
|
||||
m_mut = winapi::create_mutex("/boost_shmem_shm_global_mutex");
|
||||
if(m_mut == 0)
|
||||
return false;
|
||||
unsigned long ret = winapi::wait_for_single_object(m_mut, winapi::infinite_time);
|
||||
//Other thread has abandoned this without closing the handle
|
||||
if(ret == winapi::wait_abandoned){
|
||||
ret = winapi::wait_for_single_object(m_mut, winapi::infinite_time);
|
||||
}
|
||||
m_acquired = ret == winapi::wait_object_0;
|
||||
return m_acquired;
|
||||
}
|
||||
|
||||
inline void global_lock::release()
|
||||
{
|
||||
if(m_acquired){
|
||||
winapi::release_mutex(m_mut);
|
||||
m_acquired = false;
|
||||
}
|
||||
|
||||
if(m_mut){
|
||||
winapi::close_handle(m_mut);
|
||||
m_mut = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline global_lock::global_lock()
|
||||
: m_sem((sem_t*)-1), m_acquired(false){}
|
||||
|
||||
inline bool global_lock::acquire()
|
||||
{
|
||||
const unsigned int BufSize = 64;
|
||||
char globalMutexName[BufSize];
|
||||
const char *prefix = "/boost_shmem_shm_global_mutex-";
|
||||
if((strlen(getenv("LOGNAME") + strlen(prefix) + 1)) > BufSize){
|
||||
return false;
|
||||
}
|
||||
strcpy(globalMutexName, prefix);
|
||||
strcat(globalMutexName, getenv("LOGNAME"));
|
||||
mode_t mode = S_IRWXG | S_IRWXO | S_IRWXU;
|
||||
m_sem = sem_open(globalMutexName, O_CREAT, mode, 1);
|
||||
|
||||
if(m_sem == SEM_FAILED)
|
||||
return false;
|
||||
m_acquired = sem_wait(m_sem) == 0;
|
||||
return m_acquired;
|
||||
}
|
||||
|
||||
inline void global_lock::release()
|
||||
{
|
||||
if(m_acquired){
|
||||
sem_post(m_sem);
|
||||
m_acquired = false;
|
||||
}
|
||||
|
||||
if(m_sem != ((sem_t*)-1)){
|
||||
sem_close(m_sem);
|
||||
m_sem = ((sem_t*)-1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
} //namespace detail {
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_DETAIL_GLOBAL_LOCK_HPP
|
||||
@@ -1,21 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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_NAMED_FIFO_HPP
|
||||
#define BOOST_NAMED_FIFO_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
//TO-DO
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifndef BOOST_NAMED_FIFO_HPP
|
||||
@@ -1,541 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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_MAPPED_FILE_HPP
|
||||
#define BOOST_INTERPROCESS_MAPPED_FILE_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/interprocess/detail/creation_tags.hpp>
|
||||
#include <boost/interprocess/memory_mappable.hpp>
|
||||
#include <boost/interprocess/detail/global_lock.hpp>
|
||||
#include <boost/interprocess/detail/os_file_functions.hpp>
|
||||
#include <memory> //std::auto_ptr
|
||||
#include <string> //std::string
|
||||
#include <cstdio> //std::remove
|
||||
#include <string>
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
# include <boost/interprocess/sync/win32/win32_sync_primitives.hpp>
|
||||
#else
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <fcntl.h>
|
||||
# include <sys/mman.h> //mmap, off64_t
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
/*!\file
|
||||
Describes file_mapping and mapped region classes
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
/*!A class that wraps a file-mapping that can be used to
|
||||
create mapped regions from the mapped files*/
|
||||
class file_mapping : public memory_mappable
|
||||
{
|
||||
public:
|
||||
typedef memory_mappable::accessmode_t accessmode_t;
|
||||
typedef memory_mappable::mapping_handle_t mapping_handle_t;
|
||||
|
||||
/*!Opens a file mapping of file "filename", starting in offset
|
||||
"file_offset", and the mapping's size will be "size". The mapping
|
||||
can be opened for read-only "read_only" or read-write "read_write"
|
||||
modes. Throws interprocess_exception on error.*/
|
||||
file_mapping(const char *filename, accessmode_t mode);
|
||||
|
||||
/*!Destroys the file mapping. All mapped regions created from this are still
|
||||
valid. Does not throw*/
|
||||
~file_mapping();
|
||||
|
||||
/*!Returns the name of the file.*/
|
||||
const char *get_name() const;
|
||||
|
||||
|
||||
private:
|
||||
/*!Closes a previously opened file mapping. Never throws.*/
|
||||
void priv_close();
|
||||
|
||||
std::string m_filename;
|
||||
};
|
||||
|
||||
inline file_mapping::~file_mapping()
|
||||
{ this->priv_close(); }
|
||||
|
||||
inline const char *file_mapping::get_name() const
|
||||
{ return m_filename.c_str(); }
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline file_mapping::file_mapping
|
||||
(const char *filename, memory_mappable::accessmode_t mode)
|
||||
: memory_mappable()
|
||||
, m_filename(filename)
|
||||
{
|
||||
unsigned long file_access = 0;
|
||||
unsigned long file_creation_flags = 0;
|
||||
|
||||
//Set accesses
|
||||
if (mode == read_write){
|
||||
file_access |= winapi::generic_read | winapi::generic_write;
|
||||
}
|
||||
else if (mode == read_only){
|
||||
file_access |= winapi::generic_read;
|
||||
}
|
||||
|
||||
file_creation_flags = winapi::open_existing;
|
||||
|
||||
//Open file using windows API since we need the handle
|
||||
memory_mappable::mapping_handle_t hnd =
|
||||
winapi::create_file(filename, file_access, file_creation_flags);
|
||||
|
||||
//Check for error
|
||||
if(hnd == winapi::invalid_handle_value){
|
||||
error_info err = winapi::get_last_error();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
memory_mappable::assign_data(hnd, mode);
|
||||
}
|
||||
|
||||
inline void file_mapping::priv_close()
|
||||
{
|
||||
if(memory_mappable::get_mapping_handle() != winapi::invalid_handle_value){
|
||||
winapi::close_handle(memory_mappable::get_mapping_handle());
|
||||
memory_mappable::assign_data
|
||||
(winapi::invalid_handle_value, memory_mappable::get_mode());
|
||||
}
|
||||
}
|
||||
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline file_mapping::file_mapping
|
||||
(const char *filename, memory_mappable::accessmode_t mode)
|
||||
: m_filename(filename)
|
||||
{
|
||||
//Create new mapping
|
||||
int oflag = 0;
|
||||
|
||||
if(mode == read_only){
|
||||
oflag |= O_RDONLY;
|
||||
}
|
||||
else if(mode == read_write){
|
||||
oflag |= O_RDWR;
|
||||
}
|
||||
else{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Open file and get handle
|
||||
int hnd = ::open(filename, // filename
|
||||
oflag, // read/write access
|
||||
S_IRWXO | S_IRWXG | S_IRWXU); // permissions
|
||||
if(hnd == -1){
|
||||
error_info err = system_error_code();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
memory_mappable::assign_data(hnd, mode);
|
||||
}
|
||||
|
||||
inline void file_mapping::priv_close()
|
||||
{
|
||||
if(memory_mappable::get_mapping_handle() != -1){
|
||||
::close(memory_mappable::get_mapping_handle());
|
||||
memory_mappable::assign_data(-1, memory_mappable::get_mode());
|
||||
}
|
||||
}
|
||||
|
||||
#endif //##if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
/*!A class that wraps basic file-mapping management*/
|
||||
class mapped_file
|
||||
{
|
||||
//Non-copyable
|
||||
mapped_file();
|
||||
mapped_file(const mapped_file &);
|
||||
mapped_file &operator=(const mapped_file &);
|
||||
|
||||
public:
|
||||
/*!Creates a memory mapped file with name "name", and size "size".
|
||||
If the file was previously created it throws an error.
|
||||
The mapping can be opened in read-only "read_only" or read-write "read_write" modes.
|
||||
The user can also specify the mapping address in "addr". If "addr" is 0,
|
||||
the operating system will choose the mapping address.
|
||||
|
||||
This function can throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc)*/
|
||||
mapped_file(detail::create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode = memory_mappable::read_write,
|
||||
const void *addr = 0);
|
||||
|
||||
/*!Creates a memory mapped file with name "name", and size "size" if
|
||||
the file was not previously created. If it was previously
|
||||
created it tries to open it.
|
||||
The file can be opened in read-only "read_only" or read-write "read_write" modes.
|
||||
The user can also specify the mapping address in "addr". If "addr" is 0,
|
||||
the operating system will choose the mapping address.
|
||||
|
||||
This function can throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc)*/
|
||||
mapped_file(detail::open_only_t,
|
||||
const char *name,
|
||||
memory_mappable::accessmode_t mode = memory_mappable::read_write,
|
||||
const void *addr = 0);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", and size "size" if
|
||||
the shared memory was not previously created. If it was previously
|
||||
created it tries to open it.
|
||||
The file can be opened in read-only "read_only" or read-write "read_write" modes.
|
||||
The user can specify the mapping address in "addr".
|
||||
If "addr" is 0, the operating system will choose the mapping address.
|
||||
|
||||
This function can throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc)*/
|
||||
mapped_file(detail::open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode = memory_mappable::read_write,
|
||||
const void *addr = 0);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", with size "size".
|
||||
The file can be opened in read-only "read_only" or read-write "read_write" modes.
|
||||
The user must specify the mapping address in "addr".
|
||||
If "addr" is 0, the operating system will choose the mapping address.
|
||||
It also executes a copy of the functor "construct_func" atomically if
|
||||
the segment is created. The functor must have the following signature:
|
||||
|
||||
bool operator()(const mapped_file_info_t * info, bool created)
|
||||
|
||||
"info" is an initialized segment info structure, and "created"
|
||||
must be "true". If the functor returns "false", or throws an error
|
||||
is supposed and the shared memory won't be created.
|
||||
The user must specify a destroy_func, that will be copied in this
|
||||
constructor and executed in the destructor, before unmapping the
|
||||
shared memory segment.
|
||||
The functor must have the following signature:
|
||||
|
||||
void operator()(const mapped_file_info_t * info, bool last) const
|
||||
|
||||
"info" is an initialized segment info structure, and "last"
|
||||
indicates if this unmapping is the last unmapping so that
|
||||
there will be no no other processes attached to the segment.
|
||||
The functor must NOT throw.
|
||||
|
||||
This function can throw if copying any functor throws,
|
||||
the construct_func execution throws, and it
|
||||
will throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc) on any error*/
|
||||
template <class ConstructFunc>
|
||||
mapped_file(detail::create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", and size "size" if
|
||||
the shared memory was not previously created. If it was previously
|
||||
created tries to open it.
|
||||
The file can be opened in read-only "read_only" or read-write "read_write" modes.
|
||||
The user must specify the mapping address in "addr".
|
||||
If "addr" is 0, the operating system will choose the mapping address.
|
||||
It also executes a copy of the functor "construct_func" atomically
|
||||
if the segment is opened. The functor must have the following signature:
|
||||
|
||||
bool operator()(const mapped_file_info_t * info, bool created)
|
||||
|
||||
"info" is an initialized segment info structure, and "created"
|
||||
must be "false". If the functor returns "false", or throws an error
|
||||
is supposed and the shared memory won't be opened.
|
||||
The user must specify a destroy_func, that will be copied in this
|
||||
constructor and executed in the destructor, before unmapping the
|
||||
shared memory segment.
|
||||
The functor must have the following signature:
|
||||
|
||||
void operator()(const mapped_file_info_t * info, bool last) const
|
||||
|
||||
"info" is an initialized segment info structure, and "last"
|
||||
indicates if this unmapping is the last unmapping so that
|
||||
there will be no no other processes attached to the segment.
|
||||
The functor must NOT throw.
|
||||
|
||||
This function can throw if copying any functor throws,
|
||||
the construct_func execution throws, and it
|
||||
will throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc) on any error*/
|
||||
template <class ConstructFunc>
|
||||
mapped_file(detail::open_only_t,
|
||||
const char *name,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", and size "size" if
|
||||
the shared memory was not previously created. If it was previously
|
||||
created it tries to open it.
|
||||
The file can be opened in read-only "read_only" or read-write "read_write" modes.
|
||||
The user must specify the mapping address in "addr".
|
||||
If "addr" is 0, the operating system will choose the mapping address.
|
||||
It also executes the functor "construct_func" atomically if the segment is
|
||||
created or opened. The functor must have the following signature:
|
||||
|
||||
bool operator()(const mapped_file_info_t * info, bool created)
|
||||
|
||||
"info" is an initialized segment info structure, and "created"
|
||||
will be "true" if the shared memory was created. If the functor
|
||||
returns "false", or throws an error is supposed and the
|
||||
shared memory won't be opened.
|
||||
The user must specify a destroy_func, that will be copied in this
|
||||
constructor and executed in the destructor, before unmapping the
|
||||
shared memory segment.
|
||||
The functor must have the following signature:
|
||||
|
||||
void operator()(const mapped_file_info_t * info, bool last) const
|
||||
|
||||
"info" is an initialized segment info structure, and "last"
|
||||
indicates if this unmapping is the last unmapping so that
|
||||
there will be no no other processes attached to the segment.
|
||||
The functor must NOT throw.
|
||||
|
||||
This function can throw if copying any functor throws,
|
||||
the construct_func execution throws, and it
|
||||
will throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc) on any error*/
|
||||
template <class ConstructFunc>
|
||||
mapped_file(detail::open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func);
|
||||
|
||||
/*!Destructor. Unmaps the file from process' address space.
|
||||
It also executes the destruction functor atomically if
|
||||
the user has registered that the destruction functor
|
||||
in the constructor of this class.
|
||||
Never throws.*/
|
||||
~mapped_file();
|
||||
|
||||
/*!Returns the size of the file mapping. Never throws.*/
|
||||
std::size_t get_size() const;
|
||||
|
||||
/*!Returns the base address of the file mapping. Never throws.*/
|
||||
void* get_address() const;
|
||||
|
||||
/*!Flushes to the disk the whole file.
|
||||
Never throws*/
|
||||
bool flush();
|
||||
|
||||
/*!Returns the name of the shared memory segment used in the
|
||||
constructor. Never throws.*/
|
||||
const char *get_name() const;
|
||||
|
||||
private:
|
||||
enum type_t { DoCreate, DoOpen, DoCreateOrOpen };
|
||||
|
||||
template <class ConstructFunc>
|
||||
bool priv_open_or_create(type_t type,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
ConstructFunc construct_func);
|
||||
|
||||
//Members
|
||||
mapped_region m_mapped_region;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
inline
|
||||
mapped_file::mapped_file
|
||||
(detail::create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr)
|
||||
{
|
||||
this->priv_open_or_create(DoCreate, name, size, mode, addr, null_mapped_region_function());
|
||||
}
|
||||
|
||||
inline
|
||||
mapped_file::mapped_file
|
||||
(detail::open_only_t,
|
||||
const char *name,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr)
|
||||
{
|
||||
this->priv_open_or_create(DoOpen, name, 0, mode, addr, null_mapped_region_function());
|
||||
}
|
||||
|
||||
inline
|
||||
mapped_file::mapped_file
|
||||
(detail::open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr)
|
||||
{
|
||||
this->priv_open_or_create(DoCreateOrOpen, name, size, mode, addr, null_mapped_region_function());
|
||||
}
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
mapped_file::mapped_file(detail::create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
this->priv_open_or_create(DoCreate, name, size, mode, addr, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
mapped_file::mapped_file(detail::open_only_t,
|
||||
const char *name,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
this->priv_open_or_create(DoOpen, name, 0, mode, addr, construct_func);
|
||||
}
|
||||
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
mapped_file::mapped_file(detail::open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
this->priv_open_or_create(DoCreateOrOpen, name, size, mode, addr, construct_func);
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
mapped_file::~mapped_file()
|
||||
{}
|
||||
|
||||
std::size_t mapped_file::get_size() const
|
||||
{ return m_mapped_region.get_size(); }
|
||||
|
||||
void* mapped_file::get_address() const
|
||||
{ return m_mapped_region.get_address(); }
|
||||
|
||||
bool mapped_file::flush()
|
||||
{ return m_mapped_region.flush(); }
|
||||
|
||||
inline const char *mapped_file::get_name() const
|
||||
{ return m_name.c_str(); }
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
bool mapped_file::priv_open_or_create
|
||||
(mapped_file::type_t type, const char *name,
|
||||
std::size_t size, memory_mappable::accessmode_t mode,
|
||||
const void *addr, ConstructFunc construct_func)
|
||||
{
|
||||
error_info err;
|
||||
bool created = true;
|
||||
|
||||
m_name = name;
|
||||
|
||||
//This global interprocess_mutex guarantees synchronized creation/open logic
|
||||
detail::global_lock mut;
|
||||
if(!mut.acquire()){
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return false;
|
||||
#else
|
||||
throw interprocess_exception(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(type == DoOpen){
|
||||
//Open existing shared memory
|
||||
created = false;
|
||||
}
|
||||
else if(type == DoCreateOrOpen || type == DoCreate){
|
||||
detail::OS_file_handle_t hnd = detail::create_new_file(name);
|
||||
if(hnd != detail::invalid_file()){
|
||||
if(!detail::truncate_file(hnd, size)){
|
||||
err = system_error_code();
|
||||
detail::close_file(hnd);
|
||||
std::remove(name);
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return false;
|
||||
#else
|
||||
throw interprocess_exception(err);
|
||||
#endif
|
||||
}
|
||||
//Free resources
|
||||
if(!detail::close_file(hnd)){
|
||||
err = system_error_code();
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return false;
|
||||
#else
|
||||
throw interprocess_exception(err);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if(type == DoCreate){
|
||||
err = system_error_code();
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return false;
|
||||
#else
|
||||
throw interprocess_exception(err);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else{
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Open file mapping
|
||||
file_mapping mapping(name, mode);
|
||||
mapped_region mapped(mapping, (mapped_region::accessmode_t)mode, 0, size, addr);
|
||||
|
||||
//Now swap mapped region
|
||||
m_mapped_region.swap(mapped);
|
||||
|
||||
//Execute atomic functor
|
||||
construct_func(m_mapped_region, created);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MAPPED_FILE_HPP
|
||||
|
||||
@@ -1,505 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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_memory_mappable_HPP
|
||||
#define BOOST_INTERPROCESS_memory_mappable_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <string>
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
# include <boost/interprocess/sync/win32/win32_sync_primitives.hpp>
|
||||
#else
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <fcntl.h>
|
||||
# include <sys/mman.h> //mmap, off64_t
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
/*!\file
|
||||
Describes memory_mappable and mapped region classes
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
/*!A base class for all objects that can be memory mapped. The derived
|
||||
classes must initialize this base class with a mapping handle and the
|
||||
mode of the mapping handle.*/
|
||||
class memory_mappable
|
||||
{
|
||||
//Non-copyable
|
||||
memory_mappable(const memory_mappable &);
|
||||
memory_mappable &operator=(const memory_mappable &);
|
||||
|
||||
public:
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
typedef void * mapping_handle_t;
|
||||
typedef long long mapping_offset_t;
|
||||
enum { invalid_handle = 0 };
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
typedef int mapping_handle_t;
|
||||
typedef off64_t mapping_offset_t;
|
||||
enum { invalid_handle = -1 };
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
typedef enum { read_only = 0x01
|
||||
, read_write = 0x02
|
||||
, invalid_mode = 0xff
|
||||
} accessmode_t;
|
||||
|
||||
/*!Constructor. Initializes internal mapping handle to an invalid value.
|
||||
Does not throw.*/
|
||||
memory_mappable()
|
||||
: m_handle(mapping_handle_t(invalid_handle))
|
||||
{}
|
||||
|
||||
/*!Stores the mapping handle and the mode of the handle. This method must be called
|
||||
by the derived class. The assigned handle will be used to create mapped regions.
|
||||
Does not throw.*/
|
||||
void assign_data(mapping_handle_t handle, accessmode_t mode)
|
||||
{ m_handle = handle; m_mode = mode; }
|
||||
|
||||
/*!Stores the mapping handle and the mode of the handle. This method must be called
|
||||
by the derived class and the assigned handle will be used to create mapped regions.
|
||||
memory_mappable does not duplicate the handle using operating system functions. Just
|
||||
stores the handle internally. Does not throw.*/
|
||||
mapping_handle_t get_mapping_handle() const
|
||||
{ return m_handle; }
|
||||
|
||||
/*!Returns the registered access mode. Does not throw.*/
|
||||
accessmode_t get_mode() const
|
||||
{ return m_mode; }
|
||||
|
||||
/*!Virtual pure destructor. memory_mappable does not destroy the handle. This must
|
||||
be done by the derived class. Does not throw.*/
|
||||
virtual ~memory_mappable() = 0;
|
||||
|
||||
private:
|
||||
mapping_handle_t m_handle;
|
||||
accessmode_t m_mode;
|
||||
};
|
||||
|
||||
inline memory_mappable::~memory_mappable()
|
||||
{}
|
||||
|
||||
/*!The mapped_region class represents a portion or region created from a
|
||||
memory_mappable object.*/
|
||||
class mapped_region
|
||||
{
|
||||
//Non-copyable
|
||||
mapped_region(const mapped_region &);
|
||||
mapped_region &operator=(const mapped_region &);
|
||||
|
||||
typedef memory_mappable::mapping_offset_t mapping_offset_t;
|
||||
|
||||
public:
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
typedef long long offset_t;
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
typedef off64_t offset_t;
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
typedef enum { read_only = 0x01
|
||||
, read_write = 0x02
|
||||
, copy_on_write = 0x03
|
||||
, invalid_mode = 0xff
|
||||
} accessmode_t;
|
||||
|
||||
|
||||
/*!Creates a mapping region of the mapped memory "mapping", starting in
|
||||
offset "offset", and the mapping's size will be "size". The mapping
|
||||
can be opened for read-only "memory_mappable::read_only" or read-write
|
||||
"memory_mappable::read_write.*/
|
||||
mapped_region(const memory_mappable& mapping
|
||||
,mapped_region::accessmode_t mode
|
||||
,offset_t offset = 0
|
||||
,std::size_t size = 0
|
||||
,const void *address = 0);
|
||||
|
||||
/*!Default constructor. Address and size and offset will be 0. Does not throw*/
|
||||
mapped_region();
|
||||
|
||||
/*!Destroys the mapped region. Does not throw*/
|
||||
~mapped_region();
|
||||
|
||||
/*!Returns the size of the mapping. Never throws.*/
|
||||
std::size_t get_size() const;
|
||||
|
||||
/*!Returns the base address of the mapping. Never throws.*/
|
||||
void* get_address() const;
|
||||
|
||||
/*!Returns the offset of the mapping from the beginning of the
|
||||
mapped memory. Never throws.*/
|
||||
offset_t get_offset() const;
|
||||
|
||||
/*!Flushes to the disk a byte range within the mapped memory.
|
||||
Never throws*/
|
||||
bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0);
|
||||
|
||||
/*!Swaps the mapped_region with another mapped region*/
|
||||
void swap(mapped_region &other);
|
||||
|
||||
static std::size_t get_page_size();
|
||||
|
||||
private:
|
||||
/*!Closes a previously opened memory mapping. Never throws.*/
|
||||
void priv_close();
|
||||
|
||||
void* m_base;
|
||||
std::size_t m_size;
|
||||
offset_t m_offset;
|
||||
// #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
offset_t m_extra_offset;
|
||||
// #else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
// #endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
};
|
||||
|
||||
inline void swap(mapped_region &x, mapped_region &y)
|
||||
{ x.swap(y); }
|
||||
|
||||
inline mapped_region::mapped_region()
|
||||
: m_base(0), m_size(0), m_offset(0)
|
||||
// #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
, m_extra_offset(0)
|
||||
// #else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
// empty
|
||||
// #endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
{}
|
||||
|
||||
inline mapped_region::~mapped_region()
|
||||
{ this->priv_close(); }
|
||||
|
||||
inline std::size_t mapped_region::get_size() const
|
||||
{ return m_size; }
|
||||
|
||||
inline mapped_region::offset_t mapped_region::get_offset() const
|
||||
{ return m_offset; }
|
||||
|
||||
inline void* mapped_region::get_address() const
|
||||
{ return m_base; }
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline mapped_region::mapped_region
|
||||
(const memory_mappable &mapping
|
||||
,mapped_region::accessmode_t mode
|
||||
,mapped_region::offset_t offset
|
||||
,std::size_t size
|
||||
,const void *address)
|
||||
: m_base(0)
|
||||
{
|
||||
//Update mapping size if the user does not specify it
|
||||
if(size == 0){
|
||||
__int64 total_size;
|
||||
if(!winapi::get_file_size(mapping.get_mapping_handle(), total_size)){
|
||||
error_info err(winapi::get_last_error());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
if(total_size > (__int64)((std::size_t)(-1))){
|
||||
error_info err(size_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
size = static_cast<std::size_t>(total_size - offset);
|
||||
}
|
||||
|
||||
//Set accesses
|
||||
unsigned long file_map_access = 0;
|
||||
unsigned long map_access = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case read_only:
|
||||
file_map_access |= winapi::page_readonly;
|
||||
map_access |= winapi::file_map_read;
|
||||
break;
|
||||
case read_write:
|
||||
file_map_access |= winapi::page_readwrite;
|
||||
map_access |= winapi::file_map_write;
|
||||
break;
|
||||
case copy_on_write:
|
||||
file_map_access |= winapi::page_writecopy;
|
||||
file_map_access |= winapi::file_map_copy;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//Create file mapping
|
||||
memory_mappable::mapping_handle_t hnd =
|
||||
winapi::create_file_mapping
|
||||
(mapping.get_mapping_handle(), file_map_access, 0, 0, 0);
|
||||
|
||||
//Check if all is correct
|
||||
if(!hnd){
|
||||
error_info err = winapi::get_last_error();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//We can't map any offset so we have to obtain system's
|
||||
//memory granularity
|
||||
unsigned long granularity = 0;
|
||||
unsigned long foffset_low;
|
||||
unsigned long foffset_high;
|
||||
|
||||
winapi::system_info info;
|
||||
get_system_info(&info);
|
||||
granularity = info.dwAllocationGranularity;
|
||||
|
||||
//Now we calculate valid offsets
|
||||
foffset_low = (unsigned long)(offset / granularity) * granularity;
|
||||
foffset_high = (unsigned long)(((offset / granularity) * granularity) >> 32);
|
||||
|
||||
//We calculate the difference between demanded and valid offset
|
||||
m_extra_offset = (offset - (offset / granularity) * granularity);
|
||||
|
||||
//Store user values in memory
|
||||
m_offset = offset;
|
||||
m_size = size;
|
||||
|
||||
//Update the mapping address
|
||||
if(address){
|
||||
address = static_cast<const char*>(address) - m_extra_offset;
|
||||
}
|
||||
|
||||
//Map with new offsets and size
|
||||
m_base = winapi::map_view_of_file_ex
|
||||
(hnd,
|
||||
map_access,
|
||||
foffset_high,
|
||||
foffset_low,
|
||||
static_cast<std::size_t>(m_extra_offset + m_size),
|
||||
(void*)address);
|
||||
|
||||
//We don't need the file mapping anymore
|
||||
winapi::close_handle(hnd);
|
||||
|
||||
//Check error
|
||||
if(!m_base){
|
||||
error_info err = winapi::get_last_error();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Calculate new base for the user
|
||||
m_base = static_cast<char*>(m_base) + m_extra_offset;
|
||||
}
|
||||
|
||||
inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes)
|
||||
{
|
||||
//Check some errors
|
||||
if(m_base == 0)
|
||||
return false;
|
||||
|
||||
if(mapping_offset >= m_size || (mapping_offset + numbytes) > m_size){
|
||||
return false;
|
||||
}
|
||||
|
||||
//Update flush size if the user does not provide it
|
||||
if(numbytes == 0){
|
||||
numbytes = m_size - mapping_offset;
|
||||
}
|
||||
|
||||
//Flush it all
|
||||
return 0 == winapi::flush_view_of_file
|
||||
(static_cast<char*>(m_base)+mapping_offset,
|
||||
static_cast<std::size_t>(numbytes));
|
||||
}
|
||||
|
||||
inline void mapped_region::priv_close()
|
||||
{
|
||||
if(m_base){
|
||||
this->flush();
|
||||
winapi::unmap_view_of_file(static_cast<char*>(m_base) - m_extra_offset);
|
||||
m_base = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::size_t get_page_size()
|
||||
{
|
||||
winapi::system_info info;
|
||||
get_system_info(&info);
|
||||
return std::size_t(info.dwAllocationGranularity);
|
||||
}
|
||||
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline mapped_region::mapped_region
|
||||
(const memory_mappable &mapping,
|
||||
mapped_region::accessmode_t mode,
|
||||
mapped_region::mapping_offset_t offset,
|
||||
std::size_t size,
|
||||
const void *address)
|
||||
: m_base(MAP_FAILED)
|
||||
{
|
||||
if(size == 0){
|
||||
mapping_offset_t filesize = lseek64(mapping.get_mapping_handle(), offset, SEEK_END);
|
||||
|
||||
if(filesize == -1 ){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
if(offset >= filesize){
|
||||
error_info err(size_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
filesize -= offset;
|
||||
|
||||
size = (size_t)filesize;
|
||||
if((mapping_offset_t)size != filesize){
|
||||
error_info err(size_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Create new mapping
|
||||
int prot = 0;
|
||||
int flags = 0;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case mapped_region::read_only:
|
||||
prot |= PROT_READ;
|
||||
flags |= MAP_SHARED;
|
||||
break;
|
||||
|
||||
case mapped_region::read_write:
|
||||
prot |= (PROT_WRITE | PROT_READ);
|
||||
flags |= MAP_SHARED;
|
||||
break;
|
||||
|
||||
case mapped_region::copy_on_write:
|
||||
prot |= PROT_READ;
|
||||
flags |= MAP_PRIVATE;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//We calculate the difference between demanded and valid offset
|
||||
std::size_t page_size = this->get_page_size();
|
||||
m_extra_offset = (offset - (offset / page_size) * page_size);
|
||||
|
||||
//Store user values in memory
|
||||
m_offset = offset;
|
||||
m_size = size;
|
||||
|
||||
//Update the mapping address
|
||||
if(address){
|
||||
address = static_cast<const char*>(address) - m_extra_offset;
|
||||
}
|
||||
|
||||
//Map it to the address space
|
||||
m_base = mmap64( (void*)address
|
||||
, static_cast<std::size_t>(m_extra_offset + m_size)
|
||||
, prot
|
||||
, flags
|
||||
, mapping.get_mapping_handle()
|
||||
, offset);
|
||||
|
||||
//Check if mapping was successful
|
||||
if(m_base == MAP_FAILED){
|
||||
error_info err = system_error_code();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Check for fixed mapping error
|
||||
if(address && (m_base != (void*)address)){
|
||||
error_info err = system_error_code();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Calculate new base for the user
|
||||
m_base = static_cast<char*>(m_base) + m_extra_offset;
|
||||
m_offset = offset;
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes)
|
||||
{
|
||||
if(mapping_offset >= m_size || (mapping_offset+numbytes)> m_size){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(numbytes == 0){
|
||||
numbytes = m_size - mapping_offset;
|
||||
}
|
||||
//Flush it all
|
||||
return msync(static_cast<char*>(m_base)+mapping_offset,
|
||||
numbytes, MS_SYNC) == 0;
|
||||
}
|
||||
|
||||
inline void mapped_region::priv_close()
|
||||
{
|
||||
if(m_base != MAP_FAILED){
|
||||
this->flush();
|
||||
munmap(static_cast<char*>(m_base) - m_extra_offset, m_size + m_extra_offset);
|
||||
m_base = MAP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::size_t mapped_region::get_page_size()
|
||||
{ return std::size_t(sysconf(_SC_PAGESIZE)); }
|
||||
|
||||
#endif //##if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline void mapped_region::swap(mapped_region &other)
|
||||
{
|
||||
detail::do_swap(this->m_base, other.m_base);
|
||||
detail::do_swap(this->m_size, other.m_size);
|
||||
detail::do_swap(this->m_offset, other.m_offset);
|
||||
// #if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
detail::do_swap(this->m_extra_offset, other.m_extra_offset);
|
||||
// #else
|
||||
// #endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!No-op functor*/
|
||||
struct null_mapped_region_function
|
||||
{
|
||||
bool operator()(const mapped_region ®ion, bool) const
|
||||
{ return true; }
|
||||
};
|
||||
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_memory_mappable_HPP
|
||||
|
||||
@@ -1,695 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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_MEMORY_HPP
|
||||
#define BOOST_INTERPROCESS_MEMORY_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
#include <boost/interprocess/detail/creation_tags.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <boost/interprocess/detail/utilities.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <boost/interprocess/sync/interprocess_mutex.hpp>
|
||||
#include <boost/interprocess/exceptions.hpp>
|
||||
#include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/interprocess/detail/global_lock.hpp>
|
||||
#include <boost/compatibility/cpp_c_headers/cstddef>
|
||||
#include <boost/interprocess/memory_mappable.hpp>
|
||||
//#include <boost/optional.hpp>
|
||||
//#include <boost/utility/in_place_factory.hpp>
|
||||
/*
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
# include <boost/interprocess/sync/win32/win32_sync_primitives.hpp>
|
||||
#else
|
||||
|
||||
# ifdef BOOST_HAS_UNISTD_H
|
||||
# include <fcntl.h> //O_CREAT, O_*...
|
||||
# include <sys/mman.h> //mmap
|
||||
# include <unistd.h> //ftruncate, close
|
||||
# include <semaphore.h> //sem_t* family, SEM_VALUE_MAX
|
||||
# include <string> //std::string
|
||||
# include <sys/stat.h> //mode_t, S_IRWXG, S_IRWXO, S_IRWXU,
|
||||
# else
|
||||
# error Unknown platform
|
||||
# endif
|
||||
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
*/
|
||||
|
||||
/*!\file
|
||||
Describes shared_memory class
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
/*!A class that wraps a shared memory mapping that can be used to
|
||||
create mapped regions from the mapped files*/
|
||||
class shared_memory_object : public memory_mappable
|
||||
{
|
||||
enum type_t { DoCreate, DoOpen, DoCreateOrOpen };
|
||||
public:
|
||||
|
||||
shared_memory_object();
|
||||
|
||||
/*!Creates a shared memory object with name "name" and size "size", with the access mode "mode"
|
||||
If the file previously exists, throws an error.*/
|
||||
shared_memory_object(detail::create_only_t, const char *name, memory_mappable::accessmode_t mode)
|
||||
{ this->priv_open_or_create(DoCreate, name, mode); }
|
||||
|
||||
/*!Tries to create a shared memory object with name "name" and size "size", with the
|
||||
access mode "mode". If the file previously exists, it tries to open it with mode "mode".
|
||||
Otherwise throws an error.*/
|
||||
shared_memory_object(detail::open_or_create_t, const char *name, memory_mappable::accessmode_t mode)
|
||||
{ this->priv_open_or_create(DoCreateOrOpen, name, mode); }
|
||||
|
||||
// Tries to open a shared memory object with name "name", with the access mode "mode".
|
||||
// If the file does not previously exist, it throws an error.
|
||||
shared_memory_object(detail::open_only_t, const char *name, memory_mappable::accessmode_t mode)
|
||||
{ this->priv_open_or_create(DoOpen, name, mode); }
|
||||
|
||||
// Erases a shared memory object from the system.
|
||||
static bool remove(const char *name);
|
||||
|
||||
//Sets the size of the shared memory mapping
|
||||
void truncate(memory_mappable::mapping_offset_t length);
|
||||
|
||||
// Closes the shared memory mapping. All mapped regions are still
|
||||
// valid after destruction. The shared memory object still exists and
|
||||
// can be newly opened.
|
||||
~shared_memory_object();
|
||||
|
||||
/*!Returns the name of the file.*/
|
||||
const char *get_name() const;
|
||||
|
||||
/*!Return access mode*/
|
||||
accessmode_t get_mode() const;
|
||||
|
||||
/*!Get mapping handle*/
|
||||
mapping_handle_t get_mapping_handle() const;
|
||||
|
||||
private:
|
||||
/*!Closes a previously opened file mapping. Never throws.*/
|
||||
void priv_close();
|
||||
|
||||
bool priv_open_or_create(type_t type, const char *filename,
|
||||
memory_mappable::accessmode_t mode);
|
||||
|
||||
std::string m_filename;
|
||||
};
|
||||
|
||||
inline shared_memory_object::~shared_memory_object()
|
||||
{ this->priv_close(); }
|
||||
|
||||
/*!Returns the name of the file.*/
|
||||
inline const char *shared_memory_object::get_name() const
|
||||
{ return m_filename.c_str(); }
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline bool shared_memory_object::priv_open_or_create
|
||||
(type_t type,
|
||||
const char *filename,
|
||||
memory_mappable::accessmode_t mode)
|
||||
{
|
||||
m_filename = filename;
|
||||
|
||||
//Make sure a temporary path is created for shared memory
|
||||
const unsigned long BufferSize = 512;
|
||||
|
||||
std::string shmfile;
|
||||
shmfile.resize(BufferSize);
|
||||
|
||||
unsigned long n = winapi::get_temp_path(BufferSize, &shmfile[0]);
|
||||
if(n > BufferSize){
|
||||
shmfile.resize(n);
|
||||
n = winapi::get_temp_path(n, &shmfile[0]);
|
||||
}
|
||||
|
||||
if(!n){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Remove final null.
|
||||
shmfile.resize(n);
|
||||
shmfile += "boost_interprocess\\";
|
||||
|
||||
if(!winapi::create_directory(shmfile.c_str(), 0)){
|
||||
unsigned long err = winapi::get_last_error();
|
||||
if(err != winapi::error_already_exists){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
shmfile += filename;
|
||||
|
||||
unsigned long file_access = 0;
|
||||
unsigned long file_creation_flags = 0;
|
||||
|
||||
//Set accesses
|
||||
if (mode == read_write){
|
||||
file_access |= winapi::generic_read | winapi::generic_write;
|
||||
}
|
||||
else if (mode == read_only){
|
||||
file_access |= winapi::generic_read;
|
||||
}
|
||||
|
||||
switch(type){
|
||||
case DoOpen:
|
||||
file_creation_flags = winapi::open_existing;
|
||||
break;
|
||||
case DoCreate:
|
||||
file_creation_flags = winapi::create_new;
|
||||
break;
|
||||
case DoCreateOrOpen:
|
||||
file_creation_flags = winapi::open_always;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Open file using windows API since we need the handle
|
||||
memory_mappable::mapping_handle_t hnd = winapi::create_file
|
||||
(shmfile.c_str(), file_access, file_creation_flags, winapi::file_attribute_temporary);
|
||||
|
||||
//Check for error
|
||||
if(hnd == winapi::invalid_handle_value){
|
||||
error_info err = winapi::get_last_error();
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
memory_mappable::assign_data(hnd, mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool shared_memory_object::remove(const char *filename)
|
||||
{
|
||||
try{
|
||||
//Make sure a temporary path is created for shared memory
|
||||
const unsigned long BufferSize = 512;
|
||||
|
||||
std::string shmfile;
|
||||
shmfile.resize(BufferSize);
|
||||
|
||||
unsigned long n = winapi::get_temp_path(BufferSize, &shmfile[0]);
|
||||
if(n > BufferSize){
|
||||
shmfile.resize(n);
|
||||
n = winapi::get_temp_path(n, &shmfile[0]);
|
||||
}
|
||||
|
||||
if(!n){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
//Remove final null.
|
||||
shmfile.resize(n);
|
||||
shmfile += "boost_interprocess\\";
|
||||
shmfile += filename;
|
||||
return std::remove(shmfile.c_str()) == 0;
|
||||
}
|
||||
catch(...){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::truncate(memory_mappable::mapping_offset_t length)
|
||||
{
|
||||
if(!winapi::set_file_pointer_ex( memory_mappable::get_mapping_handle(), length
|
||||
, 0, winapi::file_begin)){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
if(!winapi::set_end_of_file(memory_mappable::get_mapping_handle())){
|
||||
error_info err = winapi::get_last_error();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::priv_close()
|
||||
{
|
||||
if(memory_mappable::get_mapping_handle() != winapi::invalid_handle_value){
|
||||
winapi::close_handle(memory_mappable::get_mapping_handle());
|
||||
memory_mappable::assign_data
|
||||
(winapi::invalid_handle_value, memory_mappable::get_mode());
|
||||
}
|
||||
}
|
||||
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
inline bool shared_memory_object::priv_open_or_create
|
||||
(type_t type,
|
||||
const char *filename,
|
||||
memory_mappable::accessmode_t mode)
|
||||
{
|
||||
m_filename = filename;
|
||||
|
||||
//Create new mapping
|
||||
|
||||
int oflag = 0;
|
||||
if(mode == memory_mappable::read_only){
|
||||
oflag |= O_RDONLY;
|
||||
}
|
||||
else if(mode == memory_mappable::read_write){
|
||||
oflag |= O_RDWR;
|
||||
}
|
||||
else{
|
||||
error_info err(mode_error);
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
switch(type){
|
||||
case DoOpen:
|
||||
//No addition
|
||||
break;
|
||||
case DoCreate:
|
||||
oflag |= (O_CREAT | O_EXCL);
|
||||
break;
|
||||
case DoCreateOrOpen:
|
||||
oflag |= O_CREAT;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error_info err = other_error;
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
//Open file using windows API since we need the handle
|
||||
memory_mappable::mapping_handle_t hnd = shm_open
|
||||
(filename, oflag, S_IRWXO | S_IRWXG | S_IRWXU);
|
||||
|
||||
//Check for error
|
||||
if(hnd == -1){
|
||||
error_info err = errno;
|
||||
this->priv_close();
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
|
||||
memory_mappable::assign_data(hnd, mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool shared_memory_object::remove(const char *filename)
|
||||
{
|
||||
return 0 != shm_unlink(filename);
|
||||
}
|
||||
|
||||
inline void shared_memory_object::truncate(memory_mappable::mapping_offset_t length)
|
||||
{
|
||||
if(0 != ftruncate(memory_mappable::get_mapping_handle(), length)){
|
||||
error_info err(system_error_code());
|
||||
throw interprocess_exception(err);
|
||||
}
|
||||
}
|
||||
|
||||
inline void shared_memory_object::priv_close()
|
||||
{
|
||||
if(memory_mappable::get_mapping_handle() != -1){
|
||||
::close(memory_mappable::get_mapping_handle());
|
||||
memory_mappable::assign_data
|
||||
(-1, memory_mappable::get_mode());
|
||||
}
|
||||
}
|
||||
|
||||
#endif //##if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
|
||||
/*!A class that wraps basic shared memory management*/
|
||||
class shared_memory
|
||||
{
|
||||
//Non-copyable
|
||||
shared_memory();
|
||||
shared_memory(const shared_memory &);
|
||||
shared_memory &operator=(const shared_memory &);
|
||||
|
||||
enum type_t { DoCreate, DoOpen, DoCreateOrOpen };
|
||||
|
||||
public:
|
||||
|
||||
/*!Creates a shared memory segment with name "name", with size "size".
|
||||
If the segment was previously created it throws an error.
|
||||
The segment can be created in two modes: read-only "read_only" or read-write "read_write".
|
||||
The user can also specify the mapping address in "addr". If "addr" is 0,
|
||||
the operating system will choose the mapping address.
|
||||
|
||||
This function can throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc)*/
|
||||
shared_memory(detail::create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode = memory_mappable::read_write,
|
||||
const void *addr = 0);
|
||||
|
||||
/*!Opens a shared memory segment with name "name". If it was previously
|
||||
created throws an error.
|
||||
The segment can be opened in two modes: read-only "read_only" or read-write "read_write".
|
||||
The user can also specify the mapping address in "addr". If "addr" is 0,
|
||||
the operating system will choose the mapping address.
|
||||
|
||||
This function can throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc)*/
|
||||
shared_memory(detail::open_only_t,
|
||||
const char *name,
|
||||
memory_mappable::accessmode_t mode = memory_mappable::read_write,
|
||||
const void *addr = 0);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", and size "size" if
|
||||
the shared memory was not previously created. If it was previously
|
||||
created it tries to open it. User can specify the mapping address in "addr".
|
||||
The segment can be opened in two modes: read-only "read_only" or read-write "read_write".
|
||||
If "addr" is 0, the operating system will choose the mapping address.
|
||||
|
||||
This function can throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc)*/
|
||||
shared_memory(detail::open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode = memory_mappable::read_write,
|
||||
const void *addr = 0);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", with size "size".
|
||||
The user must also specify the mapping address in "addr". If "addr" is 0,
|
||||
the operating system will choose the mapping address.
|
||||
It also executes a copy of the functor "construct_func" atomically if
|
||||
the segment is created. The functor must have the following signature:
|
||||
|
||||
bool operator()(const segment_info_t * info, bool created)
|
||||
|
||||
"info" is an initialized segment info structure, and "created"
|
||||
must be "true". If the functor returns "false", or throws an error
|
||||
is supposed and the shared memory won't be created.
|
||||
The user must specify a destroy_func, that will be copied in this
|
||||
constructor and executed in the destructor, before unmapping the
|
||||
shared memory segment.
|
||||
The functor must have the following signature:
|
||||
|
||||
void operator()(const segment_info_t * info, bool last) const
|
||||
|
||||
"info" is an initialized segment info structure, and "last"
|
||||
indicates if this unmapping is the last unmapping so that
|
||||
there will be no no other processes attached to the segment.
|
||||
The functor must NOT throw.
|
||||
|
||||
This function can throw if copying any functor throws,
|
||||
the construct_func execution throws, and it
|
||||
will throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc) on any error*/
|
||||
template <class ConstructFunc>
|
||||
shared_memory(detail::create_only_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", and size "size" if
|
||||
the shared memory was not previously created. If it was previously
|
||||
created tries to open it.
|
||||
User must specify the mapping address in "addr". If "addr" is 0,
|
||||
the operating system will choose the mapping address.
|
||||
It also executes a copy of the functor "construct_func" atomically
|
||||
if the segment is opened. The functor must have the following signature:
|
||||
|
||||
bool operator()(const segment_info_t * info, bool created)
|
||||
|
||||
"info" is an initialized segment info structure, and "created"
|
||||
must be "false". If the functor returns "false", or throws an error
|
||||
is supposed and the shared memory won't be opened.
|
||||
The user must specify a destroy_func, that will be copied in this
|
||||
constructor and executed in the destructor, before unmapping the
|
||||
shared memory segment.
|
||||
The functor must have the following signature:
|
||||
|
||||
void operator()(const segment_info_t * info, bool last) const
|
||||
|
||||
"info" is an initialized segment info structure, and "last"
|
||||
indicates if this unmapping is the last unmapping so that
|
||||
there will be no no other processes attached to the segment.
|
||||
The functor must NOT throw.
|
||||
|
||||
This function can throw if copying any functor throws,
|
||||
the construct_func execution throws, and it
|
||||
will throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc) on any error*/
|
||||
template <class ConstructFunc>
|
||||
shared_memory(detail::open_only_t,
|
||||
const char *name,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_funcc);
|
||||
|
||||
/*!Creates a shared memory segment with name "name", and size "size" if
|
||||
the shared memory was not previously created. If it was previously
|
||||
created it tries to open it. User can specify the mapping address in "addr".
|
||||
If "addr" is 0, the operating system will choose the mapping address.
|
||||
It also executes the functor "construct_func" atomically if the segment is
|
||||
created or opened. The functor must have the following signature:
|
||||
|
||||
bool operator()(const segment_info_t * info, bool created)
|
||||
|
||||
"info" is an initialized segment info structure, and "created"
|
||||
will be "true" if the shared memory was created. If the functor
|
||||
returns "false", or throws an error is supposed and the
|
||||
shared memory won't be opened.
|
||||
The user must specify a destroy_func, that will be copied in this
|
||||
constructor and executed in the destructor, before unmapping the
|
||||
shared memory segment.
|
||||
The functor must have the following signature:
|
||||
|
||||
void operator()(const segment_info_t * info, bool last) const
|
||||
|
||||
"info" is an initialized segment info structure, and "last"
|
||||
indicates if this unmapping is the last unmapping so that
|
||||
there will be no no other processes attached to the segment.
|
||||
The functor must NOT throw.
|
||||
|
||||
This function can throw if copying any functor throws,
|
||||
the construct_func execution throws, and it
|
||||
will throw boost::inteprocess_exception and
|
||||
other standard exceptions derived from std::exception
|
||||
(like std::bad_alloc) on any error*/
|
||||
template <class ConstructFunc>
|
||||
shared_memory(detail::open_or_create_t,
|
||||
const char *name,
|
||||
std::size_t size,
|
||||
memory_mappable::accessmode_t mode,
|
||||
const void *addr,
|
||||
const ConstructFunc &construct_func);
|
||||
|
||||
/*!Destructor. Unmaps shared memory from process' address space.
|
||||
It also executes the destruction functor atomically if
|
||||
the user has registered that the destruction functor
|
||||
in the constructor of this class.
|
||||
Never throws.*/
|
||||
~shared_memory();
|
||||
|
||||
/*!Returns the size of the shared memory segment. Never throws.*/
|
||||
std::size_t get_size() const;
|
||||
|
||||
/*!Returns shared memory segment's address for this process.
|
||||
Never throws.*/
|
||||
void* get_address() const;
|
||||
|
||||
/*!Swaps the shared memory segment this shared_memory object
|
||||
manages with another managed by "other".
|
||||
Never throws.*/
|
||||
void swap(shared_memory &other);
|
||||
|
||||
/*!Returns the name of the shared memory segment used in the
|
||||
constructor. Never throws.*/
|
||||
const char *get_name() const;
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
typedef void * OS_handle_t;
|
||||
#else //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
typedef int OS_handle_t;
|
||||
#endif //#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
|
||||
/*!Returns the handle that identifies the shared memory
|
||||
segment in a operating system. This is operating system
|
||||
and implementation dependent and should be used only
|
||||
in special situations.
|
||||
Never throws.*/
|
||||
OS_handle_t get_OS_handle() const;
|
||||
|
||||
private:
|
||||
|
||||
template <class ConstructFunc>
|
||||
bool priv_open_or_create(type_t type, const char *name, std::size_t size,
|
||||
memory_mappable::accessmode_t mode, const void *addr,
|
||||
ConstructFunc construct_func);
|
||||
mapped_region m_mapped_region;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
inline shared_memory::shared_memory
|
||||
(detail::create_only_t, const char *name, std::size_t size,
|
||||
memory_mappable::accessmode_t mode, const void *addr)
|
||||
{
|
||||
this->priv_open_or_create(DoCreate, name, size, mode, addr, null_mapped_region_function());
|
||||
}
|
||||
|
||||
inline shared_memory::shared_memory
|
||||
(detail::open_only_t, const char *name,
|
||||
memory_mappable::accessmode_t mode, const void *addr)
|
||||
{
|
||||
this->priv_open_or_create(DoOpen, name, 0, mode, addr, null_mapped_region_function());
|
||||
}
|
||||
|
||||
inline shared_memory::shared_memory
|
||||
(detail::open_or_create_t, const char *name, std::size_t size,
|
||||
memory_mappable::accessmode_t mode, const void *addr)
|
||||
{
|
||||
this->priv_open_or_create(DoCreateOrOpen, name, size, mode, addr, null_mapped_region_function());
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
inline shared_memory::shared_memory
|
||||
(detail::create_only_t, const char *name, std::size_t size,
|
||||
memory_mappable::accessmode_t mode, const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
this->priv_open_or_create(DoCreate, name, size, mode, addr, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
inline shared_memory::shared_memory
|
||||
(detail::open_only_t, const char *name,
|
||||
memory_mappable::accessmode_t mode, const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
this->priv_open_or_create(DoOpen, name, 0, mode, addr, construct_func);
|
||||
}
|
||||
|
||||
template <class ConstructFunc>
|
||||
inline shared_memory::shared_memory
|
||||
(detail::open_or_create_t, const char *name, std::size_t size,
|
||||
memory_mappable::accessmode_t mode, const void *addr,
|
||||
const ConstructFunc &construct_func)
|
||||
{
|
||||
this->priv_open_or_create(DoCreateOrOpen, name, size, mode, addr, construct_func);
|
||||
}
|
||||
|
||||
inline shared_memory::~shared_memory()
|
||||
{}
|
||||
|
||||
inline std::size_t shared_memory::get_size() const
|
||||
{ return m_mapped_region.get_size(); }
|
||||
|
||||
inline void* shared_memory::get_address() const
|
||||
{ return m_mapped_region.get_address(); }
|
||||
|
||||
inline const char *shared_memory::get_name() const
|
||||
{ return m_name.c_str(); }
|
||||
|
||||
inline void shared_memory::swap(shared_memory &other)
|
||||
{
|
||||
this->m_name.swap(other.m_name);
|
||||
this->m_mapped_region.swap(other.m_mapped_region);
|
||||
}
|
||||
|
||||
inline void swap(shared_memory &x, shared_memory &y)
|
||||
{ x.swap(y); }
|
||||
|
||||
template <class ConstructFunc> inline
|
||||
bool shared_memory::priv_open_or_create
|
||||
(shared_memory::type_t type, const char *name, std::size_t size,
|
||||
memory_mappable::accessmode_t mode, const void *addr,
|
||||
ConstructFunc construct_func)
|
||||
{
|
||||
error_info err;
|
||||
|
||||
m_name = name;
|
||||
|
||||
//This global interprocess_mutex guarantees synchronized creation/open logic
|
||||
detail::global_lock mut;
|
||||
if(!mut.acquire()){
|
||||
#ifdef BOOST_NO_EXCEPTIONS
|
||||
return false;
|
||||
#else
|
||||
throw interprocess_exception(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Do some in-place construction
|
||||
bool created = false;
|
||||
switch(type){
|
||||
case DoOpen:
|
||||
{
|
||||
shared_memory_object mapping(open_only, name, memory_mappable::read_write);
|
||||
mapped_region region(mapping, (mapped_region::accessmode_t)mode, 0, size, addr);
|
||||
m_mapped_region.swap(region);
|
||||
}
|
||||
break;
|
||||
case DoCreateOrOpen:
|
||||
{
|
||||
try{
|
||||
shared_memory_object mapping(create_only, name, memory_mappable::read_write);
|
||||
mapping.truncate(size);
|
||||
mapped_region region(mapping, (mapped_region::accessmode_t)mode, 0, size, addr);
|
||||
m_mapped_region.swap(region);
|
||||
created = true;
|
||||
}
|
||||
catch(interprocess_exception &ex){
|
||||
if(ex.get_error_code() != already_exists_error){
|
||||
throw;
|
||||
}
|
||||
shared_memory_object mapping(open_only, name, memory_mappable::read_write);
|
||||
mapped_region region(mapping, (mapped_region::accessmode_t)mode, 0, size, addr);
|
||||
m_mapped_region.swap(region);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DoCreate:
|
||||
{
|
||||
shared_memory_object mapping(create_only, name, memory_mappable::read_write);
|
||||
mapping.truncate(size);
|
||||
mapped_region region(mapping, (mapped_region::accessmode_t)mode, 0, size, addr);
|
||||
m_mapped_region.swap(region);
|
||||
created = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//Execute atomic functor
|
||||
construct_func(m_mapped_region, created);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //BOOST_INTERPROCESS_MEMORY_HPP
|
||||
@@ -1,419 +0,0 @@
|
||||
// I, Howard Hinnant, hereby place this code in the public domain.
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
//Disable "multiple copy constructors specified"
|
||||
#pragma warning (disable : 4521)
|
||||
#pragma warning (disable : 4522)
|
||||
#endif
|
||||
|
||||
#include <boost/compressed_pair.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost_ext{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct two {char _[2];};
|
||||
|
||||
namespace pointer_type_imp
|
||||
{
|
||||
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(typename U::pointer* = 0);
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename pointer_type_imp::pointer_type<T,
|
||||
typename boost::remove_reference<D>::type>::type type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct default_delete
|
||||
{
|
||||
default_delete() {}
|
||||
template <class U> default_delete(const default_delete<U>&) {}
|
||||
void operator() (T* ptr) const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(T) > 0);
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_delete<T[]>
|
||||
{
|
||||
void operator() (T* ptr) const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(T) > 0);
|
||||
delete [] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, std::size_t N>
|
||||
struct default_delete<T[N]>
|
||||
{
|
||||
void operator() (T* ptr, std::size_t) const
|
||||
{
|
||||
BOOST_STATIC_ASSERT(sizeof(T) > 0);
|
||||
delete [] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class D> class unique_ptr;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class T> struct unique_ptr_error;
|
||||
|
||||
template <class T, class D>
|
||||
struct unique_ptr_error<const unique_ptr<T, D> >
|
||||
{
|
||||
typedef unique_ptr<T, D> type;
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
template <class T, class D = default_delete<T> >
|
||||
class unique_ptr
|
||||
{
|
||||
struct nat {int for_bool_;};
|
||||
typedef typename boost::add_reference<D>::type deleter_reference;
|
||||
typedef typename boost::add_reference<const D>::type deleter_const_reference;
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
typedef typename detail::pointer_type<T, D>::type pointer;
|
||||
|
||||
// constructors
|
||||
unique_ptr() : ptr_(pointer()) {}
|
||||
explicit unique_ptr(pointer p) : ptr_(p) {}
|
||||
unique_ptr(pointer p, typename boost::mpl::if_<
|
||||
boost::is_reference<D>,
|
||||
D,
|
||||
typename boost::add_reference<const D>::type>::type d)
|
||||
: ptr_(p, d) {}
|
||||
unique_ptr(const unique_ptr& u)
|
||||
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
|
||||
|
||||
template <class U, class E>
|
||||
unique_ptr(const unique_ptr<U, E>& u,
|
||||
typename boost::enable_if_c<
|
||||
boost::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
|
||||
boost::is_convertible<E, D>::value &&
|
||||
(
|
||||
!boost::is_reference<D>::value ||
|
||||
boost::is_same<D, E>::value
|
||||
)
|
||||
,
|
||||
nat
|
||||
>::type = nat())
|
||||
: ptr_(const_cast<unique_ptr<U,E>&>(u).release(), u.get_deleter()) {}
|
||||
|
||||
// destructor
|
||||
~unique_ptr() {reset();}
|
||||
|
||||
// assignment
|
||||
unique_ptr& operator=(const unique_ptr& cu)
|
||||
{
|
||||
unique_ptr& u = const_cast<unique_ptr&>(cu);
|
||||
reset(u.release());
|
||||
ptr_.second() = u.get_deleter();
|
||||
return *this;
|
||||
}
|
||||
template <class U, class E>
|
||||
unique_ptr& operator=(const unique_ptr<U, E>& cu)
|
||||
{
|
||||
unique_ptr<U, E>& u = const_cast<unique_ptr<U, E>&>(cu);
|
||||
reset(u.release());
|
||||
ptr_.second() = u.get_deleter();
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(int nat::*)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// observers
|
||||
typename boost::add_reference<T>::type operator*() const {return *ptr_.first();}
|
||||
pointer operator->() const {return ptr_.first();}
|
||||
pointer get() const {return ptr_.first();}
|
||||
deleter_reference get_deleter() {return ptr_.second();}
|
||||
deleter_const_reference get_deleter() const {return ptr_.second();}
|
||||
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
|
||||
|
||||
// modifiers
|
||||
pointer release()
|
||||
{
|
||||
pointer tmp = ptr_.first();
|
||||
ptr_.first() = pointer();
|
||||
return tmp;
|
||||
}
|
||||
void reset(pointer p = pointer())
|
||||
{
|
||||
if (ptr_.first() != p)
|
||||
{
|
||||
if (ptr_.first())
|
||||
ptr_.second()(ptr_.first());
|
||||
ptr_.first() = p;
|
||||
}
|
||||
}
|
||||
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
|
||||
private:
|
||||
boost::compressed_pair<pointer, D> ptr_;
|
||||
|
||||
unique_ptr(unique_ptr&);
|
||||
template <class U, class E> unique_ptr(unique_ptr<U, E>&);
|
||||
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
|
||||
|
||||
|
||||
unique_ptr& operator=(unique_ptr&);
|
||||
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&);
|
||||
template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
class unique_ptr<T[], D>
|
||||
{
|
||||
struct nat {int for_bool_;};
|
||||
typedef typename boost::add_reference<D>::type deleter_reference;
|
||||
typedef typename boost::add_reference<const D>::type deleter_const_reference;
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
typedef typename detail::pointer_type<T, D>::type pointer;
|
||||
|
||||
// constructors
|
||||
unique_ptr() : ptr_(pointer()) {}
|
||||
explicit unique_ptr(pointer p) : ptr_(p) {}
|
||||
unique_ptr(pointer p, typename boost::mpl::if_<
|
||||
boost::is_reference<D>,
|
||||
D,
|
||||
typename boost::add_reference<const D>::type>::type d)
|
||||
: ptr_(p, d) {}
|
||||
unique_ptr(const unique_ptr& u)
|
||||
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
|
||||
|
||||
// destructor
|
||||
~unique_ptr() {reset();}
|
||||
|
||||
// assignment
|
||||
unique_ptr& operator=(const unique_ptr& cu)
|
||||
{
|
||||
unique_ptr& u = const_cast<unique_ptr&>(cu);
|
||||
reset(u.release());
|
||||
ptr_.second() = u.get_deleter();
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(int nat::*)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// observers
|
||||
typename boost::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
|
||||
pointer get() const {return ptr_.first();}
|
||||
deleter_reference get_deleter() {return ptr_.second();}
|
||||
deleter_const_reference get_deleter() const {return ptr_.second();}
|
||||
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
|
||||
|
||||
// modifiers
|
||||
pointer release()
|
||||
{
|
||||
pointer tmp = ptr_.first();
|
||||
ptr_.first() = pointer();
|
||||
return tmp;
|
||||
}
|
||||
void reset(pointer p = pointer())
|
||||
{
|
||||
if (ptr_.first() != p)
|
||||
{
|
||||
if (ptr_.first())
|
||||
ptr_.second()(ptr_.first());
|
||||
ptr_.first() = p;
|
||||
}
|
||||
}
|
||||
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
|
||||
private:
|
||||
boost::compressed_pair<pointer, D> ptr_;
|
||||
|
||||
template <class U, class E> unique_ptr(U p, E,
|
||||
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
|
||||
template <class U> explicit unique_ptr(U,
|
||||
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
|
||||
|
||||
unique_ptr(unique_ptr&);
|
||||
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
|
||||
|
||||
unique_ptr& operator=(unique_ptr&);
|
||||
template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
|
||||
};
|
||||
|
||||
template <class T, class D, std::size_t N>
|
||||
class unique_ptr<T[N], D>
|
||||
{
|
||||
struct nat {int for_bool_;};
|
||||
typedef typename boost::add_reference<D>::type deleter_reference;
|
||||
typedef typename boost::add_reference<const D>::type deleter_const_reference;
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
typedef typename detail::pointer_type<T, D>::type pointer;
|
||||
static const std::size_t size = N;
|
||||
|
||||
// constructors
|
||||
unique_ptr() : ptr_(pointer()) {}
|
||||
explicit unique_ptr(pointer p) : ptr_(p) {}
|
||||
unique_ptr(pointer p, typename boost::mpl::if_<
|
||||
boost::is_reference<D>,
|
||||
D,
|
||||
typename boost::add_reference<const D>::type>::type d)
|
||||
: ptr_(p, d) {}
|
||||
unique_ptr(const unique_ptr& u)
|
||||
: ptr_(const_cast<unique_ptr&>(u).release(), u.get_deleter()) {}
|
||||
|
||||
// destructor
|
||||
~unique_ptr() {reset();}
|
||||
|
||||
// assignment
|
||||
unique_ptr& operator=(const unique_ptr& cu)
|
||||
{
|
||||
unique_ptr& u = const_cast<unique_ptr&>(cu);
|
||||
reset(u.release());
|
||||
ptr_.second() = u.get_deleter();
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(int nat::*)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// observers
|
||||
typename boost::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
|
||||
pointer get() const {return ptr_.first();}
|
||||
deleter_reference get_deleter() {return ptr_.second();}
|
||||
deleter_const_reference get_deleter() const {return ptr_.second();}
|
||||
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
|
||||
|
||||
// modifiers
|
||||
pointer release()
|
||||
{
|
||||
pointer tmp = ptr_.first();
|
||||
ptr_.first() = pointer();
|
||||
return tmp;
|
||||
}
|
||||
void reset(pointer p = pointer())
|
||||
{
|
||||
if (ptr_.first() != p)
|
||||
{
|
||||
if (ptr_.first())
|
||||
ptr_.second()(ptr_.first(), N);
|
||||
ptr_.first() = p;
|
||||
}
|
||||
}
|
||||
void swap(unique_ptr& u) {ptr_.swap(u.ptr_);}
|
||||
private:
|
||||
boost::compressed_pair<pointer, D> ptr_;
|
||||
|
||||
template <class U, class E> unique_ptr(U p, E,
|
||||
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
|
||||
template <class U> explicit unique_ptr(U,
|
||||
typename boost::enable_if<boost::is_convertible<U, pointer> >::type* = 0);
|
||||
|
||||
unique_ptr(unique_ptr&);
|
||||
template <class U> unique_ptr(U&, typename detail::unique_ptr_error<U>::type = 0);
|
||||
|
||||
unique_ptr& operator=(unique_ptr&);
|
||||
template <class U> typename detail::unique_ptr_error<U>::type operator=(U&);
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
inline
|
||||
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) {x.swap(y);}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() == y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() != y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() < y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() <= y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() > y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() >= y.get();}
|
||||
|
||||
template <class T, class D>
|
||||
inline
|
||||
unique_ptr<T, D>
|
||||
move(unique_ptr<T, D>& p)
|
||||
{
|
||||
return unique_ptr<T, D>(p.release(), p.get_deleter());
|
||||
}
|
||||
|
||||
} //namespace boost_ext{
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
@@ -1,407 +0,0 @@
|
||||
// I, Howard Hinnant, hereby place this code in the public domain.
|
||||
|
||||
namespace std { namespace detail {
|
||||
|
||||
template <bool cond, class Then, class Else>
|
||||
struct select
|
||||
{
|
||||
typedef Then type;
|
||||
};
|
||||
|
||||
template <class Then, class Else>
|
||||
struct select<false, Then, Else>
|
||||
{
|
||||
typedef Else type;
|
||||
};
|
||||
|
||||
template <bool b, class T = void> struct restrict_to {};
|
||||
template <class T> struct restrict_to<true, T> {typedef T type;};
|
||||
|
||||
using boost::compressed_pair;
|
||||
|
||||
struct two {char _[2];};
|
||||
|
||||
namespace pointer_type_imp
|
||||
{
|
||||
|
||||
template <class U> static two test(...);
|
||||
template <class U> static char test(typename U::pointer* = 0);
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <class T, class D>
|
||||
struct pointer_type
|
||||
{
|
||||
typedef typename pointer_type_imp::pointer_type<T,
|
||||
typename tr1::remove_reference<D>::type>::type type;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template <class T>
|
||||
struct default_delete
|
||||
{
|
||||
default_delete() {}
|
||||
template <class U> default_delete(const default_delete<U>&) {}
|
||||
void operator() (T* ptr) const
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "Can't delete pointer to incomplete type");
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_delete<T[]>
|
||||
{
|
||||
void operator() (T* ptr) const
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "Can't delete pointer to incomplete type");
|
||||
delete [] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, std::size_t N>
|
||||
struct default_delete<T[N]>
|
||||
{
|
||||
void operator() (T* ptr, std::size_t) const
|
||||
{
|
||||
static_assert(sizeof(T) > 0, "Can't delete pointer to incomplete type");
|
||||
delete [] ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class D = default_delete<T> >
|
||||
class unique_ptr
|
||||
{
|
||||
struct nat {int for_bool_;};
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
typedef typename detail::pointer_type<T, D>::type pointer;
|
||||
|
||||
// constructors
|
||||
unique_ptr() : ptr_(pointer()) {}
|
||||
explicit unique_ptr(pointer p) : ptr_(p) {}
|
||||
unique_ptr(pointer p, typename detail::select<
|
||||
tr1::is_reference<D>::value,
|
||||
D,
|
||||
const D&>::type d)
|
||||
: ptr_(p, d) {}
|
||||
unique_ptr(pointer p, typename tr1::remove_reference<D>::type&& d)
|
||||
: ptr_(p, std::move(d))
|
||||
{
|
||||
static_assert(!tr1::is_reference<D>::value, "rvalue deleter bound to reference");
|
||||
}
|
||||
unique_ptr(unique_ptr&& u)
|
||||
: ptr_(u.release(), std::forward<D>(u.get_deleter())) {}
|
||||
template <class U, class E>
|
||||
unique_ptr(unique_ptr<U, E>&& u,
|
||||
typename detail::restrict_to<
|
||||
tr1::is_convertible<typename unique_ptr<U, E>::pointer, pointer>::value &&
|
||||
tr1::is_convertible<E, D>::value &&
|
||||
(
|
||||
!tr1::is_reference<D>::value ||
|
||||
tr1::is_same<D, E>::value
|
||||
)
|
||||
,
|
||||
nat
|
||||
>::type = nat())
|
||||
: ptr_(u.release(), std::forward<D>(u.get_deleter())) {}
|
||||
|
||||
// destructor
|
||||
~unique_ptr() {reset();}
|
||||
|
||||
// assignment
|
||||
unique_ptr& operator=(unique_ptr&& u)
|
||||
{
|
||||
reset(u.release());
|
||||
ptr_.second() = std::move(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
template <class U, class E>
|
||||
unique_ptr& operator=(unique_ptr<U, E>&& u)
|
||||
{
|
||||
reset(u.release());
|
||||
ptr_.second() = std::move(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(int nat::*)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// observers
|
||||
typename tr1::add_reference<T>::type operator*() const {return *ptr_.first();}
|
||||
pointer operator->() const {return ptr_.first();}
|
||||
pointer get() const {return ptr_.first();}
|
||||
D& get_deleter() {return ptr_.second();}
|
||||
const D& get_deleter() const {return ptr_.second();}
|
||||
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
|
||||
|
||||
// modifiers
|
||||
pointer release()
|
||||
{
|
||||
pointer tmp = ptr_.first();
|
||||
ptr_.first() = pointer();
|
||||
return tmp;
|
||||
}
|
||||
void reset(pointer p = pointer())
|
||||
{
|
||||
if (ptr_.first() != p)
|
||||
{
|
||||
if (ptr_.first())
|
||||
ptr_.second()(ptr_.first());
|
||||
ptr_.first() = p;
|
||||
}
|
||||
}
|
||||
void swap(unique_ptr&& u) {ptr_.swap(u.ptr_);}
|
||||
private:
|
||||
detail::compressed_pair<pointer, D> ptr_;
|
||||
|
||||
unique_ptr(const unique_ptr&);
|
||||
template <class U, class E> unique_ptr(const unique_ptr<U, E>&);
|
||||
unique_ptr& operator=(const unique_ptr&);
|
||||
template <class U, class E> unique_ptr& operator=(const unique_ptr<U, E>&);
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
class unique_ptr<T[], D>
|
||||
{
|
||||
struct nat {int for_bool_;};
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
typedef typename detail::pointer_type<T, D>::type pointer;
|
||||
|
||||
// constructors
|
||||
unique_ptr() : ptr_(pointer()) {}
|
||||
explicit unique_ptr(pointer p) : ptr_(p) {}
|
||||
unique_ptr(pointer p, typename detail::select<
|
||||
tr1::is_reference<D>::value,
|
||||
D,
|
||||
const D&>::type d)
|
||||
: ptr_(p, d) {}
|
||||
unique_ptr(pointer p, typename tr1::remove_reference<D>::type&& d)
|
||||
: ptr_(p, std::move(d))
|
||||
{
|
||||
static_assert(!tr1::is_reference<D>::value, "rvalue deleter bound to reference");
|
||||
}
|
||||
unique_ptr(unique_ptr&& u)
|
||||
: ptr_(u.release(), std::forward<D>(u.get_deleter())) {}
|
||||
|
||||
// destructor
|
||||
~unique_ptr() {reset();}
|
||||
|
||||
// assignment
|
||||
unique_ptr& operator=(unique_ptr&& u)
|
||||
{
|
||||
reset(u.release());
|
||||
ptr_.second() = std::move(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(int nat::*)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// observers
|
||||
typename tr1::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
|
||||
pointer get() const {return ptr_.first();}
|
||||
D& get_deleter() {return ptr_.second();}
|
||||
const D& get_deleter() const {return ptr_.second();}
|
||||
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
|
||||
|
||||
// modifiers
|
||||
pointer release()
|
||||
{
|
||||
pointer tmp = ptr_.first();
|
||||
ptr_.first() = pointer();
|
||||
return tmp;
|
||||
}
|
||||
void reset(pointer p = pointer())
|
||||
{
|
||||
if (ptr_.first() != p)
|
||||
{
|
||||
if (ptr_.first())
|
||||
ptr_.second()(ptr_.first());
|
||||
ptr_.first() = p;
|
||||
}
|
||||
}
|
||||
void swap(unique_ptr&& u) {ptr_.swap(u.ptr_);}
|
||||
private:
|
||||
detail::compressed_pair<pointer, D> ptr_;
|
||||
|
||||
template <class U> unique_ptr(U p,
|
||||
typename detail::select<
|
||||
tr1::is_reference<D>::value,
|
||||
D,
|
||||
const D&>::type d,
|
||||
typename detail::restrict_to<tr1::is_convertible<U, pointer>::value>::type* = 0);
|
||||
template <class U> unique_ptr(U p, typename tr1::remove_reference<D>::type&& d,
|
||||
typename detail::restrict_to<tr1::is_convertible<U, pointer>::value>::type* = 0);
|
||||
template <class U> explicit unique_ptr(U,
|
||||
typename detail::restrict_to<tr1::is_convertible<U, pointer>::value>::type* = 0);
|
||||
unique_ptr(const unique_ptr&);
|
||||
unique_ptr& operator=(const unique_ptr&);
|
||||
};
|
||||
|
||||
template <class T, class D, std::size_t N>
|
||||
class unique_ptr<T[N], D>
|
||||
{
|
||||
struct nat {int for_bool_;};
|
||||
public:
|
||||
typedef T element_type;
|
||||
typedef D deleter_type;
|
||||
typedef typename detail::pointer_type<T, D>::type pointer;
|
||||
static const std::size_t size = N;
|
||||
|
||||
// constructors
|
||||
unique_ptr() : ptr_(pointer()) {}
|
||||
explicit unique_ptr(pointer p) : ptr_(p) {}
|
||||
unique_ptr(pointer p, typename detail::select<
|
||||
tr1::is_reference<D>::value,
|
||||
D,
|
||||
const D&>::type d)
|
||||
: ptr_(p, d) {}
|
||||
unique_ptr(pointer p, typename tr1::remove_reference<D>::type&& d)
|
||||
: ptr_(p, std::move(d))
|
||||
{
|
||||
static_assert(!tr1::is_reference<D>::value, "rvalue deleter bound to reference");
|
||||
}
|
||||
unique_ptr(unique_ptr&& u)
|
||||
: ptr_(u.release(), std::forward<D>(u.get_deleter())) {}
|
||||
|
||||
// destructor
|
||||
~unique_ptr() {reset();}
|
||||
|
||||
// assignment
|
||||
unique_ptr& operator=(unique_ptr&& u)
|
||||
{
|
||||
reset(u.release());
|
||||
ptr_.second() = std::move(u.get_deleter());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(int nat::*)
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// observers
|
||||
typename tr1::add_reference<T>::type operator[](std::size_t i) const {return ptr_.first()[i];}
|
||||
pointer get() const {return ptr_.first();}
|
||||
D& get_deleter() {return ptr_.second();}
|
||||
const D& get_deleter() const {return ptr_.second();}
|
||||
operator int nat::*() const {return ptr_.first() ? &nat::for_bool_ : 0;}
|
||||
|
||||
// modifiers
|
||||
pointer release()
|
||||
{
|
||||
pointer tmp = ptr_.first();
|
||||
ptr_.first() = pointer();
|
||||
return tmp;
|
||||
}
|
||||
void reset(pointer p = pointer())
|
||||
{
|
||||
if (ptr_.first() != p)
|
||||
{
|
||||
if (ptr_.first())
|
||||
ptr_.second()(ptr_.first(), N);
|
||||
ptr_.first() = p;
|
||||
}
|
||||
}
|
||||
void swap(unique_ptr&& u) {ptr_.swap(u.ptr_);}
|
||||
private:
|
||||
detail::compressed_pair<pointer, D> ptr_;
|
||||
|
||||
template <class U> unique_ptr(U p,
|
||||
typename detail::select<
|
||||
tr1::is_reference<D>::value,
|
||||
D,
|
||||
const D&>::type d,
|
||||
typename detail::restrict_to<tr1::is_convertible<U, pointer>::value>::type* = 0);
|
||||
template <class U> unique_ptr(U p, typename tr1::remove_reference<D>::type&& d,
|
||||
typename detail::restrict_to<tr1::is_convertible<U, pointer>::value>::type* = 0);
|
||||
template <class U> explicit unique_ptr(U,
|
||||
typename detail::restrict_to<tr1::is_convertible<U, pointer>::value>::type* = 0);
|
||||
unique_ptr(const unique_ptr&);
|
||||
unique_ptr& operator=(const unique_ptr&);
|
||||
};
|
||||
|
||||
template <class T, class D>
|
||||
inline
|
||||
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) {x.swap(y);}
|
||||
|
||||
template <class T, class D>
|
||||
inline
|
||||
void swap(unique_ptr<T, D>&& x, unique_ptr<T, D>& y) {x.swap(y);}
|
||||
|
||||
template <class T, class D>
|
||||
inline
|
||||
void swap(unique_ptr<T, D>& x, unique_ptr<T, D>&& y) {x.swap(y);}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() == y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() != y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator <(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() < y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() <= y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator >(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() > y.get();}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
inline
|
||||
bool
|
||||
operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y)
|
||||
{return x.get() >= y.get();}
|
||||
|
||||
} // std
|
||||
@@ -1,629 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998
|
||||
* Silicon Graphics Computer Systems, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation. Silicon Graphics makes no
|
||||
* representations about the suitability of this software for any
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This file comes from SGI's sstream file. Modified by Ion Gaztañaga 2005.
|
||||
// Changed internal SGI string to a generic, templatized string. Added efficient
|
||||
// internal buffer get/set/swap functions, so that we can obtain/establish the
|
||||
// internal buffer without any reallocation or copy. Kill those temporaries!
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!\file
|
||||
This file defines basic_stringbuf, basic_istringstream,
|
||||
basic_ostringstream, and basic_stringstreamclasses. These classes
|
||||
represent streamsbufs and streams whose sources or destinations are
|
||||
STL-like strings that can be swapped with external strings to avoid
|
||||
unnecessary allocations/copies.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_INTERPROCESS_STRINGSTREAM_HPP
|
||||
#define BOOST_INTERPROCESS_STRINGSTREAM_HPP
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#include <iosfwd>
|
||||
#include <ios>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string> // char traits
|
||||
#include <cstddef> // ptrdiff_t
|
||||
#include <boost/interprocess/interprocess_fwd.hpp>
|
||||
#include <assert.h>
|
||||
|
||||
namespace boost { namespace interprocess {
|
||||
|
||||
/*!A streambuf class that controls the transmission of elements to and from
|
||||
a basic_istringstream, basic_ostringstream or basic_stringstream.
|
||||
It holds a character string specified by CharString template parameter
|
||||
as its formatting buffer. The string must have contiguous storage, like
|
||||
std::string, boost::interprocess::string or boost::interprocess::basic_string*/
|
||||
template <class CharString, class CharTraits>
|
||||
class basic_stringbuf
|
||||
: public std::basic_streambuf<typename CharString::value_type, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef CharString string_type;
|
||||
typedef typename CharString::value_type char_type;
|
||||
typedef typename CharTraits::int_type int_type;
|
||||
typedef typename CharTraits::pos_type pos_type;
|
||||
typedef typename CharTraits::off_type off_type;
|
||||
typedef CharTraits traits_type;
|
||||
|
||||
private:
|
||||
typedef std::basic_streambuf<char_type, traits_type> base_t;
|
||||
|
||||
basic_stringbuf(const basic_stringbuf&);
|
||||
basic_stringbuf & operator =(const basic_stringbuf&);
|
||||
|
||||
public:
|
||||
/*!Constructor. Throws if string_type default constructor throws.*/
|
||||
explicit basic_stringbuf(std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: base_t(), m_mode(mode)
|
||||
{ this->set_pointers(); }
|
||||
|
||||
/*!Constructor. Throws if string_type(const VectorParameter ¶m) throws.*/
|
||||
template<class VectorParameter>
|
||||
explicit basic_stringbuf(const VectorParameter ¶m,
|
||||
std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: base_t(), m_mode(mode), m_string(param)
|
||||
{ this->set_pointers(); }
|
||||
|
||||
virtual ~basic_stringbuf(){}
|
||||
|
||||
public:
|
||||
|
||||
/*!Swaps the underlying string with the passed string.
|
||||
This function resets the read/write position in the stream.
|
||||
Does not throw.*/
|
||||
void swap_string(string_type &vect)
|
||||
{ m_string.swap(vect); this->set_pointers(); }
|
||||
|
||||
/*!Returns a const reference to the internal string.
|
||||
Does not throw.*/
|
||||
const string_type &string() const { return m_string; }
|
||||
|
||||
/*!Calls resize() method of the internal string.
|
||||
Resets the stream to the first position.
|
||||
Throws if the internals string's resize throws.*/
|
||||
void resize(typename string_type::size_type size)
|
||||
{ m_string.resize(size); this->set_pointers(); }
|
||||
|
||||
private:
|
||||
void set_pointers()
|
||||
{
|
||||
// The initial read position is the beginning of the string.
|
||||
if(m_mode & std::ios_base::in)
|
||||
this->setg(&m_string[0], &m_string[0], &m_string[m_string.size()]);
|
||||
|
||||
// The initial write position is the beginning of the string.
|
||||
if(m_mode & std::ios_base::out)
|
||||
this->setp(&m_string[0], &m_string[m_string.size()]);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual int_type underflow()
|
||||
{
|
||||
// Precondition: gptr() >= egptr(). Returns a character, if available.
|
||||
return this->gptr() != this->egptr()
|
||||
? CharTraits::to_int_type(*this->gptr())
|
||||
: CharTraits::eof();
|
||||
}
|
||||
|
||||
virtual int_type uflow()
|
||||
{
|
||||
// Precondition: gptr() >= egptr().
|
||||
if(this->gptr() != this->egptr()) {
|
||||
int_type c = CharTraits::to_int_type(*this->gptr());
|
||||
this->gbump(1);
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return CharTraits::eof();
|
||||
}
|
||||
|
||||
virtual int_type pbackfail(int_type c = CharTraits::eof())
|
||||
{
|
||||
if(this->gptr() != this->eback()) {
|
||||
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
|
||||
if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) {
|
||||
this->gbump(-1);
|
||||
return c;
|
||||
}
|
||||
else if(m_mode & std::ios_base::out) {
|
||||
this->gbump(-1);
|
||||
*this->gptr() = c;
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return CharTraits::eof();
|
||||
}
|
||||
else {
|
||||
this->gbump(-1);
|
||||
return CharTraits::not_eof(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
return CharTraits::eof();
|
||||
}
|
||||
|
||||
virtual int_type overflow(int_type c = CharTraits::eof())
|
||||
{
|
||||
if(m_mode & std::ios_base::out) {
|
||||
if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
|
||||
if(!(m_mode & std::ios_base::in)) {
|
||||
if(this->pptr() != this->epptr()) {
|
||||
*this->pptr() = CharTraits::to_char_type(c);
|
||||
this->pbump(1);
|
||||
return c;
|
||||
}
|
||||
else
|
||||
return CharTraits::eof();
|
||||
}
|
||||
else {
|
||||
// We're not using a special append buffer, just the string itself.
|
||||
if(this->pptr() == this->epptr()) {
|
||||
std::ptrdiff_t offset = this->gptr() - this->eback();
|
||||
m_string.push_back(CharTraits::to_char_type(c));
|
||||
this->setg(&m_string[0], &m_string[offset], &m_string[m_string.size()]);
|
||||
this->setp(&m_string[0], &m_string[m_string.size()]);
|
||||
this->pbump(static_cast<int>(m_string.size()));
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
*this->pptr() = CharTraits::to_char_type(c);
|
||||
this->pbump(1);
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // c is EOF, so we don't have to do anything
|
||||
return CharTraits::not_eof(c);
|
||||
}
|
||||
else // Overflow always fails if it's read-only.
|
||||
return CharTraits::eof();
|
||||
}
|
||||
|
||||
virtual std::streamsize xsputn(const char_type* s, std::streamsize n)
|
||||
{
|
||||
std::streamsize nwritten = 0;
|
||||
|
||||
if((m_mode & std::ios_base::out) && n > 0) {
|
||||
// If the put pointer is somewhere in the middle of the
|
||||
// string, then overwrite instead of append.
|
||||
assert(this->pbase() == &m_string[0]);
|
||||
// if(this->pbase() == &m_string[0]) {
|
||||
std::streamsize avail = static_cast<std::streamsize>(
|
||||
&m_string[m_string.size()] - this->pptr());
|
||||
if(avail > n) {
|
||||
CharTraits::copy(this->pptr(), s, n);
|
||||
this->pbump(n);
|
||||
return n;
|
||||
}
|
||||
else if(avail){
|
||||
CharTraits::copy(this->pptr(), s, avail);
|
||||
nwritten += avail;
|
||||
n -= avail;
|
||||
s += avail;
|
||||
}
|
||||
// }
|
||||
|
||||
// At this point we know we're appending.
|
||||
if(m_mode & std::ios_base::in) {
|
||||
std::ptrdiff_t get_offset = this->gptr() - this->eback();
|
||||
m_string.insert(m_string.end(), s, s + n);
|
||||
this->setg(&m_string[0], &m_string[get_offset], &m_string[m_string.size()]);
|
||||
this->setp(&m_string[0], &m_string[m_string.size()]);
|
||||
this->pbump(static_cast<int>(m_string.size()));
|
||||
}
|
||||
else {
|
||||
m_string.insert(m_string.end(), s, s + n);
|
||||
}
|
||||
nwritten += n;
|
||||
}
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
virtual std::streamsize xsputnc(char_type c, std::streamsize n)
|
||||
{
|
||||
std::streamsize nwritten = 0;
|
||||
|
||||
if((m_mode & std::ios_base::out) && n > 0) {
|
||||
// If the put pointer is somewhere in the middle of the string,
|
||||
// then overwrite instead of append.
|
||||
assert(this->pbase() == &m_string[0]);
|
||||
// if(this->pbase() == &m_string[0]) {
|
||||
std::streamsize avail = static_cast<std::streamsize>
|
||||
(&m_string[m_string.size()] - this->pptr());
|
||||
if(avail > n) {
|
||||
CharTraits::assign(this->pptr(), n, c);
|
||||
this->pbump(n);
|
||||
return n;
|
||||
}
|
||||
else if(avail){
|
||||
CharTraits::assign(this->pptr(), avail, c);
|
||||
nwritten += avail;
|
||||
n -= avail;
|
||||
}
|
||||
// }
|
||||
|
||||
// At this point we know we're appending.
|
||||
if(this->m_mode & std::ios_base::in) {
|
||||
std::streamsize get_offset = static_cast<std::streamsize>
|
||||
(this->gptr() - this->eback());
|
||||
m_string.insert(m_string.end(), n, c);
|
||||
this->setg(&m_string[0], &m_string[get_offset], &m_string[m_string.size()]);
|
||||
this->setp(&m_string[0], &m_string[m_string.size()]);
|
||||
this->pbump(static_cast<int>(m_string.size()));
|
||||
}
|
||||
else {
|
||||
m_string.insert(m_string.end(), n, c);
|
||||
}
|
||||
nwritten += n;
|
||||
}
|
||||
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
virtual base_t* setbuf(char_type* buf, std::streamsize n)
|
||||
{
|
||||
// According to the C++ standard the effects of setbuf are implementation
|
||||
// defined, except that setbuf(0, 0) has no effect. In this implementation,
|
||||
// setbuf(<anything>, n), for n > 0, calls resize(n) on the underlying
|
||||
// string.
|
||||
if(n > 0) {
|
||||
// bool do_get_area = false;
|
||||
// bool do_put_area = false;
|
||||
std::ptrdiff_t offg = 0;
|
||||
std::ptrdiff_t offp = 0;
|
||||
|
||||
assert(this->pbase() == &m_string[0]);
|
||||
//if(this->pbase() == &m_string[0]) {
|
||||
//do_put_area = true;
|
||||
offp = this->pptr() - this->pbase();
|
||||
//}
|
||||
|
||||
assert(this->eback() == &m_string[0]);
|
||||
//if(this->eback() == &m_string[0]) {
|
||||
//do_get_area = true;
|
||||
offg = this->gptr() - this->eback();
|
||||
//}
|
||||
|
||||
m_string.resize(n);
|
||||
|
||||
//if(do_get_area) {
|
||||
this->setg(&m_string[0], &m_string[offg], &m_string[m_string.size()]);
|
||||
//}
|
||||
|
||||
//if(do_put_area) {
|
||||
this->setp(&m_string[0], &m_string[m_string.size()]);
|
||||
this->pbump(static_cast<int>(offp));
|
||||
//}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
bool in = false;
|
||||
bool out = false;
|
||||
|
||||
const std::ios_base::openmode inout =
|
||||
std::ios_base::in | std::ios_base::out;
|
||||
|
||||
if((mode & inout) == inout) {
|
||||
if(dir == std::ios_base::beg || dir == std::ios_base::end)
|
||||
in = out = true;
|
||||
}
|
||||
else if(mode & std::ios_base::in)
|
||||
in = true;
|
||||
else if(mode & std::ios_base::out)
|
||||
out = true;
|
||||
|
||||
if(!in && !out)
|
||||
return pos_type(off_type(-1));
|
||||
else if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) ||
|
||||
(out && (!(m_mode & std::ios_base::out) || this->pptr() == 0)))
|
||||
return pos_type(off_type(-1));
|
||||
|
||||
std::streamoff newoff;
|
||||
switch(dir) {
|
||||
case std::ios_base::beg:
|
||||
newoff = 0;
|
||||
break;
|
||||
case std::ios_base::end:
|
||||
newoff = static_cast<std::streamoff>(m_string.size());
|
||||
break;
|
||||
case std::ios_base::cur:
|
||||
newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback())
|
||||
: static_cast<std::streamoff>(this->pptr() - this->pbase());
|
||||
break;
|
||||
default:
|
||||
return pos_type(off_type(-1));
|
||||
}
|
||||
|
||||
off += newoff;
|
||||
|
||||
if(in) {
|
||||
std::ptrdiff_t n = this->egptr() - this->eback();
|
||||
|
||||
if(off < 0 || off > n)
|
||||
return pos_type(off_type(-1));
|
||||
else
|
||||
this->setg(this->eback(), this->eback() + off, this->eback() + n);
|
||||
}
|
||||
|
||||
if(out) {
|
||||
std::ptrdiff_t n = this->epptr() - this->pbase();
|
||||
|
||||
if(off < 0 || off > n)
|
||||
return pos_type(off_type(-1));
|
||||
else {
|
||||
this->setp(this->pbase(), this->pbase() + n);
|
||||
this->pbump(off);
|
||||
}
|
||||
}
|
||||
return pos_type(off);
|
||||
}
|
||||
|
||||
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
bool in = (mode & std::ios_base::in) != 0;
|
||||
bool out = (mode & std::ios_base::out) != 0;
|
||||
|
||||
if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) ||
|
||||
(out && (!(m_mode & std::ios_base::out) || this->pptr() == 0)))
|
||||
return pos_type(off_type(-1));
|
||||
|
||||
const off_type n = pos - pos_type(off_type(0));
|
||||
|
||||
if(in) {
|
||||
if(n < 0 || n > this->egptr() - this->eback())
|
||||
return pos_type(off_type(-1));
|
||||
this->setg(this->eback(), this->eback() + n, this->egptr());
|
||||
}
|
||||
|
||||
if(out) {
|
||||
if(n < 0 || n > off_type(m_string.size()))
|
||||
return pos_type(off_type(-1));
|
||||
this->setp(&m_string[0], &m_string[m_string.size()]);
|
||||
this->pbump(n);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ios_base::openmode m_mode;
|
||||
string_type m_string;
|
||||
};
|
||||
|
||||
/*!A basic_istream class that holds a character string specified by CharString
|
||||
template parameter as its formatting buffer. The string must have
|
||||
contiguous storage, like std::string, boost::interprocess::string or
|
||||
boost::interprocess::basic_string*/
|
||||
template <class CharString, class CharTraits>
|
||||
class basic_istringstream
|
||||
: public std::basic_istream<typename CharString::value_type, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef CharString string_type;
|
||||
typedef typename std::basic_ios
|
||||
<typename CharString::value_type, CharTraits>::char_type char_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_istream<char_type, CharTraits> base_t;
|
||||
|
||||
public:
|
||||
/*!Constructor. Throws if string_type default constructor throws.*/
|
||||
basic_istringstream(std::ios_base::openmode mode = std::ios_base::in)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
/*!Constructor. Throws if string_type(const VectorParameter ¶m) throws.*/
|
||||
template<class VectorParameter>
|
||||
basic_istringstream(const VectorParameter ¶m,
|
||||
std::ios_base::openmode mode = std::ios_base::in)
|
||||
: basic_ios_t(), base_t(0),
|
||||
m_buf(param, mode | std::ios_base::in)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_istringstream(){};
|
||||
|
||||
public:
|
||||
/*!Returns the address of the stored stream buffer.*/
|
||||
basic_stringbuf<CharString, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_stringbuf<CharString, CharTraits>*>(&m_buf); }
|
||||
|
||||
/*!Swaps the underlying string with the passed string.
|
||||
This function resets the read position in the stream.
|
||||
Does not throw.*/
|
||||
void swap_string(string_type &vect)
|
||||
{ m_buf.swap_string(vect); }
|
||||
|
||||
/*!Returns a const reference to the internal string.
|
||||
Does not throw.*/
|
||||
const string_type &string() const
|
||||
{ return m_buf.string(); }
|
||||
|
||||
/*!Calls resize() method of the internal string.
|
||||
Resets the stream to the first position.
|
||||
Throws if the internals string's resize throws.*/
|
||||
void resize(typename string_type::size_type size)
|
||||
{ m_buf.resize(size); }
|
||||
|
||||
private:
|
||||
basic_stringbuf<CharString, CharTraits> m_buf;
|
||||
};
|
||||
|
||||
/*!A basic_ostream class that holds a character string specified by CharString
|
||||
template parameter as its formatting buffer. The string must have
|
||||
contiguous storage, like std::string, boost::interprocess::string or
|
||||
boost::interprocess::basic_string*/
|
||||
template <class CharString, class CharTraits>
|
||||
class basic_ostringstream
|
||||
: public std::basic_ostream<typename CharString::value_type, CharTraits>
|
||||
{
|
||||
public:
|
||||
typedef CharString string_type;
|
||||
typedef typename std::basic_ios
|
||||
<typename CharString::value_type, CharTraits>::char_type char_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_ostream<char_type, CharTraits> base_t;
|
||||
|
||||
public:
|
||||
/*!Constructor. Throws if string_type default constructor throws.*/
|
||||
basic_ostringstream(std::ios_base::openmode mode = std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
/*!Constructor. Throws if string_type(const VectorParameter ¶m) throws.*/
|
||||
template<class VectorParameter>
|
||||
basic_ostringstream(const VectorParameter ¶m,
|
||||
std::ios_base::openmode mode = std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(param, mode | std::ios_base::out)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_ostringstream(){}
|
||||
|
||||
public:
|
||||
/*!Returns the address of the stored stream buffer.*/
|
||||
basic_stringbuf<CharString, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_stringbuf<CharString, CharTraits>*>(&m_buf); }
|
||||
|
||||
/*!Swaps the underlying string with the passed string.
|
||||
This function resets the write position in the stream.
|
||||
Does not throw.*/
|
||||
void swap_string(string_type &vect)
|
||||
{ m_buf.swap_string(vect); }
|
||||
|
||||
/*!Returns a const reference to the internal string.
|
||||
Does not throw.*/
|
||||
const string_type &string() const
|
||||
{ return m_buf.string(); }
|
||||
|
||||
/*!Calls resize() method of the internal string.
|
||||
Resets the stream to the first position.
|
||||
Throws if the internals string's resize throws.*/
|
||||
void resize(typename string_type::size_type size)
|
||||
{ m_buf.resize(size); }
|
||||
|
||||
private:
|
||||
basic_stringbuf<CharString, CharTraits> m_buf;
|
||||
};
|
||||
|
||||
|
||||
/*!A basic_iostream class that holds a character string specified by CharString
|
||||
template parameter as its formatting buffer. The string must have
|
||||
contiguous storage, like std::string, boost::interprocess::string or
|
||||
boost::interprocess::basic_string*/
|
||||
template <class CharString, class CharTraits>
|
||||
class basic_stringstream
|
||||
: public std::basic_iostream<typename CharString::value_type, CharTraits>
|
||||
|
||||
{
|
||||
public:
|
||||
typedef CharString string_type;
|
||||
typedef typename std::basic_ios
|
||||
<typename CharString::value_type, CharTraits>::char_type char_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
|
||||
typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
|
||||
|
||||
private:
|
||||
typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
|
||||
typedef std::basic_iostream<char_type, CharTraits> base_t;
|
||||
|
||||
public:
|
||||
/*!Constructor. Throws if string_type default constructor throws.*/
|
||||
basic_stringstream(std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
/*!Constructor. Throws if string_type(const VectorParameter ¶m) throws.*/
|
||||
template<class VectorParameter>
|
||||
basic_stringstream(const VectorParameter ¶m, std::ios_base::openmode mode
|
||||
= std::ios_base::in | std::ios_base::out)
|
||||
: basic_ios_t(), base_t(0), m_buf(param, mode)
|
||||
{ basic_ios_t::init(&m_buf); }
|
||||
|
||||
~basic_stringstream(){}
|
||||
|
||||
public:
|
||||
//Returns the address of the stored stream buffer.
|
||||
basic_stringbuf<CharString, CharTraits>* rdbuf() const
|
||||
{ return const_cast<basic_stringbuf<CharString, CharTraits>*>(&m_buf); }
|
||||
|
||||
/*!Swaps the underlying string with the passed string.
|
||||
This function resets the read/write position in the stream.
|
||||
Does not throw.*/
|
||||
void swap_string(string_type &vect)
|
||||
{ m_buf.swap_string(vect); }
|
||||
|
||||
/*!Returns a const reference to the internal string.
|
||||
Does not throw.*/
|
||||
const string_type &string() const
|
||||
{ return m_buf.string(); }
|
||||
|
||||
/*!Calls resize() method of the internal string.
|
||||
Resets the stream to the first position.
|
||||
Throws if the internals string's resize throws.*/
|
||||
void resize(typename string_type::size_type size)
|
||||
{ m_buf.resize(size); }
|
||||
|
||||
private:
|
||||
basic_stringbuf<CharString, CharTraits> m_buf;
|
||||
};
|
||||
|
||||
//Some typedefs to simplify usage
|
||||
/*
|
||||
typedef basic_stringbuf<std::string<char> > stringbuf;
|
||||
typedef basic_stringstream<std::string<char> > stringstream;
|
||||
typedef basic_istringstream<std::string<char> > istringstream;
|
||||
typedef basic_ostringstream<std::string<char> > ostringstream;
|
||||
|
||||
typedef basic_stringbuf<std::string<wchar_t> > wstringbuf;
|
||||
typedef basic_stringstream<std::string<wchar_t> > wstringstream;
|
||||
typedef basic_istringstream<std::string<wchar_t> > wistringstream;
|
||||
typedef basic_ostringstream<std::string<wchar_t> > wostringstream;
|
||||
*/
|
||||
}} //namespace boost { namespace interprocess {
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif /* BOOST_INTERPROCESS_STRINGSTREAM_HPP */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,197 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
|
||||
inline interprocess_condition::interprocess_condition()
|
||||
{
|
||||
m_command = SLEEP;
|
||||
m_num_waiters = 0;
|
||||
}
|
||||
|
||||
inline interprocess_condition::~interprocess_condition()
|
||||
{}
|
||||
|
||||
|
||||
inline void interprocess_condition::notify_one()
|
||||
{
|
||||
this->notify(NOTIFY_ONE);
|
||||
}
|
||||
|
||||
inline void interprocess_condition::notify_all()
|
||||
{
|
||||
this->notify(NOTIFY_ALL);
|
||||
}
|
||||
|
||||
inline void interprocess_condition::notify(long command)
|
||||
{
|
||||
//This interprocess_mutex guarantees that no other thread can enter to the
|
||||
//do_timed_wait method logic, so that thread count will be
|
||||
//constant until the function writes a NOTIFY_ALL command.
|
||||
//It also guarantees that no other notification can be signaled
|
||||
//on this interprocess_condition before this one ends
|
||||
using namespace boost::detail;
|
||||
m_enter_mut.lock();
|
||||
|
||||
//Return if there are no waiters
|
||||
// if(!winapi::exchange_and_add(&m_num_waiters, 0)){
|
||||
if(!m_num_waiters) {
|
||||
m_enter_mut.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
//Notify that all threads should execute wait logic
|
||||
while(SLEEP != BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)&m_command, command, SLEEP)){
|
||||
winapi::sched_yield();
|
||||
}
|
||||
/*
|
||||
//Wait until the threads are waked
|
||||
while(SLEEP != winapi::exchange_and_add((long*)&m_command, 0)){
|
||||
winapi::sched_yield();
|
||||
}
|
||||
*/
|
||||
//The enter interprocess_mutex will rest locked until the last waiting thread unlocks it
|
||||
}
|
||||
|
||||
inline void interprocess_condition::do_wait(interprocess_mutex &mut)
|
||||
{
|
||||
this->do_timed_wait(false, boost::posix_time::ptime(), mut);
|
||||
}
|
||||
|
||||
inline bool interprocess_condition::do_timed_wait
|
||||
(const boost::posix_time::ptime &abs_time, interprocess_mutex &mut)
|
||||
{
|
||||
return this->do_timed_wait(true, abs_time, mut);
|
||||
}
|
||||
|
||||
inline bool interprocess_condition::do_timed_wait(bool tout_enabled,
|
||||
const boost::posix_time::ptime &abs_time,
|
||||
interprocess_mutex &mut)
|
||||
{
|
||||
using namespace boost::detail;
|
||||
boost::posix_time::ptime now =
|
||||
boost::posix_time::microsec_clock::universal_time();
|
||||
|
||||
if(tout_enabled){
|
||||
if(now >= abs_time) return false;
|
||||
}
|
||||
|
||||
//The enter interprocess_mutex guarantees that while executing a notification,
|
||||
//no other thread can execute the do_timed_wait method.
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
boost::interprocess::scoped_lock<interprocess_mutex> lock(m_enter_mut);
|
||||
//---------------------------------------------------------------
|
||||
//We increment the waiting thread count protected so that it will be
|
||||
//always constant when another thread enters the notification logic.
|
||||
//The increment marks this thread as "waiting on interprocess_condition"
|
||||
BOOST_INTERLOCKED_INCREMENT((long*)&m_num_waiters);
|
||||
|
||||
//We unlock the external interprocess_mutex atomically with the increment
|
||||
mut.unlock();
|
||||
}
|
||||
|
||||
//By default, we suppose that no timeout has happened
|
||||
bool timed_out = false, unlock_enter_mut= false;
|
||||
|
||||
//Loop until a notification indicates that the thread should
|
||||
//exit or timeout occurs
|
||||
while(1){
|
||||
//The thread sleeps/spins until a interprocess_condition commands a notification
|
||||
//Notification occurred, we will lock the checking interprocess_mutex so that
|
||||
while(m_command == SLEEP){
|
||||
// while(winapi::exchange_and_add(&m_command, 0) == SLEEP){
|
||||
winapi::sched_yield();
|
||||
|
||||
//Check for timeout
|
||||
if(tout_enabled){
|
||||
now = boost::posix_time::microsec_clock::universal_time();
|
||||
|
||||
if(now >= abs_time){
|
||||
//If we can lock the interprocess_mutex it means that no notification
|
||||
//is being executed in this interprocess_condition variable
|
||||
timed_out = m_enter_mut.try_lock();
|
||||
|
||||
//If locking fails, indicates that another thread is executing
|
||||
//notification, so we play the notification game
|
||||
if(!timed_out){
|
||||
//There is an ongoing notification, we will try again later
|
||||
continue;
|
||||
}
|
||||
//No notification in execution, since enter interprocess_mutex is locked.
|
||||
//We will execute time-out logic, so we will decrement count,
|
||||
//release the enter interprocess_mutex and return false.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If a timeout occurred, the interprocess_mutex will not execute checking logic
|
||||
if(tout_enabled && timed_out){
|
||||
//Decrement wait count
|
||||
BOOST_INTERLOCKED_DECREMENT((long*)&m_num_waiters);
|
||||
unlock_enter_mut = true;
|
||||
break;
|
||||
}
|
||||
else{
|
||||
//Notification occurred, we will lock the checking interprocess_mutex so that
|
||||
//if a notify_one notification occurs, only one thread can exit
|
||||
//---------------------------------------------------------------
|
||||
boost::interprocess::scoped_lock<interprocess_mutex> lock(m_check_mut);
|
||||
//---------------------------------------------------------------
|
||||
long result = BOOST_INTERLOCKED_COMPARE_EXCHANGE
|
||||
((long*)&m_command, SLEEP, NOTIFY_ONE);
|
||||
if(result == SLEEP){
|
||||
//Other thread has been notified and since it was a NOTIFY one
|
||||
//command, this thread must sleep again
|
||||
continue;
|
||||
}
|
||||
else if(result == NOTIFY_ONE){
|
||||
//If it was a NOTIFY_ONE command, only this thread should
|
||||
//exit. This thread has atomically marked command as sleep before
|
||||
//so no other thread will exit.
|
||||
//Decrement wait count.
|
||||
unlock_enter_mut = true;
|
||||
BOOST_INTERLOCKED_DECREMENT((long*)&m_num_waiters);
|
||||
break;
|
||||
}
|
||||
else{
|
||||
//If it is a NOTIFY_ALL command, all threads should return
|
||||
//from do_timed_wait function. Decrement wait count.
|
||||
unlock_enter_mut = BOOST_INTERLOCKED_DECREMENT((long*)&m_num_waiters) == 0;
|
||||
//Check if this is the last thread of notify_all waiters
|
||||
//Only the last thread will release the interprocess_mutex
|
||||
if(unlock_enter_mut){
|
||||
BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)&m_command, SLEEP, NOTIFY_ALL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Unlock the enter interprocess_mutex if it is a single notification, if this is
|
||||
//the last notified thread in a notify_all or a timeout has occurred
|
||||
if(unlock_enter_mut){
|
||||
m_enter_mut.unlock();
|
||||
}
|
||||
|
||||
//Lock external again before returning from the method
|
||||
mut.lock();
|
||||
return !timed_out;
|
||||
}
|
||||
|
||||
} //namespace interprocess
|
||||
|
||||
} // namespace boost
|
||||
@@ -1,120 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
inline static void do_lock_func(volatile long &m_s)
|
||||
{
|
||||
using namespace boost::detail;
|
||||
do{
|
||||
long prev_s = BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)&m_s, 0, 1);
|
||||
|
||||
if (m_s == 0 && prev_s == 1){
|
||||
break;
|
||||
}
|
||||
// relinquish current timeslice
|
||||
winapi::sched_yield();
|
||||
}while (true);
|
||||
}
|
||||
|
||||
inline static bool do_trylock_func(volatile long &m_s)
|
||||
{
|
||||
using namespace boost::detail;
|
||||
long prev_s = BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)&m_s, 0, 1);
|
||||
|
||||
if (m_s == 0 && prev_s == 1){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static bool do_timedlock_func(volatile long &m_s, const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
//Obtain current count and target time
|
||||
boost::posix_time::ptime now =
|
||||
boost::posix_time::microsec_clock::universal_time();
|
||||
using namespace boost::detail;
|
||||
|
||||
if(now >= abs_time) return false;
|
||||
|
||||
do{
|
||||
long prev_s = BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)&m_s, 0, 1);
|
||||
|
||||
if (m_s == 0 && prev_s == 1){
|
||||
break;
|
||||
}
|
||||
now = boost::posix_time::microsec_clock::universal_time();
|
||||
|
||||
if(now >= abs_time){
|
||||
return false;
|
||||
}
|
||||
// relinquish current time slice
|
||||
winapi::sched_yield();
|
||||
}while (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline static void do_unlock_func(volatile long &m_s)
|
||||
{
|
||||
using namespace boost::detail;
|
||||
BOOST_INTERLOCKED_COMPARE_EXCHANGE((long*)&m_s, 1, 0);
|
||||
}
|
||||
|
||||
inline interprocess_mutex::interprocess_mutex()
|
||||
: m_s(1)
|
||||
{}
|
||||
|
||||
inline interprocess_mutex::~interprocess_mutex()
|
||||
{}
|
||||
|
||||
inline void interprocess_mutex::lock(void)
|
||||
{
|
||||
do_lock_func(m_s);
|
||||
}
|
||||
|
||||
inline bool interprocess_mutex::try_lock(void)
|
||||
{
|
||||
return do_trylock_func(m_s);
|
||||
}
|
||||
|
||||
inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
return do_timedlock_func(m_s, abs_time);
|
||||
}
|
||||
|
||||
inline void interprocess_mutex::unlock(void)
|
||||
{
|
||||
do_unlock_func(m_s);
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
@@ -1,96 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Parts of the pthread code come from Boost Threads code:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2001-2003
|
||||
// William E. Kempf
|
||||
//
|
||||
// Permission to use, copy, modify, distribute and sell this software
|
||||
// and its documentation for any purpose is hereby granted without fee,
|
||||
// provided that the above copyright notice appear in all copies and
|
||||
// that both that copyright notice and this permission notice appear
|
||||
// in supporting documentation. William E. Kempf makes no representations
|
||||
// about the suitability of this software for any purpose.
|
||||
// It is provided "as is" without express or implied warranty.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace interprocess {
|
||||
|
||||
inline interprocess_recursive_mutex::interprocess_recursive_mutex()
|
||||
: m_nLockCount(0), m_nOwner(0xffffffff){}
|
||||
|
||||
inline interprocess_recursive_mutex::~interprocess_recursive_mutex(){}
|
||||
|
||||
inline void interprocess_recursive_mutex::lock()
|
||||
{
|
||||
unsigned long pNumber = winapi::current_thread_id();
|
||||
if(pNumber == m_nOwner){
|
||||
++m_nLockCount;
|
||||
}
|
||||
else{
|
||||
m_shared_timed_mutex.lock();
|
||||
m_nOwner = pNumber;
|
||||
++m_nLockCount;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool interprocess_recursive_mutex::try_lock()
|
||||
{
|
||||
unsigned long pNumber = winapi::current_thread_id();
|
||||
if(pNumber == m_nOwner) { // we own it
|
||||
++m_nLockCount;
|
||||
return true;
|
||||
}
|
||||
if(m_shared_timed_mutex.try_lock()){
|
||||
m_nOwner = pNumber;
|
||||
++m_nLockCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool interprocess_recursive_mutex::timed_lock(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
unsigned long pNumber = winapi::current_thread_id();
|
||||
if(pNumber == m_nOwner) { // we own it
|
||||
++m_nLockCount;
|
||||
return true;
|
||||
}
|
||||
if(m_shared_timed_mutex.timed_lock(abs_time)){
|
||||
m_nOwner = pNumber;
|
||||
++m_nLockCount;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void interprocess_recursive_mutex::unlock()
|
||||
{
|
||||
unsigned long pNumber = winapi::current_thread_id();
|
||||
assert(pNumber == m_nOwner);
|
||||
--m_nLockCount;
|
||||
if(!m_nLockCount){
|
||||
m_nOwner = m_nLockCount;
|
||||
--m_nOwner;
|
||||
m_shared_timed_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace interprocess {
|
||||
|
||||
} //namespace boost {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include<boost/interprocess/exceptions.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
|
||||
inline interprocess_semaphore::~interprocess_semaphore()
|
||||
{}
|
||||
|
||||
inline interprocess_semaphore::interprocess_semaphore(int initialCount)
|
||||
: m_mut(), m_cond(), m_count(initialCount)
|
||||
{}
|
||||
|
||||
inline void interprocess_semaphore::post()
|
||||
{
|
||||
scoped_lock<interprocess_mutex> lock(m_mut);
|
||||
if(m_count == 0){
|
||||
m_cond.notify_one();
|
||||
}
|
||||
++m_count;
|
||||
}
|
||||
|
||||
inline void interprocess_semaphore::wait()
|
||||
{
|
||||
scoped_lock<interprocess_mutex> lock(m_mut);
|
||||
while(m_count == 0){
|
||||
m_cond.wait(lock);
|
||||
}
|
||||
--m_count;
|
||||
}
|
||||
|
||||
inline bool interprocess_semaphore::try_wait()
|
||||
{
|
||||
scoped_lock<interprocess_mutex> lock(m_mut);
|
||||
if(m_count == 0){
|
||||
return false;
|
||||
}
|
||||
--m_count;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool interprocess_semaphore::timed_wait(const boost::posix_time::ptime &abs_time)
|
||||
{
|
||||
scoped_lock<interprocess_mutex> lock(m_mut);
|
||||
while(m_count == 0){
|
||||
if(!m_cond.timed_wait(lock, abs_time))
|
||||
return false;
|
||||
}
|
||||
--m_count;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
inline int interprocess_semaphore::get_count() const
|
||||
{
|
||||
scoped_lock<interprocess_mutex> lock(m_mut);
|
||||
return count;
|
||||
}*/
|
||||
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
@@ -1,351 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// (C) Copyright Ion Gaztañaga 2005-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_WIN32_SYNC_PRIMITIVES_HPP
|
||||
#define BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP
|
||||
|
||||
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/interprocess/detail/config_begin.hpp>
|
||||
#include <boost/interprocess/detail/workaround.hpp>
|
||||
|
||||
#if (defined BOOST_WINDOWS) && !(defined BOOST_DISABLE_WIN32)
|
||||
# include <stddef.h>
|
||||
# include <stdarg.h>
|
||||
# include <boost/detail/interlocked.hpp>
|
||||
#else
|
||||
# error "This file can only be included in Windows OS"
|
||||
#endif
|
||||
|
||||
//The structures used in Interprocess with the
|
||||
//same binary interface as windows ones
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace winapi {
|
||||
|
||||
//Some used constants
|
||||
static const unsigned long infinite_time = 0xFFFFFFFF;
|
||||
static const unsigned long error_already_exists = 183L;
|
||||
static const unsigned long error_file_not_found = 2u;
|
||||
|
||||
static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3;
|
||||
static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001;
|
||||
|
||||
static const unsigned long page_readonly = 0x02;
|
||||
static const unsigned long page_readwrite = 0x04;
|
||||
static const unsigned long page_writecopy = 0x08;
|
||||
|
||||
static const unsigned long standard_rights_required = 0x000F0000L;
|
||||
static const unsigned long section_query = 0x0001;
|
||||
static const unsigned long section_map_write = 0x0002;
|
||||
static const unsigned long section_map_read = 0x0004;
|
||||
static const unsigned long section_map_execute = 0x0008;
|
||||
static const unsigned long section_extend_size = 0x0010;
|
||||
static const unsigned long section_all_access = standard_rights_required |
|
||||
section_query |
|
||||
section_map_write |
|
||||
section_map_read |
|
||||
section_map_execute |
|
||||
section_extend_size |
|
||||
section_all_access ;
|
||||
|
||||
static const unsigned long file_map_copy = section_query;
|
||||
static const unsigned long file_map_write = section_map_write;
|
||||
static const unsigned long file_map_read = section_map_read;
|
||||
static const unsigned long file_map_all_access = section_all_access;
|
||||
|
||||
static const unsigned long file_share_read = 0x00000001;
|
||||
static const unsigned long file_share_write = 0x00000002;
|
||||
|
||||
static const unsigned long generic_read = 0x80000000L;
|
||||
static const unsigned long generic_write = 0x40000000L;
|
||||
|
||||
static const unsigned long wait_object_0 = 0;
|
||||
static const unsigned long wait_abandoned = 0x00000080L;
|
||||
static const unsigned long wait_timeout = 258L;
|
||||
static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF;
|
||||
|
||||
static const unsigned long format_message_allocate_buffer
|
||||
= (unsigned long)0x00000100;
|
||||
static const unsigned long format_message_ignore_inserts
|
||||
= (unsigned long)0x00000200;
|
||||
static const unsigned long format_message_from_string
|
||||
= (unsigned long)0x00000400;
|
||||
static const unsigned long format_message_from_hmodule
|
||||
= (unsigned long)0x00000800;
|
||||
static const unsigned long format_message_from_system
|
||||
= (unsigned long)0x00001000;
|
||||
static const unsigned long format_message_argument_array
|
||||
= (unsigned long)0x00002000;
|
||||
static const unsigned long format_message_max_width_mask
|
||||
= (unsigned long)0x000000FF;
|
||||
static const unsigned long lang_neutral = (unsigned long)0x00;
|
||||
static const unsigned long sublang_default = (unsigned long)0x01;
|
||||
static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF;
|
||||
static void * const invalid_handle_value = (void*)(long*)-1;
|
||||
static const unsigned long create_new = 1;
|
||||
static const unsigned long create_always = 2;
|
||||
static const unsigned long open_existing = 3;
|
||||
static const unsigned long open_always = 4;
|
||||
static const unsigned long truncate_existing = 5;
|
||||
|
||||
static const unsigned long file_attribute_temporary = 0x00000100;
|
||||
|
||||
static const unsigned long file_begin = 0;
|
||||
static const unsigned long file_current = 1;
|
||||
static const unsigned long file_end = 2;
|
||||
|
||||
static const unsigned long lockfile_fail_immediately = 1;
|
||||
static const unsigned long lockfile_exclusive_lock = 2;
|
||||
static const unsigned long error_lock_violation = 33;
|
||||
|
||||
} //namespace winapi {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#if !defined( BOOST_USE_WINDOWS_H )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace winapi {
|
||||
|
||||
struct interprocess_overlapped
|
||||
{
|
||||
unsigned long *internal;
|
||||
unsigned long *internal_high;
|
||||
union {
|
||||
struct {
|
||||
unsigned long offset;
|
||||
unsigned long offset_high;
|
||||
}dummy;
|
||||
void *pointer;
|
||||
};
|
||||
|
||||
void *h_event;
|
||||
};
|
||||
|
||||
struct interprocess_filetime
|
||||
{
|
||||
unsigned long dwLowDateTime;
|
||||
unsigned long dwHighDateTime;
|
||||
};
|
||||
|
||||
struct interprocess_security_attributes
|
||||
{
|
||||
unsigned long nLength;
|
||||
void *lpSecurityDescriptor;
|
||||
int bInheritHandle;
|
||||
};
|
||||
|
||||
struct system_info {
|
||||
union {
|
||||
unsigned long dwOemId; // Obsolete field...do not use
|
||||
struct {
|
||||
unsigned short wProcessorArchitecture;
|
||||
unsigned short wReserved;
|
||||
} dummy;
|
||||
};
|
||||
unsigned long dwPageSize;
|
||||
void * lpMinimumApplicationAddress;
|
||||
void * lpMaximumApplicationAddress;
|
||||
unsigned long * dwActiveProcessorMask;
|
||||
unsigned long dwNumberOfProcessors;
|
||||
unsigned long dwProcessorType;
|
||||
unsigned long dwAllocationGranularity;
|
||||
unsigned short wProcessorLevel;
|
||||
unsigned short wProcessorRevision;
|
||||
};
|
||||
|
||||
//Some windows API declarations
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
|
||||
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
|
||||
extern "C" __declspec(dllimport) int __stdcall CloseHandle(void*);
|
||||
extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateMutexA(interprocess_security_attributes*, int, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall OpenMutexA(unsigned long, int, const char *);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void *, unsigned long);
|
||||
extern "C" __declspec(dllimport) int __stdcall ReleaseMutex(void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall UnmapViewOfFile(void *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateSemaphoreA(interprocess_security_attributes*, long, long, const char *);
|
||||
extern "C" __declspec(dllimport) int __stdcall ReleaseSemaphore(void *, long, long *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall OpenSemaphoreA(unsigned long, int, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, interprocess_security_attributes*, unsigned long, unsigned long, unsigned long, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, size_t, void*);
|
||||
extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *);
|
||||
extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct _SECURITY_ATTRIBUTES*, unsigned long, unsigned long, void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *);
|
||||
extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
|
||||
extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, size_t);
|
||||
extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size);
|
||||
extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
|
||||
(unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId,
|
||||
unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize,
|
||||
va_list *Arguments);
|
||||
extern "C" __declspec(dllimport) void *__stdcall LocalFree (void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall CreateDirectoryA(const char *, interprocess_security_attributes*);
|
||||
extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length, char *buffer);
|
||||
extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *);
|
||||
extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, __int64 distance, __int64 *new_file_pointer, unsigned long move_method);
|
||||
extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
|
||||
extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high);
|
||||
extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
|
||||
extern "C" __declspec(dllimport) int __stdcall UnlockFileEx(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped);
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement( long volatile * );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd(long volatile *, long);
|
||||
|
||||
} //namespace winapi {
|
||||
} //namespace interprocess {
|
||||
} //namespace boost {
|
||||
|
||||
#else
|
||||
# include <windows.h>
|
||||
#endif //#if !defined( BOOST_USE_WINDOWS_H )
|
||||
|
||||
namespace boost {
|
||||
namespace interprocess {
|
||||
namespace winapi {
|
||||
|
||||
static inline unsigned long format_message
|
||||
(unsigned long dwFlags, const void *lpSource,
|
||||
unsigned long dwMessageId, unsigned long dwLanguageId,
|
||||
char *lpBuffer, unsigned long nSize, va_list *Arguments)
|
||||
{
|
||||
return FormatMessageA
|
||||
(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
|
||||
}
|
||||
|
||||
//And now, wrapper functions
|
||||
static inline void * local_free(void *hmem)
|
||||
{ return LocalFree(hmem); }
|
||||
|
||||
static inline unsigned long make_lang_id(unsigned long p, unsigned long s)
|
||||
{ return ((((unsigned short)(s)) << 10) | (unsigned short)(p)); }
|
||||
|
||||
static inline void sched_yield()
|
||||
{ Sleep(1); }
|
||||
|
||||
static inline unsigned long get_current_thread_id()
|
||||
{ return GetCurrentThreadId(); }
|
||||
|
||||
static inline unsigned int close_handle(void* handle)
|
||||
{ return CloseHandle(handle); }
|
||||
|
||||
static inline unsigned long get_last_error()
|
||||
{ return GetLastError(); }
|
||||
|
||||
static inline void get_system_time_as_file_time(interprocess_filetime *filetime)
|
||||
{ GetSystemTimeAsFileTime(filetime); }
|
||||
|
||||
static inline void *create_mutex(const char *name)
|
||||
{ return CreateMutexA(0, 0, name); }
|
||||
|
||||
static inline void *open_mutex(const char *name)
|
||||
{ return OpenMutexA(mutex_all_access, 0, name); }
|
||||
|
||||
static inline unsigned long wait_for_single_object(void *handle, unsigned long time)
|
||||
{ return WaitForSingleObject(handle, time); }
|
||||
|
||||
static inline int release_mutex(void *handle)
|
||||
{ return ReleaseMutex(handle); }
|
||||
|
||||
static inline int unmap_view_of_file(void *address)
|
||||
{ return UnmapViewOfFile(address); }
|
||||
|
||||
static inline void *create_semaphore(long initialCount, const char *name)
|
||||
{ return CreateSemaphoreA(0, initialCount, (long)(((unsigned long)(-1))>>1), name); }
|
||||
|
||||
static inline int release_semaphore(void *handle, long release_count, long *prev_count)
|
||||
{ return ReleaseSemaphore(handle, release_count, prev_count); }
|
||||
|
||||
static inline void *open_semaphore(const char *name)
|
||||
{ return OpenSemaphoreA(semaphore_all_access, 1, name); }
|
||||
|
||||
static inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name)
|
||||
{ return CreateFileMappingA (handle, 0, access, high_size, low_size, name); }
|
||||
|
||||
static inline void * open_file_mapping (unsigned long access, const char *name)
|
||||
{ return OpenFileMappingA (access, 0, name); }
|
||||
|
||||
static inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr)
|
||||
{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); }
|
||||
|
||||
static inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes = 0)
|
||||
{ return CreateFileA(name, access, file_share_read | file_share_write, 0, creation_flags, attributes, 0); }
|
||||
|
||||
static inline bool delete_file(const char *name)
|
||||
{ return 0 != DeleteFileA(name); }
|
||||
|
||||
static inline void get_system_info(system_info *info)
|
||||
{ GetSystemInfo(info); }
|
||||
|
||||
static inline int flush_view_of_file(void *base_addr, std::size_t numbytes)
|
||||
{ return FlushViewOfFile(base_addr, numbytes); }
|
||||
|
||||
static inline bool get_file_size(void *handle, __int64 &size)
|
||||
{
|
||||
return 0 != GetFileSizeEx(handle, &size);
|
||||
}
|
||||
|
||||
static inline bool create_directory(const char *name, interprocess_security_attributes* security)
|
||||
{
|
||||
return 0 != CreateDirectoryA(name, security);
|
||||
}
|
||||
|
||||
static inline unsigned long get_temp_path(unsigned long length, char *buffer)
|
||||
{
|
||||
return GetTempPathA(length, buffer);
|
||||
}
|
||||
|
||||
static inline int set_end_of_file(void *handle)
|
||||
{
|
||||
return 0 != SetEndOfFile(handle);
|
||||
}
|
||||
|
||||
static inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method)
|
||||
{
|
||||
return 0 != SetFilePointerEx(handle, distance, new_file_pointer, move_method);
|
||||
}
|
||||
|
||||
static inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
|
||||
{
|
||||
return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped);
|
||||
}
|
||||
|
||||
static inline bool unlock_file_ex(void *hnd, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped)
|
||||
{
|
||||
return 0 != UnlockFileEx(hnd, reserved, size_low, size_high, overlapped);
|
||||
}
|
||||
|
||||
static inline long interlocked_increment(long volatile *addr)
|
||||
{ return InterlockedIncrement(addr); }
|
||||
|
||||
static inline long interlocked_decrement(long volatile *addr)
|
||||
{ return InterlockedDecrement(addr); }
|
||||
|
||||
static inline long interlocked_compare_exchange(long volatile *addr, long val1, long val2)
|
||||
{ return InterlockedCompareExchange(addr, val1, val2); }
|
||||
|
||||
static inline long exchange_and_add(long volatile* addend, long value)
|
||||
{ return InterlockedExchangeAdd((long*)addend, value); }
|
||||
|
||||
} //namespace winapi
|
||||
} //namespace interprocess
|
||||
} //namespace boost
|
||||
|
||||
#include <boost/interprocess/detail/config_end.hpp>
|
||||
|
||||
#endif //#ifdef BOOST_INTERPROCESS_WIN32_SYNC_PRIMITIVES_HPP
|
||||
Reference in New Issue
Block a user