From 24e420abe91c6c50151d9c0d73394e9bb3989dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 28 Apr 2019 19:18:22 +0200 Subject: [PATCH] Add block size customization options to deque. --- doc/container.qbk | 34 +++++- example/doc_custom_deque.cpp | 41 +++++++ include/boost/container/container_fwd.hpp | 3 +- include/boost/container/deque.hpp | 139 +++++++++++++--------- include/boost/container/options.hpp | 90 +++++++++++++- include/boost/container/vector.hpp | 13 -- test/deque_options_test.cpp | 43 +++++++ 7 files changed, 287 insertions(+), 76 deletions(-) create mode 100644 example/doc_custom_deque.cpp create mode 100644 test/deque_options_test.cpp diff --git a/doc/container.qbk b/doc/container.qbk index 541753b..db62dc8 100644 --- a/doc/container.qbk +++ b/doc/container.qbk @@ -33,7 +33,7 @@ In short, what does [*Boost.Container] offer? * Emplacement and move semantics are implemented, including emulation for pre-C++11 compilers. * Polymorphic allocators and memory resources, including implementation and emulation for pre-C++17 compilers -* New advanced features (e.g. recursive containers, configuration options for containers) are present. +* New advanced features (e.g. recursive containers) and configurability options [link container.configurable_containers] for containers. * Containers support stateful allocators and are compatible with [*Boost.Interprocess] (they can be safely placed in shared memory). * Users obtain a more uniform performance across all plataforms, @@ -676,8 +676,8 @@ the last template parameter and defined using the utility class The rate at which the capacity of a vector grows is implementation dependent and implementations choose exponential growth in order to meet the amortized constant time requirement for push_back. A higher growth factor will make it faster as it will require less data movement, but it will have a greater memory - impact (on average, more memory will be unused). A user can provide it's own implementation and some predefined - policies are available: [classref boost::container::growth_factor_50 growth_factor_50], + impact (on average, more memory will be unused). A user can provide a custom implementation of the growth factor and some + predefined policies are available: [classref boost::container::growth_factor_50 growth_factor_50], [classref boost::container::growth_factor_60 growth_factor_60] and [classref boost::container::growth_factor_50 growth_factor_100]. @@ -695,6 +695,31 @@ used to customize `vector` container: [endsect] +[section:configurable_deques Configurable deques] + +[*Boost.Container] offers the possibility to configure at compile time some parameters of +[classref boost::container::deque deque] implementation. This configuration is passed as +the last template parameter and defined using the utility class +[classref boost::container::deque_options deque_options].The following parameters can be configured: + +Parameters that control the size of deque's 'block' (deque allocates contiguous chunks of elements, called 'blocks'). +Only one of these paratemers can be specified: + +* [classref boost::container::block_bytes block_bytes]: the number of bytes deque will allocate for store + elements contiguously: `deque::get_block_size()` will return aproximately `block_bytes/sizeof(value_type)`. + A value of zero means the default value. +* [classref boost::container::block_size block_size]: the number of elements deque will allocate contiguously. + If this option is specified, `deque::get_block_size()` will return the specified `block_size`. + A value of zero means the default value. + +See the following example to see how [classref boost::container::deque_options deque_options] can be +used to customize `deque` container: + +[import ../example/doc_custom_deque.cpp] +[doc_custom_deque] + +[endsect] + [endsect] [section:extended_allocators Extended functionality: Extended allocators] @@ -1251,6 +1276,9 @@ use [*Boost.Container]? There are several reasons for that: * [@https://github.com/boostorg/container/issues/117 GitHub #117: ['"flat_map/map::insert_or_assign with hint has wrong return types"]]. * [@https://github.com/boostorg/container/issues/118 GitHub #118: ['"Non-unique inplace_set_difference used in in flat_tree_merge_unique and iterator invalidation in insert_unique"]]. +* ['deque] can now have options, using [classref boost::container::deque_options deque_options]. + The block size/bytes can be be specified. + [endsect] [section:release_notes_boost_1_70_00 Boost 1.70 Release] diff --git a/example/doc_custom_deque.cpp b/example/doc_custom_deque.cpp new file mode 100644 index 0000000..004796e --- /dev/null +++ b/example/doc_custom_deque.cpp @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2013-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_custom_deque +#include +#include + +//Make sure assertions are active +#ifdef NDEBUG +#undef NDEBUG +#endif +#include + +int main () +{ + using namespace boost::container; + + //This option specifies the desired block size for deque + typedef deque_options< block_size<128u> >::type block_128_option_t; + + //This deque will allocate blocks of 128 elements + typedef deque block_128_deque_t; + assert(block_128_deque_t::get_block_size() == 128u); + + //This option specifies the maximum block size for deque + //in bytes + typedef deque_options< block_bytes<1024u> >::type block_1024_bytes_option_t; + + //This deque will allocate blocks of 1024 bytes + typedef deque block_1024_bytes_deque_t; + assert(block_1024_bytes_deque_t::get_block_size() == 1024u/sizeof(int)); + + return 0; +} +//] diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp index 0cbc991..529b739 100644 --- a/include/boost/container/container_fwd.hpp +++ b/include/boost/container/container_fwd.hpp @@ -117,7 +117,8 @@ template < class T, std::size_t N class small_vector; template + ,class Allocator = void + ,class Options = void> class deque; template #include //new_allocator #include +#include // container/detail #include #include //algo_equal(), algo_lexicographical_compare @@ -61,7 +62,7 @@ namespace boost { namespace container { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED -template +template class deque; template @@ -72,14 +73,12 @@ struct deque_value_traits static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move::value; }; -// Note: this function is simply a kludge to work around several compilers' -// bugs in handling constant expressions. -template -struct deque_buf_size +template +struct deque_block_size { - static const std::size_t min_size = 512u; - static const std::size_t sizeof_t = sizeof(T); - static const std::size_t value = sizeof_t < min_size ? (min_size/sizeof_t) : std::size_t(1); + BOOST_STATIC_ASSERT_MSG(!(BlockBytes && BlockSize), "BlockBytes and BlockSize can't be specified at the same time"); + static const std::size_t block_bytes = BlockBytes ? BlockBytes : 512u; + static const std::size_t value = BlockSize ? BlockSize : (sizeof(T) < block_bytes ? (block_bytes/sizeof(T)) : std::size_t(1)); }; namespace dtl { @@ -132,9 +131,6 @@ class deque_iterator , deque_iterator , nat>::type nonconst_iterator; - BOOST_CONTAINER_FORCEINLINE static std::size_t s_buffer_size() - { return deque_buf_size::value; } - typedef Pointer val_alloc_ptr; typedef typename boost::intrusive::pointer_traits:: template rebind_pointer::type index_pointer; @@ -151,8 +147,8 @@ class deque_iterator BOOST_CONTAINER_FORCEINLINE Pointer get_last() const { return m_last; } BOOST_CONTAINER_FORCEINLINE index_pointer get_node() const { return m_node; } - BOOST_CONTAINER_FORCEINLINE deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_NOEXCEPT_OR_NOTHROW - : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y) + BOOST_CONTAINER_FORCEINLINE deque_iterator(val_alloc_ptr x, index_pointer y, difference_type block_size) BOOST_NOEXCEPT_OR_NOTHROW + : m_cur(x), m_first(*y), m_last(*y + block_size), m_node(y) {} BOOST_CONTAINER_FORCEINLINE deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW @@ -190,15 +186,20 @@ class deque_iterator if(!this->m_cur && !x.m_cur){ return 0; } - return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) + + const difference_type block_size = this->m_last - this->m_first; + BOOST_ASSERT(block_size); + return block_size * (this->m_node - x.m_node - 1) + (this->m_cur - this->m_first) + (x.m_last - x.m_cur); } deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_ASSERT(!!m_cur); ++this->m_cur; if (this->m_cur == this->m_last) { - this->priv_set_node(this->m_node + 1); + const difference_type block_size = m_last - m_first; + BOOST_ASSERT(block_size); + this->priv_set_node(this->m_node + 1, block_size); this->m_cur = this->m_first; } return *this; @@ -213,8 +214,11 @@ class deque_iterator deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_ASSERT(!!m_cur); if (this->m_cur == this->m_first) { - this->priv_set_node(this->m_node - 1); + const difference_type block_size = m_last - m_first; + BOOST_ASSERT(block_size); + this->priv_set_node(this->m_node - 1, block_size); this->m_cur = this->m_last; } --this->m_cur; @@ -230,16 +234,19 @@ class deque_iterator deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW { + BOOST_ASSERT(!!m_cur); difference_type offset = n + (this->m_cur - this->m_first); - if (offset >= 0 && offset < difference_type(this->s_buffer_size())) + const difference_type block_size = this->m_last - this->m_first; + BOOST_ASSERT(block_size); + if (offset >= 0 && offset < block_size) this->m_cur += n; else { difference_type node_offset = - offset > 0 ? offset / difference_type(this->s_buffer_size()) - : -difference_type((-offset - 1) / this->s_buffer_size()) - 1; - this->priv_set_node(this->m_node + node_offset); + offset > 0 ? (offset / block_size) + : (-difference_type((-offset - 1) / block_size) - 1); + this->priv_set_node(this->m_node + node_offset, block_size); this->m_cur = this->m_first + - (offset - node_offset * difference_type(this->s_buffer_size())); + (offset - node_offset * block_size); } return *this; } @@ -274,11 +281,11 @@ class deque_iterator BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return !(l < r); } - BOOST_CONTAINER_FORCEINLINE void priv_set_node(index_pointer new_node) BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE void priv_set_node(index_pointer new_node, difference_type block_size) BOOST_NOEXCEPT_OR_NOTHROW { this->m_node = new_node; this->m_first = *new_node; - this->m_last = this->m_first + this->s_buffer_size(); + this->m_last = this->m_first + block_size; } BOOST_CONTAINER_FORCEINLINE friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW @@ -287,10 +294,22 @@ class deque_iterator } //namespace dtl { +template +struct get_deque_opt +{ + typedef Options type; +}; + +template<> +struct get_deque_opt +{ + typedef deque_null_opt type; +}; + // Deque base class. It has two purposes. First, its constructor // and destructor allocate (but don't initialize) storage. This makes // exception safety easier. -template +template class deque_base { BOOST_COPYABLE_AND_MOVABLE(deque_base) @@ -315,19 +334,24 @@ class deque_base typedef allocator_type stored_allocator_type; typedef val_alloc_size size_type; + private: + typedef typename get_deque_opt::type options_type; + protected: + typedef dtl::deque_iterator iterator; + typedef dtl::deque_iterator const_iterator; + + BOOST_CONSTEXPR BOOST_CONTAINER_FORCEINLINE static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW + { return deque_block_size::value; } typedef deque_value_traits traits_t; typedef ptr_alloc_t map_allocator_type; - BOOST_CONTAINER_FORCEINLINE static size_type s_buffer_size() BOOST_NOEXCEPT_OR_NOTHROW - { return deque_buf_size::value; } - BOOST_CONTAINER_FORCEINLINE val_alloc_ptr priv_allocate_node() - { return this->alloc().allocate(s_buffer_size()); } + { return this->alloc().allocate(get_block_size()); } BOOST_CONTAINER_FORCEINLINE void priv_deallocate_node(val_alloc_ptr p) BOOST_NOEXCEPT_OR_NOTHROW - { this->alloc().deallocate(p, s_buffer_size()); } + { this->alloc().deallocate(p, get_block_size()); } BOOST_CONTAINER_FORCEINLINE ptr_alloc_ptr priv_allocate_map(size_type n) { return this->ptr_alloc().allocate(n); } @@ -335,9 +359,6 @@ class deque_base BOOST_CONTAINER_FORCEINLINE void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_NOEXCEPT_OR_NOTHROW { this->ptr_alloc().deallocate(p, n); } - typedef dtl::deque_iterator iterator; - typedef dtl::deque_iterator const_iterator; - BOOST_CONTAINER_FORCEINLINE deque_base(size_type num_elements, const allocator_type& a) : members_(a) { this->priv_initialize_map(num_elements); } @@ -379,7 +400,7 @@ class deque_base void priv_initialize_map(size_type num_elements) { // if(num_elements){ - size_type num_nodes = num_elements / s_buffer_size() + 1; + size_type num_nodes = num_elements / get_block_size() + 1; this->members_.m_map_size = dtl::max_value((size_type) InitialMapSize, num_nodes + 2); this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size); @@ -398,11 +419,11 @@ class deque_base } BOOST_CATCH_END - this->members_.m_start.priv_set_node(nstart); - this->members_.m_finish.priv_set_node(nfinish - 1); + this->members_.m_start.priv_set_node(nstart, get_block_size()); + this->members_.m_finish.priv_set_node(nfinish - 1, get_block_size()); this->members_.m_start.m_cur = this->members_.m_start.m_first; this->members_.m_finish.m_cur = this->members_.m_finish.m_first + - num_elements % s_buffer_size(); + num_elements % get_block_size(); // } } @@ -490,16 +511,18 @@ class deque_base //! and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle. //! //! \tparam T The type of object that is stored in the deque -//! \tparam Allocator The allocator used for all internal memory management -template > +//! \tparam A The allocator used for all internal memory management, use void +//! for the default allocator +//! \tparam Options A type produced from \c boost::container::vector_options. +template #else -template +template #endif -class deque : protected deque_base::type> +class deque : protected deque_base::type, Options> { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: - typedef deque_base::type> Base; + typedef deque_base::type, Options> Base; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED typedef typename real_allocator::type ValAllocator; @@ -530,13 +553,15 @@ class deque : protected deque_base::type> private: // Internal typedefs BOOST_COPYABLE_AND_MOVABLE(deque) typedef typename Base::ptr_alloc_ptr index_pointer; - BOOST_CONTAINER_FORCEINLINE static size_type s_buffer_size() - { return Base::s_buffer_size(); } typedef allocator_traits allocator_traits_type; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: + + BOOST_CONSTEXPR BOOST_CONTAINER_FORCEINLINE static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW + { return Base::get_block_size(); } + ////////////////////////////////////////////// // // construct/copy/destroy @@ -1776,7 +1801,7 @@ class deque : protected deque_base::type> for (index_pointer node = this->members_.m_start.m_node + 1; node < this->members_.m_finish.m_node; ++node) { - this->priv_destroy_range(*node, *node + this->s_buffer_size()); + this->priv_destroy_range(*node, *node + get_block_size()); this->priv_deallocate_node(*node); } @@ -2087,13 +2112,13 @@ class deque : protected deque_base::type> BOOST_TRY { for ( ; cur < this->members_.m_finish.m_node; ++cur){ boost::container::uninitialized_fill_alloc - (this->alloc(), *cur, *cur + this->s_buffer_size(), value); + (this->alloc(), *cur, *cur + get_block_size(), value); } boost::container::uninitialized_fill_alloc (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value); } BOOST_CATCH(...){ - this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur)); + this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur, get_block_size())); BOOST_RETHROW } BOOST_CATCH_END @@ -2125,14 +2150,14 @@ class deque : protected deque_base::type> BOOST_TRY { for (; cur_node < this->members_.m_finish.m_node; ++cur_node) { FwdIt mid = first; - boost::container::iterator_advance(mid, this->s_buffer_size()); + boost::container::iterator_advance(mid, get_block_size()); ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node); first = mid; } ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first); } BOOST_CATCH(...){ - this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node)); + this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node, get_block_size())); BOOST_RETHROW } BOOST_CATCH_END @@ -2142,7 +2167,7 @@ class deque : protected deque_base::type> void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW { this->priv_deallocate_node(this->members_.m_finish.m_first); - this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); + this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1, get_block_size()); this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; allocator_traits_type::destroy ( this->alloc() @@ -2161,7 +2186,7 @@ class deque : protected deque_base::type> , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) ); this->priv_deallocate_node(this->members_.m_start.m_first); - this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1); + this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1, get_block_size()); this->members_.m_start.m_cur = this->members_.m_start.m_first; } @@ -2170,8 +2195,8 @@ class deque : protected deque_base::type> size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first; if (n > vacancies){ size_type new_elems = n-vacancies; - size_type new_nodes = (new_elems + this->s_buffer_size() - 1) / - this->s_buffer_size(); + size_type new_nodes = (new_elems + get_block_size() - 1) / + get_block_size(); size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map); if (new_nodes > s){ this->priv_reallocate_map(new_nodes, true); @@ -2196,7 +2221,7 @@ class deque : protected deque_base::type> size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1; if (n > vacancies){ size_type new_elems = n - vacancies; - size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size(); + size_type new_nodes = (new_elems + get_block_size() - 1)/get_block_size(); size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map)); if (new_nodes + 1 > s){ this->priv_reallocate_map(new_nodes, false); @@ -2245,8 +2270,8 @@ class deque : protected deque_base::type> this->members_.m_map_size = new_map_size; } - this->members_.m_start.priv_set_node(new_nstart); - this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1); + this->members_.m_start.priv_set_node(new_nstart, get_block_size()); + this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1, get_block_size()); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; @@ -2266,8 +2291,8 @@ namespace boost { //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template -struct has_trivial_destructor_after_move > +template +struct has_trivial_destructor_after_move > { typedef typename ::boost::container::allocator_traits::pointer pointer; static const bool value = ::boost::has_trivial_destructor_after_move::value && diff --git a/include/boost/container/options.hpp b/include/boost/container/options.hpp index 2ac7783..36dbecf 100644 --- a/include/boost/container/options.hpp +++ b/include/boost/container/options.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace boost { namespace container { @@ -111,6 +112,22 @@ using tree_assoc_options_t = typename boost::container::tree_assoc_options +struct default_if_void +{ + typedef T type; +}; + +template +struct default_if_void +{ + typedef Default type; +}; + +#endif + +#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + template struct get_stored_size_type_with_alloctraits { @@ -177,7 +194,7 @@ BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_fa //!This option specifies the unsigned integer type that a user wants the container //!to use to hold size-related information inside a container (e.g. current size, current capacity). //! -//!\tparam StoredSizeType A unsigned integer type. It shall be smaller than than the size +//!\tparam StoredSizeType An unsigned integer type. It shall be smaller than than the size //! of the size_type deduced from `allocator_traits::size_type` or the same type. //! //!If the maximum capacity() to be used is limited, a user can try to use 8-bit, 16-bit @@ -185,7 +202,7 @@ BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_fa //!memory can be saved for empty vectors. This could potentially performance benefits due to better //!cache usage. //! -//!Note that alignment requirements can disallow theoritical space savings. Example: +//!Note that alignment requirements can disallow theoretical space savings. Example: //!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine //!a 8 bit size type (total size: 4 byte pointer + 2 x 1 byte sizes = 6 bytes) //!will not save space when comparing two 16-bit size types because usually @@ -236,6 +253,75 @@ using vector_options_t = typename boost::container::vector_options:: #endif +//////////////////////////////////////////////////////////////// +// +// +// OPTIONS FOR DEQUE-BASED CONTAINERS +// +// +//////////////////////////////////////////////////////////////// + +#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + +template +struct deque_opt +{ + static const std::size_t block_bytes = BlockBytes; + static const std::size_t block_size = BlockSize; + BOOST_STATIC_ASSERT_MSG(!(block_bytes && block_size), "block_bytes and block_size can't be specified at the same time"); +}; + +typedef deque_opt<0u, 0u> deque_null_opt; + +#endif + +//! Helper metafunction to combine options into a single type to be used +//! by \c boost::container::deque. +//! Supported options are: \c boost::container::block_bytes +#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES) +template +#else +template +#endif +struct deque_options +{ + /// @cond + typedef typename ::boost::intrusive::pack_options + < deque_null_opt, + #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES) + O1, O2, O3, O4 + #else + Options... + #endif + >::type packed_options; + typedef deque_opt< packed_options::block_bytes, packed_options::block_size > implementation_defined; + /// @endcond + typedef implementation_defined type; +}; + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + +//! Helper alias metafunction to combine options into a single type to be used +//! by \c boost::container::deque. +//! Supported options are: \c boost::container::block_bytes +template +using deque_options_t = typename boost::container::deque_options::type; + +#endif + +//!This option specifies the maximum size of a block in bytes: this delimites the number of contiguous elements +//!that will be allocated by deque as min(1u, BlockBytes/sizeof(value_type)) +//!A value zero represents the default value. +//! +//!\tparam BlockBytes An unsigned integer value. +BOOST_INTRUSIVE_OPTION_CONSTANT(block_bytes, std::size_t, BlockBytes, block_bytes) + +//!This option specifies the size of a block, delimites the number of contiguous elements +//!that will be allocated by deque as BlockSize. +//!A value zero represents the default value. +//! +//!\tparam BlockBytes An unsigned integer value. +BOOST_INTRUSIVE_OPTION_CONSTANT(block_size, std::size_t, BlockSize, block_size) } //namespace container { } //namespace boost { diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp index 010b599..8d4b872 100644 --- a/include/boost/container/vector.hpp +++ b/include/boost/container/vector.hpp @@ -702,18 +702,6 @@ struct vector_alloc_holder struct growth_factor_60; -template -struct default_if_void -{ - typedef T type; -}; - -template -struct default_if_void -{ - typedef Default type; -}; - template struct get_vector_opt { @@ -728,7 +716,6 @@ struct get_vector_opt typedef vector_opt type; }; - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! A vector is a sequence that supports random access to elements, constant diff --git a/test/deque_options_test.cpp b/test/deque_options_test.cpp new file mode 100644 index 0000000..9a7a43a --- /dev/null +++ b/test/deque_options_test.cpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include + +using namespace boost::container; + +void test_block_bytes() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = deque_options_t< block_bytes<128u> >; + #else + typedef deque_options< block_bytes<128u> >::type options_t; + #endif + typedef deque deque_t; + BOOST_TEST(deque_t::get_block_size() == 128u/sizeof(unsigned short)); +} + +void test_block_elements() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = deque_options_t< block_size<64> >; + #else + typedef deque_options< block_size<64 > >::type options_t; + #endif + typedef deque deque_t; + BOOST_TEST(deque_t::get_block_size() == 64U); +} + +int main() +{ + test_block_bytes(); + test_block_elements(); + return ::boost::report_errors(); +}