Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/container for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP Chris@16: #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@101: Chris@16: #include //allocator_traits Chris@16: #include Chris@16: #include //multiallocation_chain Chris@16: #include //version_type Chris@16: #include //allocation_type Chris@16: #include //integral_constant Chris@16: #include //pointer_traits Chris@101: #include //BOOST_TRY Chris@16: Chris@16: namespace boost { Chris@16: namespace container { Chris@16: namespace container_detail { Chris@16: Chris@16: template::value> Chris@16: struct allocator_version_traits Chris@16: { Chris@16: typedef ::boost::container::container_detail::integral_constant Chris@16: alloc_version; Chris@16: Chris@16: typedef typename Allocator::multiallocation_chain multiallocation_chain; Chris@16: Chris@16: typedef typename boost::container::allocator_traits::pointer pointer; Chris@16: typedef typename boost::container::allocator_traits::size_type size_type; Chris@16: Chris@16: //Node allocation interface Chris@16: static pointer allocate_one(Allocator &a) Chris@16: { return a.allocate_one(); } Chris@16: Chris@16: static void deallocate_one(Allocator &a, const pointer &p) Chris@16: { a.deallocate_one(p); } Chris@16: Chris@16: static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m) Chris@16: { return a.allocate_individual(n, m); } Chris@16: Chris@16: static void deallocate_individual(Allocator &a, multiallocation_chain &holder) Chris@16: { a.deallocate_individual(holder); } Chris@16: Chris@101: static pointer allocation_command(Allocator &a, allocation_type command, Chris@101: size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) Chris@101: { return a.allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct allocator_version_traits Chris@16: { Chris@16: typedef ::boost::container::container_detail::integral_constant Chris@16: alloc_version; Chris@16: Chris@16: typedef typename boost::container::allocator_traits::pointer pointer; Chris@16: typedef typename boost::container::allocator_traits::size_type size_type; Chris@16: typedef typename boost::container::allocator_traits::value_type value_type; Chris@16: Chris@16: typedef typename boost::intrusive::pointer_traits:: Chris@16: template rebind_pointer::type void_ptr; Chris@16: typedef container_detail::basic_multiallocation_chain Chris@16: multialloc_cached_counted; Chris@16: typedef boost::container::container_detail:: Chris@16: transform_multiallocation_chain Chris@16: < multialloc_cached_counted, value_type> multiallocation_chain; Chris@16: Chris@16: //Node allocation interface Chris@16: static pointer allocate_one(Allocator &a) Chris@16: { return a.allocate(1); } Chris@16: Chris@16: static void deallocate_one(Allocator &a, const pointer &p) Chris@16: { a.deallocate(p, 1); } Chris@16: Chris@16: static void deallocate_individual(Allocator &a, multiallocation_chain &holder) Chris@16: { Chris@16: size_type n = holder.size(); Chris@16: typename multiallocation_chain::iterator it = holder.begin(); Chris@16: while(n--){ Chris@16: pointer p = boost::intrusive::pointer_traits::pointer_to(*it); Chris@16: ++it; Chris@16: a.deallocate(p, 1); Chris@16: } Chris@16: } Chris@16: Chris@16: struct allocate_individual_rollback Chris@16: { Chris@16: allocate_individual_rollback(Allocator &a, multiallocation_chain &chain) Chris@16: : mr_a(a), mp_chain(&chain) Chris@16: {} Chris@16: Chris@16: ~allocate_individual_rollback() Chris@16: { Chris@16: if(mp_chain) Chris@16: allocator_version_traits::deallocate_individual(mr_a, *mp_chain); Chris@16: } Chris@16: Chris@16: void release() Chris@16: { Chris@16: mp_chain = 0; Chris@16: } Chris@16: Chris@16: Allocator &mr_a; Chris@16: multiallocation_chain * mp_chain; Chris@16: }; Chris@16: Chris@16: static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m) Chris@16: { Chris@16: allocate_individual_rollback rollback(a, m); Chris@16: while(n--){ Chris@16: m.push_front(a.allocate(1)); Chris@16: } Chris@16: rollback.release(); Chris@16: } Chris@16: Chris@101: static pointer allocation_command(Allocator &a, allocation_type command, Chris@101: size_type, size_type &prefer_in_recvd_out_size, pointer &reuse) Chris@16: { Chris@101: pointer ret = pointer(); Chris@101: if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){ Chris@101: throw_logic_error("version 1 allocator without allocate_new flag"); Chris@16: } Chris@16: else{ Chris@16: BOOST_TRY{ Chris@101: ret = a.allocate(prefer_in_recvd_out_size); Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: if(!(command & nothrow_allocation)){ Chris@16: BOOST_RETHROW Chris@16: } Chris@16: } Chris@16: BOOST_CATCH_END Chris@101: reuse = pointer(); Chris@16: } Chris@16: return ret; Chris@16: } Chris@16: }; Chris@16: Chris@16: } //namespace container_detail { Chris@16: } //namespace container { Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)