////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2005-2008. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP #define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP #if (defined _MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace interprocess { namespace detail { template struct smart_ptr_type { typedef typename SmartPtr::value_type value_type; typedef value_type *pointer; static pointer get (const SmartPtr &smartptr) { return smartptr.get();} }; template struct smart_ptr_type { typedef T value_type; typedef value_type *pointer; static pointer get (pointer ptr) { return ptr;} }; //!Overload for smart pointers to avoid ADL problems with get_pointer template inline typename smart_ptr_type::pointer get_pointer(const Ptr &ptr) { return smart_ptr_type::get(ptr); } //!To avoid ADL problems with swap template inline void do_swap(T& x, T& y) { using std::swap; swap(x, y); } //!A deleter for scoped_ptr that deallocates the memory //!allocated for an object using a STL allocator. template struct scoped_ptr_dealloc_functor { typedef typename Allocator::pointer pointer; typedef detail::integral_constant::value> alloc_version; typedef detail::integral_constant allocator_v1; typedef detail::integral_constant allocator_v2; private: void priv_deallocate(const typename Allocator::pointer &p, allocator_v1) { m_alloc.deallocate(p, 1); } void priv_deallocate(const typename Allocator::pointer &p, allocator_v2) { m_alloc.deallocate_one(p); } public: Allocator& m_alloc; scoped_ptr_dealloc_functor(Allocator& a) : m_alloc(a) {} void operator()(pointer ptr) { if (ptr) priv_deallocate(ptr, alloc_version()); } }; //!A deleter for scoped_ptr that deallocates the memory //!allocated for an object using a STL allocator. template struct scoped_deallocator { typedef typename Allocator::pointer pointer; typedef detail::integral_constant::value> alloc_version; typedef detail::integral_constant allocator_v1; typedef detail::integral_constant allocator_v2; private: void priv_deallocate(allocator_v1) { m_alloc.deallocate(m_ptr, 1); } void priv_deallocate(allocator_v2) { m_alloc.deallocate_one(m_ptr); } public: pointer m_ptr; Allocator& m_alloc; scoped_deallocator(pointer p, Allocator& a) : m_ptr(p), m_alloc(a) {} ~scoped_deallocator() { if (m_ptr)priv_deallocate(alloc_version()); } void release() { m_ptr = 0; } }; //!A deleter for scoped_ptr that deallocates the memory //!allocated for an array of objects using a STL allocator. template struct scoped_array_deallocator { typedef typename Allocator::pointer pointer; typedef typename Allocator::size_type size_type; scoped_array_deallocator(pointer p, Allocator& a, size_type length) : m_ptr(p), m_alloc(a), m_length(length) {} ~scoped_array_deallocator() { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); } void release() { m_ptr = 0; } private: pointer m_ptr; Allocator& m_alloc; size_type m_length; }; template struct null_scoped_array_deallocator { typedef typename Allocator::pointer pointer; typedef typename Allocator::size_type size_type; null_scoped_array_deallocator(pointer, Allocator&, size_type) {} void release() {} }; //!A deleter for scoped_ptr that destroys //!an object using a STL allocator. template struct scoped_destructor_n { typedef typename Allocator::pointer pointer; typedef typename Allocator::value_type value_type; typedef typename Allocator::size_type size_type; pointer m_p; size_type m_n; scoped_destructor_n(pointer p, size_type n) : m_p(p), m_n(n) {} void release() { m_p = 0; } void increment_size(size_type inc) { m_n += inc; } ~scoped_destructor_n() { if(!m_p) return; value_type *raw_ptr = detail::get_pointer(m_p); for(std::size_t i = 0; i < m_n; ++i, ++raw_ptr) raw_ptr->~value_type(); } }; //!A deleter for scoped_ptr that destroys //!an object using a STL allocator. template struct null_scoped_destructor_n { typedef typename Allocator::pointer pointer; typedef typename Allocator::size_type size_type; null_scoped_destructor_n(pointer, size_type) {} void increment_size(size_type) {} void release() {} }; template class allocator_destroyer { typedef typename A::value_type value_type; typedef detail::integral_constant::value> alloc_version; typedef detail::integral_constant allocator_v1; typedef detail::integral_constant allocator_v2; private: A & a_; private: void priv_deallocate(const typename A::pointer &p, allocator_v1) { a_.deallocate(p, 1); } void priv_deallocate(const typename A::pointer &p, allocator_v2) { a_.deallocate_one(p); } public: allocator_destroyer(A &a) : a_(a) {} void operator()(const typename A::pointer &p) { detail::get_pointer(p)->~value_type(); priv_deallocate(p, alloc_version()); } }; template class allocator_destroyer_and_chain_builder { typedef typename A::value_type value_type; typedef typename A::multiallocation_iterator multiallocation_iterator; typedef typename A::multiallocation_chain multiallocation_chain; A & a_; multiallocation_chain &c_; public: allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c) : a_(a), c_(c) {} void operator()(const typename A::pointer &p) { value_type *vp = detail::get_pointer(p); vp->~value_type(); c_.push_back(vp); } }; template class allocator_multialloc_chain_node_deallocator { typedef typename A::value_type value_type; typedef typename A::multiallocation_iterator multiallocation_iterator; typedef typename A::multiallocation_chain multiallocation_chain; typedef allocator_destroyer_and_chain_builder chain_builder; A & a_; multiallocation_chain c_; public: allocator_multialloc_chain_node_deallocator(A &a) : a_(a), c_() {} chain_builder get_chain_builder() { return chain_builder(a_, c_); } ~allocator_multialloc_chain_node_deallocator() { multiallocation_iterator it(c_.get_it()); if(it != multiallocation_iterator()) a_.deallocate_individual(it); } }; template class allocator_multialloc_chain_array_deallocator { typedef typename A::value_type value_type; typedef typename A::multiallocation_iterator multiallocation_iterator; typedef typename A::multiallocation_chain multiallocation_chain; typedef allocator_destroyer_and_chain_builder chain_builder; A & a_; multiallocation_chain c_; public: allocator_multialloc_chain_array_deallocator(A &a) : a_(a), c_() {} chain_builder get_chain_builder() { return chain_builder(a_, c_); } ~allocator_multialloc_chain_array_deallocator() { multiallocation_iterator it(c_.get_it()); if(it != multiallocation_iterator()) a_.deallocate_many(it); } }; //!A class used for exception-safe multi-allocation + construction. template struct multiallocation_destroy_dealloc { typedef typename Allocator::multiallocation_iterator multiallocation_iterator; typedef typename Allocator::value_type value_type; multiallocation_iterator m_itbeg; Allocator& m_alloc; multiallocation_destroy_dealloc(multiallocation_iterator itbeg, Allocator& a) : m_itbeg(itbeg), m_alloc(a) {} ~multiallocation_destroy_dealloc() { multiallocation_iterator endit; while(m_itbeg != endit){ detail::get_pointer(&*m_itbeg)->~value_type(); m_alloc.deallocate(&*m_itbeg, 1); ++m_itbeg; } } void next() { ++m_itbeg; } void release() { m_itbeg = multiallocation_iterator(); } }; //!Forces a cast from any pointer to char *pointer template inline char* char_ptr_cast(T *ptr) { //This is nasty, but we like it a lot! return (char*)(ptr); } inline char* char_ptr_cast() { //This is nasty, but we like it a lot! return (char*)(0); } //Rounds "orig_size" by excess to round_to bytes inline std::size_t get_rounded_size(std::size_t orig_size, std::size_t round_to) { return ((orig_size-1)/round_to+1)*round_to; } inline std::size_t get_truncated_size(std::size_t orig_size, std::size_t multiple) { return orig_size/multiple*multiple; } template struct ct_rounded_size { enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo }; }; template struct ct_min { enum { value = (Value1 < Value2)? Value1 : Value2 }; }; template struct ct_max { enum { value = (Value1 > Value2)? Value1 : Value2 }; }; // Gennaro Prota wrote this. Thanks! template struct ct_max_pow2_less { enum { c = 2*n < p }; static const std::size_t value = c ? (ct_max_pow2_less< c*p, 2*c*n>::value) : n; }; template <> struct ct_max_pow2_less<0, 0> { static const std::size_t value = 0; }; //!Obtains a generic pointer of the same type that //!can point to other pointed type: Ptr -> Ptr template struct pointer_to_other; template class Sp> struct pointer_to_other< Sp, U > { typedef Sp type; }; template class Sp> struct pointer_to_other< Sp, U > { typedef Sp type; }; template class Sp> struct pointer_to_other< Sp, U > { typedef Sp type; }; template struct pointer_to_other< T*, U > { typedef U* type; }; } //namespace detail { //!Trait class to detect if an index is a node //!index. This allows more efficient operations //!when deallocating named objects. template struct is_node_index { enum { value = false }; }; //!Trait class to detect if an index is an intrusive //!index. This will embed the derivation hook in each //!allocation header, to provide memory for the intrusive //!container. template struct is_intrusive_index { enum { value = false }; }; template SizeType get_next_capacity(const SizeType max_size ,const SizeType capacity ,const SizeType n) { // if (n > max_size - capacity) // throw std::length_error("get_next_capacity"); const SizeType m3 = max_size/3; if (capacity < m3) return capacity + max_value(3*(capacity+1)/5, n); if (capacity < m3*2) return capacity + max_value((capacity+1)/2, n); return max_size; } namespace detail { template struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair() : first(), second() {} pair(const T1& x, const T2& y) : first(x), second(y) {} template pair(const std::pair& p) : first(p.first), second(p.second) {} #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair(const detail::moved_object >& p) : first(move(p.get().first)), second(move(p.get().second)) {} #else template pair(std::pair && p) : first(move(p.first)), second(move(p.second)) {} #endif #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair(const detail::moved_object >& p) : first(move(p.get().first)), second(move(p.get().second)) {} #else template pair(pair && p) : first(move(p.first)), second(move(p.second)) {} #endif #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair(const detail::moved_object &x, const detail::moved_object &y) : first(move(x.get())), second(move(y.get())) {} #else template pair(U &&x, V &&y) : first(move(x)), second(move(y)) {} #endif #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE pair(const detail::moved_object &p) : first(move(p.get().first)), second(move(p.get().second)) {} #else pair(pair &&p) : first(move(p.first)), second(move(p.second)) {} #endif #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE pair& operator=(const detail::moved_object &p) { first = move(p.get().first); second = move(p.get().second); return *this; } #else pair& operator=(pair &&p) { first = move(p.first); second = move(p.second); return *this; } #endif pair& operator=(const pair &p) { first = p.first; second = p.second; return *this; } #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template pair& operator=(const detail::moved_object > &p) { first = move(p.get().first); second = move(p.get().second); return *this; } #else template pair& operator=(std::pair &&p) { first = move(p.first); second = move(p.second); return *this; } #endif #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE void swap(const detail::moved_object &p) { std::swap(*this, p.get()); } void swap(pair& p) { std::swap(*this, p); } #else void swap(pair &&p) { std::swap(*this, p); } #endif }; template inline bool operator==(const pair& x, const pair& y) { return static_cast(x.first == y.first && x.second == y.second); } template inline bool operator< (const pair& x, const pair& y) { return static_cast(x.first < y.first || (!(y.first < x.first) && x.second < y.second)); } template inline bool operator!=(const pair& x, const pair& y) { return static_cast(!(x == y)); } template inline bool operator> (const pair& x, const pair& y) { return y < x; } template inline bool operator>=(const pair& x, const pair& y) { return static_cast(!(x < y)); } template inline bool operator<=(const pair& x, const pair& y) { return static_cast(!(y < x)); } template inline pair make_pair(T1 x, T2 y) { return pair(x, y); } #ifndef BOOST_INTERPROCESS_RVALUE_REFERENCE template inline void swap(const detail::moved_object > &x, pair& y) { swap(x.get().first, y.first); swap(x.get().second, y.second); } template inline void swap(pair& x, const detail::moved_object > &y) { swap(x.first, y.get().first); swap(x.second, y.get().second); } template inline void swap(pair& x, pair& y) { swap(x.first, y.first); swap(x.second, y.second); } #else template inline void swap(pair&&x, pair&&y) { swap(x.first, y.first); swap(x.second, y.second); } #endif template struct cast_functor { typedef typename detail::add_reference::type result_type; result_type operator()(char &ptr) const { return *static_cast(static_cast(&ptr)); } }; template class multiallocation_chain_adaptor { private: MultiallocChain chain_; multiallocation_chain_adaptor (const multiallocation_chain_adaptor &); multiallocation_chain_adaptor &operator= (const multiallocation_chain_adaptor &); public: typedef transform_iterator < typename MultiallocChain:: multiallocation_iterator , detail::cast_functor > multiallocation_iterator; multiallocation_chain_adaptor() : chain_() {} void push_back(T *mem) { chain_.push_back(mem); } void push_front(T *mem) { chain_.push_front(mem); } void swap(multiallocation_chain_adaptor &other_chain) { chain_.swap(other_chain.chain_); } void splice_back(multiallocation_chain_adaptor &other_chain) { chain_.splice_back(other_chain.chain_); } T *pop_front() { return static_cast(chain_.pop_front()); } bool empty() const { return chain_.empty(); } multiallocation_iterator get_it() const { return multiallocation_iterator(chain_.get_it()); } std::size_t size() const { return chain_.size(); } }; } //namespace detail { //!The pair is movable if any of its members is movable template struct is_movable > { enum { value = is_movable::value || is_movable::value }; }; //!The pair is movable if any of its members is movable template struct is_movable > { enum { value = is_movable::value || is_movable::value }; }; ///has_trivial_destructor_after_move<> == true_type ///specialization for optimizations template struct has_trivial_destructor_after_move : public boost::has_trivial_destructor {}; template T* addressof(T& v) { return reinterpret_cast( &const_cast(reinterpret_cast(v))); } } //namespace interprocess { } //namespace boost { #include #endif //#ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP