Add Polymorphic Memory Resource utilities and rework the separately compiled library:

- Dlmalloc's based C function are boost_cont_xxx no longer exported, but wrapped into C++ linkage dlmalloc_xxx functions to effectively reuse Boost's dynamic library and autolink machinery instead of rewriting machinery to compile the C source file.
- Refactored scoped_allocator_adaptor's construct logic as it was shared with polymorphic allocator's one. Moved common logic to detail/dispatch_uses_allocator.hpp. Refactored also scoped_allocator_adaptor test utilities to be reused with polymorphic_allocator tests.
This commit is contained in:
Ion Gaztañaga
2015-09-07 19:16:46 +02:00
parent 77100c0bfc
commit 33d2f0f7af
110 changed files with 10143 additions and 1160 deletions

View File

@@ -27,7 +27,7 @@
#include <boost/container/detail/adaptive_node_pool.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/dlmalloc.hpp>
#include <boost/container/detail/singleton.hpp>
#include <boost/container/detail/placement_new.hpp>
@@ -164,7 +164,7 @@ class adaptive_pool
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
}
else{
return static_cast<pointer>(boost_cont_malloc(count*sizeof(T)));
return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
}
}
@@ -180,7 +180,7 @@ class adaptive_pool
singleton_t::instance().deallocate_node(ptr);
}
else{
boost_cont_free(ptr);
dlmalloc_free(ptr);
}
}
@@ -198,7 +198,7 @@ class adaptive_pool
//!Returns maximum the number of objects the previously allocated memory
//!pointed by p can hold.
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
{ return boost_cont_size(p); }
{ return dlmalloc_size(p); }
//!Allocates just one object. Memory allocated with this function
//!must be deallocated only with deallocate_one().
@@ -251,17 +251,17 @@ class adaptive_pool
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(BOOST_UNLIKELY(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(BOOST_UNLIKELY(!boost_cont_multialloc_nodes
(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain)))){
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes
(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
boost::container::throw_bad_alloc();
}
}
@@ -271,29 +271,29 @@ class adaptive_pool
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(BOOST_UNLIKELY(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(BOOST_UNLIKELY(!boost_cont_multialloc_arrays
(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain)))){
if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays
(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
boost::container::throw_bad_alloc();
}
}
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
{/*
boost_cont_memchain ch;
dlmalloc_memchain ch;
void *beg(&*chain.begin()), *last(&*chain.last());
size_t size(chain.size());
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
boost_cont_multidealloc(&ch);*/
boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
dlmalloc_multidealloc(&ch);*/
dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
}
//!Deallocates all free blocks of the pool
@@ -326,7 +326,7 @@ class adaptive_pool
,size_type &prefer_in_recvd_out_size, pointer &reuse_ptr)
{
std::size_t const preferred_size = prefer_in_recvd_out_size;
boost_cont_command_ret_t ret = {0 , 0};
dlmalloc_command_ret_t ret = {0 , 0};
if(BOOST_UNLIKELY(limit_size > this->max_size() || preferred_size > this->max_size())){
return pointer();
}
@@ -335,7 +335,7 @@ class adaptive_pool
std::size_t r_size;
{
void* reuse_ptr_void = reuse_ptr;
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
}
prefer_in_recvd_out_size = r_size/sizeof(T);

View File

@@ -24,12 +24,14 @@
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/dlmalloc.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
#include <cassert>
//!\file
namespace boost {
namespace container {
@@ -86,21 +88,18 @@ class allocator<void, Version, AllocationDisableMask>
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//!\file
//! This class is an extended STL-compatible that offers advanced allocation mechanism
//!(in-place expansion, shrinking, burst-allocation...)
//!
//! This allocator is a wrapper around a modified DLmalloc.
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template<class T>
#else
//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
//! the allocator offers advanced expand in place and burst allocation capabilities.
//
//!
//! AllocationDisableMask works only if Version is 2 and it can be an inclusive OR
//! of allocation types the user wants to disable.
template<class T, unsigned Version, unsigned int AllocationDisableMask>
#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
template< class T
, unsigned Version BOOST_CONTAINER_DOCONLY(=2)
, unsigned int AllocationDisableMask BOOST_CONTAINER_DOCONLY(=0)>
class allocator
{
typedef unsigned int allocation_type;
@@ -186,7 +185,7 @@ class allocator
(void)hint;
if(count > this->max_size())
boost::container::throw_bad_alloc();
void *ret = boost_cont_malloc(count*sizeof(T));
void *ret = dlmalloc_malloc(count*sizeof(T));
if(!ret)
boost::container::throw_bad_alloc();
return static_cast<pointer>(ret);
@@ -195,7 +194,7 @@ class allocator
//!Deallocates previously allocated memory.
//!Never throws
void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
{ boost_cont_free(ptr); }
{ dlmalloc_free(ptr); }
//!Returns the maximum number of elements that could be allocated.
//!Never throws
@@ -243,7 +242,7 @@ class allocator
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return boost_cont_size(p);
return dlmalloc_size(p);
}
//!Allocates just one object. Memory allocated with this function
@@ -289,16 +288,16 @@ class allocator
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));/*
boost_cont_memchain ch;
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}
}
@@ -309,9 +308,9 @@ class allocator
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
boost::container::throw_bad_alloc();
}
chain.incorporate_after(chain.before_begin()
@@ -319,7 +318,7 @@ class allocator
,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
/*
if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
boost::container::throw_bad_alloc();
}*/
}
@@ -330,12 +329,12 @@ class allocator
void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
dlmalloc_memchain ch;
void *beg(&*chain.begin()), *last(&*chain.last());
size_t size(chain.size());
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
boost_cont_multidealloc(&ch);
//boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
dlmalloc_multidealloc(&ch);
//dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
}
private:
@@ -346,7 +345,7 @@ class allocator
,pointer &reuse_ptr)
{
std::size_t const preferred_size = prefer_in_recvd_out_size;
boost_cont_command_ret_t ret = {0 , 0};
dlmalloc_command_ret_t ret = {0 , 0};
if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
return pointer();
}
@@ -355,7 +354,7 @@ class allocator
std::size_t r_size;
{
void* reuse_ptr_void = reuse_ptr;
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
}
prefer_in_recvd_out_size = r_size/sizeof(T);

View File

@@ -24,6 +24,7 @@
//! - boost::container::vector
//! - boost::container::stable_vector
//! - boost::container::static_vector
//! - boost::container::small_vector
//! - boost::container::slist
//! - boost::container::list
//! - boost::container::set
@@ -38,11 +39,19 @@
//! - boost::container::string
//! - boost::container::wstring
//!
//! It forward declares the following allocators:
//! Forward declares the following allocators:
//! - boost::container::allocator
//! - boost::container::node_allocator
//! - boost::container::adaptive_pool
//!
//! Forward declares the following polymorphic resource classes:
//! - boost::container::pmr::memory_resource
//! - boost::container::pmr::polymorphic_allocator
//! - boost::container::pmr::monotonic_buffer_resource
//! - boost::container::pmr::pool_options
//! - boost::container::pmr::unsynchronized_pool_resource
//! - boost::container::pmr::synchronized_pool_resource
//!
//! And finally it defines the following types
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -54,11 +63,18 @@
namespace boost{
namespace intrusive{
namespace detail{
//Create namespace to avoid compilation errors
}}
}}}
namespace boost{ namespace container{ namespace container_detail{
namespace bi = boost::intrusive;
namespace bid = boost::intrusive::detail;
}}}
namespace boost{ namespace container{ namespace pmr{
namespace bi = boost::intrusive;
namespace bid = boost::intrusive::detail;
}}}
#include <cstddef>
@@ -210,6 +226,26 @@ template
, std::size_t Version = 2>
class node_allocator;
namespace pmr {
class memory_resource;
template<class T>
class polymorphic_allocator;
class monotonic_buffer_resource;
struct pool_options;
template <class Allocator>
class resource_adaptor_imp;
class unsynchronized_pool_resource;
class synchronized_pool_resource;
} //namespace pmr {
#else
//! Default options for tree-based associative containers

View File

@@ -23,7 +23,6 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/pool_common_alloc.hpp>
#include <boost/container/detail/mutex.hpp>

View File

@@ -15,27 +15,6 @@
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4127)
/*
we need to import/export our code only if the user has specifically
asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
if they want just this one to be dynamically liked:
*/
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
/* export if this is our own source, otherwise import: */
#ifdef BOOST_CONTAINER_SOURCE
# define BOOST_CONTAINER_DECL __declspec(dllexport)
#else
# define BOOST_CONTAINER_DECL __declspec(dllimport)
#endif /* BOOST_CONTAINER_SOURCE */
#endif /* DYN_LINK */
#endif /* _MSC_VER */
/* if BOOST_CONTAINER_DECL isn't defined yet define it now: */
#ifndef BOOST_CONTAINER_DECL
#define BOOST_CONTAINER_DECL
#endif
#ifdef __cplusplus
@@ -215,14 +194,6 @@ typedef struct boost_cont_memchain_impl
}while(0)\
/**/
BOOST_CONTAINER_DECL size_t boost_cont_size(const void *p);
BOOST_CONTAINER_DECL void* boost_cont_malloc(size_t bytes);
BOOST_CONTAINER_DECL void boost_cont_free(void* mem);
BOOST_CONTAINER_DECL void* boost_cont_memalign(size_t bytes, size_t alignment);
/*!Indicates the all elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
must be contiguous.*/
#define DL_MULTIALLOC_ALL_CONTIGUOUS ((size_t)(-1))
@@ -231,22 +202,6 @@ BOOST_CONTAINER_DECL void* boost_cont_memalign(size_t bytes, size_t alignment);
should be selected by those functions.*/
#define DL_MULTIALLOC_DEFAULT_CONTIGUOUS ((size_t)(0))
BOOST_CONTAINER_DECL int boost_cont_multialloc_nodes
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL int boost_cont_multialloc_arrays
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL void boost_cont_multidealloc(boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL size_t boost_cont_footprint();
BOOST_CONTAINER_DECL size_t boost_cont_allocated_memory();
BOOST_CONTAINER_DECL size_t boost_cont_chunksize(const void *p);
BOOST_CONTAINER_DECL int boost_cont_all_deallocated();
typedef struct boost_cont_malloc_stats_impl
{
size_t max_system_bytes;
@@ -254,26 +209,6 @@ typedef struct boost_cont_malloc_stats_impl
size_t in_use_bytes;
} boost_cont_malloc_stats_t;
BOOST_CONTAINER_DECL boost_cont_malloc_stats_t boost_cont_malloc_stats();
BOOST_CONTAINER_DECL size_t boost_cont_in_use_memory();
BOOST_CONTAINER_DECL int boost_cont_trim(size_t pad);
BOOST_CONTAINER_DECL int boost_cont_mallopt
(int parameter_number, int parameter_value);
BOOST_CONTAINER_DECL int boost_cont_grow
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
BOOST_CONTAINER_DECL int boost_cont_shrink
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
BOOST_CONTAINER_DECL void* boost_cont_alloc
(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
BOOST_CONTAINER_DECL int boost_cont_malloc_check();
typedef unsigned int allocation_type;
enum
@@ -303,7 +238,50 @@ typedef struct boost_cont_command_ret_impl
int second;
}boost_cont_command_ret_t;
BOOST_CONTAINER_DECL boost_cont_command_ret_t boost_cont_allocation_command
size_t boost_cont_size(const void *p);
void* boost_cont_malloc(size_t bytes);
void boost_cont_free(void* mem);
void* boost_cont_memalign(size_t bytes, size_t alignment);
int boost_cont_multialloc_nodes
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
int boost_cont_multialloc_arrays
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
void boost_cont_multidealloc(boost_cont_memchain *pchain);
size_t boost_cont_footprint();
size_t boost_cont_allocated_memory();
size_t boost_cont_chunksize(const void *p);
int boost_cont_all_deallocated();
boost_cont_malloc_stats_t boost_cont_malloc_stats();
size_t boost_cont_in_use_memory();
int boost_cont_trim(size_t pad);
int boost_cont_mallopt(int parameter_number, int parameter_value);
int boost_cont_grow
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
int boost_cont_shrink
(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
void* boost_cont_alloc
(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
int boost_cont_malloc_check();
boost_cont_command_ret_t boost_cont_allocation_command
( allocation_type command
, size_t sizeof_object
, size_t limit_objects
@@ -312,7 +290,17 @@ BOOST_CONTAINER_DECL boost_cont_command_ret_t boost_cont_allocation_command
, void *reuse_ptr
);
BOOST_CONTAINER_DECL int boost_cont_mallopt(int param_number, int value);
void *boost_cont_sync_create();
void boost_cont_sync_destroy(void *sync);
int boost_cont_sync_lock(void *sync);
void boost_cont_sync_unlock(void *sync);
int boost_cont_global_sync_lock();
void boost_cont_global_sync_unlock();
#ifdef __cplusplus
} //extern "C" {

View File

@@ -1,24 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
#define BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/detail/alloc_lib.h>
#endif //#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP

View File

@@ -18,6 +18,13 @@
# pragma once
#endif
//Define BOOST_CONTAINER_DYNAMIC_LINKING which is independent from BOOST_*_NO_LIB
//and is needed is some tests that need to disable some checks (like operator new replacements)
//that don't work across DLL boundaries
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
# define BOOST_CONTAINER_DYNAMIC_LINKING
#endif
//
// Automatically link to the correct build variant where possible.
//
@@ -27,12 +34,14 @@
// once it's done with it:
//
#define BOOST_LIB_NAME boost_container
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
#if defined(BOOST_CONTAINER_DYNAMIC_LINKING)
# define BOOST_DYN_LINK
#endif
//
// And include the header that does the work:
//

View File

@@ -0,0 +1,139 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
#define BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/intrusive/circular_list_algorithms.hpp>
#include <boost/move/detail/type_traits.hpp>
#include <boost/assert.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
struct list_node
{
list_node *next;
list_node *previous;
};
struct list_node_traits
{
typedef list_node node;
typedef list_node* node_ptr;
typedef const list_node* const_node_ptr;
static node_ptr get_next(const_node_ptr n)
{ return n->next; }
static node_ptr get_previous(const_node_ptr n)
{ return n->previous; }
static void set_next(const node_ptr & n, const node_ptr & next)
{ n->next = next; }
static void set_previous(const node_ptr & n, const node_ptr & previous)
{ n->previous = previous; }
};
struct block_list_header
: public list_node
{
std::size_t size;
};
typedef bi::circular_list_algorithms<list_node_traits> list_algo;
template<class DerivedFromBlockListHeader = block_list_header>
class block_list_base
{
list_node m_list;
static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
public:
static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockListHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
explicit block_list_base()
{ list_algo::init_header(&m_list); }
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
block_list_base(const block_list_base&) = delete;
block_list_base operator=(const block_list_base&) = delete;
#else
private:
block_list_base (const block_list_base&);
block_list_base operator=(const block_list_base&);
public:
#endif
~block_list_base()
{}
void *allocate(std::size_t size, memory_resource &mr)
{
if((size_t(-1) - header_size) < size)
throw_bad_alloc();
void *p = mr.allocate(size+header_size);
block_list_header &mb = *::new((void*)p) DerivedFromBlockListHeader;
mb.size = size+header_size;
list_algo::link_after(&m_list, &mb);
return (char *)p + header_size;
}
void deallocate(void *p, memory_resource &mr) BOOST_NOEXCEPT
{
DerivedFromBlockListHeader *pheader = static_cast<DerivedFromBlockListHeader*>
(static_cast<void*>((char*)p - header_size));
list_algo::unlink(pheader);
const std::size_t size = pheader->size;
static_cast<DerivedFromBlockListHeader*>(pheader)->~DerivedFromBlockListHeader();
mr.deallocate(pheader, size, memory_resource::max_align);
}
void release(memory_resource &mr) BOOST_NOEXCEPT
{
list_node *n = list_algo::node_traits::get_next(&m_list);
while(n != &m_list){
DerivedFromBlockListHeader &d = static_cast<DerivedFromBlockListHeader&>(*n);
n = list_algo::node_traits::get_next(n);
std::size_t size = d.size;
d.~DerivedFromBlockListHeader();
mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
}
list_algo::init_header(&m_list);
}
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER

View File

@@ -0,0 +1,157 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
#define BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/throw_exception.hpp>
#include <boost/move/detail/type_traits.hpp>
#include <boost/intrusive/linear_slist_algorithms.hpp>
#include <boost/assert.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
struct slist_node
{
slist_node *next;
};
struct slist_node_traits
{
typedef slist_node node;
typedef slist_node* node_ptr;
typedef const slist_node* const_node_ptr;
static node_ptr get_next(const_node_ptr n)
{ return n->next; }
static void set_next(const node_ptr & n, const node_ptr & next)
{ n->next = next; }
};
struct block_slist_header
: public slist_node
{
std::size_t size;
};
typedef bi::linear_slist_algorithms<slist_node_traits> slist_algo;
template<class DerivedFromBlockSlistHeader = block_slist_header>
class block_slist_base
{
slist_node m_slist;
static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
public:
static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockSlistHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
explicit block_slist_base()
{ slist_algo::init_header(&m_slist); }
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
block_slist_base(const block_slist_base&) = delete;
block_slist_base operator=(const block_slist_base&) = delete;
#else
private:
block_slist_base (const block_slist_base&);
block_slist_base operator=(const block_slist_base&);
public:
#endif
~block_slist_base()
{}
void *allocate(std::size_t size, memory_resource &mr)
{
if((size_t(-1) - header_size) < size)
throw_bad_alloc();
void *p = mr.allocate(size+header_size);
block_slist_header &mb = *::new((void*)p) DerivedFromBlockSlistHeader;
mb.size = size+header_size;
slist_algo::link_after(&m_slist, &mb);
return (char *)p + header_size;
}
void release(memory_resource &mr) BOOST_NOEXCEPT
{
slist_node *n = slist_algo::node_traits::get_next(&m_slist);
while(n){
DerivedFromBlockSlistHeader &d = static_cast<DerivedFromBlockSlistHeader&>(*n);
n = slist_algo::node_traits::get_next(n);
std::size_t size = d.block_slist_header::size;
d.~DerivedFromBlockSlistHeader();
mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
}
slist_algo::init_header(&m_slist);
}
};
class block_slist
: public block_slist_base<>
{
memory_resource &m_upstream_rsrc;
public:
explicit block_slist(memory_resource &upstream_rsrc)
: block_slist_base<>(), m_upstream_rsrc(upstream_rsrc)
{}
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
block_slist(const block_slist&) = delete;
block_slist operator=(const block_slist&) = delete;
#else
private:
block_slist (const block_slist&);
block_slist operator=(const block_slist&);
public:
#endif
~block_slist()
{ this->release(); }
void *allocate(std::size_t size)
{ return this->block_slist_base<>::allocate(size, m_upstream_rsrc); }
void release() BOOST_NOEXCEPT
{ return this->block_slist_base<>::release(m_upstream_rsrc); }
memory_resource& upstream_resource() const BOOST_NOEXCEPT
{ return m_upstream_rsrc; }
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER

View File

@@ -25,6 +25,7 @@
#pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data
#pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier"
#pragma warning (disable : 4284) // odd return type for operator->
#pragma warning (disable : 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
#pragma warning (disable : 4324) // structure was padded due to __declspec(align(
#pragma warning (disable : 4345) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
#pragma warning (disable : 4355) // "this" : used in base member initializer list

View File

@@ -0,0 +1,293 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/uses_allocator.hpp>
#include <boost/container/detail/addressof.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/move/detail/fwd_macros.hpp>
#endif
#include <boost/move/utility_core.hpp>
#include <boost/core/no_exceptions_support.hpp>
namespace boost { namespace container {
namespace container_detail {
// Check if we can detect is_convertible using advanced SFINAE expressions
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
//! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
//! Thanks Mathias!
//With variadic templates, we need a single class to implement the trait
template<class T, class ...Args>
struct is_constructible
{
typedef char yes_type;
struct no_type
{ char padding[2]; };
template<std::size_t N>
struct dummy;
template<class X>
static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
template<class X>
static no_type test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
};
template <class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_prefix
: is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
{};
#else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//Without advanced SFINAE expressions, we can't use is_constructible
//so backup to constructible_with_allocator_xxx
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_prefix
: constructible_with_allocator_prefix<T>
{};
template <class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_suffix
: constructible_with_allocator_suffix<T>
{};
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
struct is_constructible_with_allocator_prefix
: constructible_with_allocator_prefix<T>
{};
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
struct is_constructible_with_allocator_suffix
: constructible_with_allocator_suffix<T>
{};
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template < typename ConstructAlloc
, typename ArgAlloc
, typename T
, class ...Args
>
inline typename container_detail::enable_if_and
< void
, container_detail::is_not_pair<T>
, container_detail::not_< uses_allocator<T, ArgAlloc> >
>::type dispatch_uses_allocator
( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
{
(void)arg_alloc;
allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
}
// allocator_arg_t
template < typename ConstructAlloc
, typename ArgAlloc
, typename T
, class ...Args
>
inline typename container_detail::enable_if_and
< void
, container_detail::is_not_pair<T>
, uses_allocator<T, ArgAlloc>
, is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
>::type dispatch_uses_allocator
( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
{
allocator_traits<ConstructAlloc>::construct
( construct_alloc, p, allocator_arg
, ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
}
// allocator suffix
template < typename ConstructAlloc
, typename ArgAlloc
, typename T
, class ...Args
>
inline typename container_detail::enable_if_and
< void
, container_detail::is_not_pair<T>
, uses_allocator<T, ArgAlloc>
, container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
>::type dispatch_uses_allocator
( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
{
allocator_traits<ConstructAlloc>::construct
(construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
}
#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline typename container_detail::enable_if_and\
< void\
, container_detail::is_not_pair<T>\
, container_detail::not_<uses_allocator<T, ArgAlloc> >\
>::type\
dispatch_uses_allocator\
(ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
(void)arg_alloc;\
allocator_traits<ConstructAlloc>::construct(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline typename container_detail::enable_if_and\
< void\
, container_detail::is_not_pair<T>\
, uses_allocator<T, ArgAlloc>\
, is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
>::type\
dispatch_uses_allocator\
(ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
allocator_traits<ConstructAlloc>::construct\
(construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline typename container_detail::enable_if_and\
< void\
, container_detail::is_not_pair<T>\
, uses_allocator<T, ArgAlloc>\
, container_detail::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
>::type\
dispatch_uses_allocator\
(ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
allocator_traits<ConstructAlloc>::construct\
(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
}\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template < typename ConstructAlloc
, typename ArgAlloc
, typename Pair
> inline
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
dispatch_uses_allocator
( ConstructAlloc & construct_alloc
, ArgAlloc & arg_alloc
, Pair* p)
{
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first));
BOOST_TRY{
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second));
}
BOOST_CATCH(...) {
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
BOOST_RETHROW
}
BOOST_CATCH_END
}
template < typename ConstructAlloc
, typename ArgAlloc
, class Pair, class U, class V>
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if<container_detail::is_pair<Pair> >::type)
dispatch_uses_allocator
( ConstructAlloc & construct_alloc
, ArgAlloc & arg_alloc
, Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->first), ::boost::forward<U>(x));
BOOST_TRY{
(dispatch_uses_allocator)(construct_alloc, arg_alloc, container_detail::addressof(p->second), ::boost::forward<V>(y));
}
BOOST_CATCH(...){
allocator_traits<ConstructAlloc>::destroy(construct_alloc, container_detail::addressof(p->first));
BOOST_RETHROW
}
BOOST_CATCH_END
}
template < typename ConstructAlloc
, typename ArgAlloc
, class Pair, class Pair2>
BOOST_CONTAINER_DOC1ST(void, typename container_detail::enable_if< container_detail::is_pair<Pair> >::type)
dispatch_uses_allocator
(ConstructAlloc & construct_alloc
, ArgAlloc & arg_alloc
, Pair* p, Pair2& x)
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
template < typename ConstructAlloc
, typename ArgAlloc
, class Pair, class Pair2>
typename container_detail::enable_if_and
< void
, container_detail::is_pair<Pair>
, container_detail::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
dispatch_uses_allocator
(ConstructAlloc & construct_alloc
, ArgAlloc & arg_alloc
, Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
//template <typename ConstructAlloc, typename ArgAlloc, class Pair, class Pair2>
//void dispatch_uses_allocator( ConstructAlloc & construct_alloc, ArgAlloc & arg_alloc
// , pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
} //namespace container_detail
}} // namespace boost { namespace container {
#include <boost/container/detail/config_end.hpp>
#endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP

View File

@@ -0,0 +1,103 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
#define BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/detail/alloc_lib.h>
namespace boost{
namespace container{
typedef boost_cont_command_ret_t dlmalloc_command_ret_t;
typedef boost_cont_memchain dlmalloc_memchain;
typedef boost_cont_memchain_it dlmalloc_memchain_it;
typedef boost_cont_malloc_stats_t dlmalloc_malloc_stats_t;
BOOST_CONTAINER_DECL size_t dlmalloc_size(const void *p);
BOOST_CONTAINER_DECL void* dlmalloc_malloc(size_t bytes);
BOOST_CONTAINER_DECL void dlmalloc_free(void* mem);
BOOST_CONTAINER_DECL void* dlmalloc_memalign(size_t bytes, size_t alignment);
BOOST_CONTAINER_DECL int dlmalloc_multialloc_nodes
(size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL int dlmalloc_multialloc_arrays
(size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL void dlmalloc_multidealloc(boost_cont_memchain *pchain);
BOOST_CONTAINER_DECL size_t dlmalloc_footprint();
BOOST_CONTAINER_DECL size_t dlmalloc_allocated_memory();
BOOST_CONTAINER_DECL size_t dlmalloc_chunksize(const void *p);
BOOST_CONTAINER_DECL int dlmalloc_all_deallocated();
BOOST_CONTAINER_DECL boost_cont_malloc_stats_t dlmalloc_malloc_stats();
BOOST_CONTAINER_DECL size_t dlmalloc_in_use_memory();
BOOST_CONTAINER_DECL int dlmalloc_trim(size_t pad);
BOOST_CONTAINER_DECL int dlmalloc_mallopt(int parameter_number, int parameter_value);
BOOST_CONTAINER_DECL int dlmalloc_grow(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
BOOST_CONTAINER_DECL int dlmalloc_shrink(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
BOOST_CONTAINER_DECL void* dlmalloc_alloc(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
BOOST_CONTAINER_DECL int dlmalloc_malloc_check();
BOOST_CONTAINER_DECL boost_cont_command_ret_t dlmalloc_allocation_command
( allocation_type command
, size_t sizeof_object
, size_t limit_objects
, size_t preferred_objects
, size_t *received_objects
, void *reuse_ptr
);
BOOST_CONTAINER_DECL int dlmalloc_mallopt(int param_number, int value);
BOOST_CONTAINER_DECL void *dlmalloc_sync_create();
BOOST_CONTAINER_DECL void dlmalloc_sync_destroy(void *sync);
BOOST_CONTAINER_DECL bool dlmalloc_sync_lock(void *sync);
BOOST_CONTAINER_DECL void dlmalloc_sync_unlock(void *sync);
BOOST_CONTAINER_DECL bool dlmalloc_global_sync_lock();
BOOST_CONTAINER_DECL void dlmalloc_global_sync_unlock();
} //namespace container{
} //namespace boost{
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP

View File

@@ -25,7 +25,7 @@
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/pool_common.hpp>
#include <boost/container/detail/alloc_lib.h>
#include <boost/container/detail/dlmalloc.hpp>
#include <cstddef>
namespace boost{
@@ -44,15 +44,15 @@ struct fake_segment_manager
typedef boost::container::container_detail::
basic_multiallocation_chain<void*> multiallocation_chain;
static void deallocate(void_pointer p)
{ boost_cont_free(p); }
{ dlmalloc_free(p); }
static void deallocate_many(multiallocation_chain &chain)
{
std::size_t size = chain.size();
std::pair<void*, void*> ptrs = chain.extract_data();
boost_cont_memchain dlchain;
dlmalloc_memchain dlchain;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
boost_cont_multidealloc(&dlchain);
dlmalloc_multidealloc(&dlchain);
}
typedef std::ptrdiff_t difference_type;
@@ -60,7 +60,7 @@ struct fake_segment_manager
static void *allocate_aligned(std::size_t nbytes, std::size_t alignment)
{
void *ret = boost_cont_memalign(nbytes, alignment);
void *ret = dlmalloc_memalign(nbytes, alignment);
if(!ret)
boost::container::throw_bad_alloc();
return ret;
@@ -68,7 +68,7 @@ struct fake_segment_manager
static void *allocate(std::size_t nbytes)
{
void *ret = boost_cont_malloc(nbytes);
void *ret = dlmalloc_malloc(nbytes);
if(!ret)
boost::container::throw_bad_alloc();
return ret;

View File

@@ -0,0 +1,191 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_POOL_RESOURCE_HPP
#define BOOST_CONTAINER_POOL_RESOURCE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/detail/block_list.hpp>
#include <boost/container/pmr/pool_options.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
class pool_data_t;
static const std::size_t pool_options_minimum_max_blocks_per_chunk = 1u;
static const std::size_t pool_options_default_max_blocks_per_chunk = 32u;
static const std::size_t pool_options_minimum_largest_required_pool_block =
memory_resource::max_align > 2*sizeof(void*) ? memory_resource::max_align : 2*sizeof(void*);
static const std::size_t pool_options_default_largest_required_pool_block =
pool_options_minimum_largest_required_pool_block > 4096u
? pool_options_minimum_largest_required_pool_block : 4096u;
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
class pool_resource
{
typedef block_list_base<> block_list_base_t;
pool_options m_options;
memory_resource& m_upstream;
block_list_base_t m_oversized_list;
pool_data_t *m_pool_data;
std::size_t m_pool_count;
static void priv_limit_option(std::size_t &val, std::size_t min, std::size_t max);
static std::size_t priv_pool_index(std::size_t block_size);
static std::size_t priv_pool_block(std::size_t index);
void priv_fix_options();
void priv_init_pools();
void priv_constructor_body();
public:
//! <b>Requires</b>: `upstream` is the address of a valid memory resource.
//!
//! <b>Effects</b>: Constructs a pool resource object that will obtain memory
//! from upstream whenever the pool resource is unable to satisfy a memory
//! request from its own internal data structures. The resulting object will hold
//! a copy of upstream, but will not own the resource to which upstream points.
//! [ Note: The intention is that calls to upstream->allocate() will be
//! substantially fewer than calls to this->allocate() in most cases. - end note
//! The behavior of the pooling mechanism is tuned according to the value of
//! the opts argument.
//!
//! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if
//! or under what conditions this constructor calls upstream->allocate().
pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
//! <b>Effects</b>: Same as
//! `pool_resource(pool_options(), get_default_resource())`.
pool_resource() BOOST_NOEXCEPT;
//! <b>Effects</b>: Same as
//! `pool_resource(pool_options(), upstream)`.
explicit pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
//! <b>Effects</b>: Same as
//! `pool_resource(opts, get_default_resource())`.
explicit pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
pool_resource(const pool_resource&) = delete;
pool_resource operator=(const pool_resource&) = delete;
#else
private:
pool_resource (const pool_resource&);
pool_resource operator=(const pool_resource&);
public:
#endif
//! <b>Effects</b>: Calls
//! `this->release()`.
virtual ~pool_resource();
//! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary
//! to release all allocated memory. [ Note: memory is released back to
//! `upstream_resource()` even if deallocate has not been called for some
//! of the allocated blocks. - end note ]
void release();
//! <b>Returns</b>: The value of the upstream argument provided to the
//! constructor of this object.
memory_resource* upstream_resource() const;
//! <b>Returns</b>: The options that control the pooling behavior of this resource.
//! The values in the returned struct may differ from those supplied to the pool
//! resource constructor in that values of zero will be replaced with
//! implementation-defined defaults and sizes may be rounded to unspecified granularity.
pool_options options() const;
public: //public so that [un]synchronized_pool_resource can use them
//! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`.
//! The size and alignment of the allocated memory shall meet the requirements for
//! a class derived from `memory_resource`.
//!
//! <b>Effects</b>: If the pool selected for a block of size bytes is unable to
//! satisfy the memory request from its own internal data structures, it will call
//! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger
//! than that which the largest pool can handle, then memory will be allocated
//! using `upstream_resource()->allocate()`.
//!
//! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
//! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under
//! what circumstances this operation will result in a call to
//! `upstream_resource()->deallocate()`.
//!
//! <b>Throws</b>: Nothing.
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
//! <b>Returns</b>:
//! `this == dynamic_cast<const pool_resource*>(&other)`.
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
//Non-standard observers
public:
//! <b>Returns</b>: The number of pools that will be used in the pool resource.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_count() const;
//! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`.
//! from the pool specified by `pool_index`. Returns `pool_count()` if `bytes` is bigger
//! than `options().largest_required_pool_block` (no pool will be used to serve this).
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_index(std::size_t bytes) const;
//! <b>Requires</b>: `pool_idx < pool_index()`
//!
//! <b>Returns</b>: The number blocks that will be allocated in the next chunk
//! from the pool specified by `pool_idx`.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
//! <b>Requires</b>: `pool_idx < pool_index()`
//!
//! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_block(std::size_t pool_idx) const;
//! <b>Requires</b>: `pool_idx < pool_index()`
//!
//! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached
//! and will be served without calling the upstream_allocator.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_cached_blocks(std::size_t pool_idx) const;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_POOL_RESOURCE_HPP

View File

@@ -30,6 +30,8 @@ namespace boost {
namespace container {
namespace container_detail {
using ::boost::move_detail::enable_if;
using ::boost::move_detail::enable_if_and;
using ::boost::move_detail::is_same;
using ::boost::move_detail::is_different;
using ::boost::move_detail::is_pointer;

View File

@@ -19,8 +19,6 @@
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_CONTAINER_PERFECT_FORWARDING
@@ -59,6 +57,23 @@
#define BOOST_CONTAINER_DOCIGN(T) T
#define BOOST_CONTAINER_DOCONLY(T)
#include <boost/container/detail/config_end.hpp>
/*
we need to import/export our code only if the user has specifically
asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
if they want just this one to be dynamically liked:
*/
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
/* export if this is our own source, otherwise import: */
#ifdef BOOST_CONTAINER_SOURCE
# define BOOST_CONTAINER_DECL BOOST_SYMBOL_EXPORT
#else
# define BOOST_CONTAINER_DECL BOOST_SYMBOL_IMPORT
#endif /* BOOST_CONTAINER_SOURCE */
#else
#define BOOST_CONTAINER_DECL
#endif /* DYN_LINK */
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP

View File

@@ -26,7 +26,7 @@
#include <boost/container/detail/node_pool.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/multiallocation_chain.hpp>
#include <boost/container/detail/alloc_lib_auto_link.hpp>
#include <boost/container/detail/dlmalloc.hpp>
#include <boost/container/detail/singleton.hpp>
#include <boost/assert.hpp>
@@ -157,7 +157,7 @@ class node_allocator
return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
}
else{
void *ret = boost_cont_malloc(count*sizeof(T));
void *ret = dlmalloc_malloc(count*sizeof(T));
if(BOOST_UNLIKELY(!ret))
boost::container::throw_bad_alloc();
return static_cast<pointer>(ret);
@@ -176,7 +176,7 @@ class node_allocator
singleton_t::instance().deallocate_node(ptr);
}
else{
boost_cont_free(ptr);
dlmalloc_free(ptr);
}
}
@@ -204,7 +204,7 @@ class node_allocator
size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_STATIC_ASSERT(( Version > 1 ));
return boost_cont_size(p);
return dlmalloc_size(p);
}
//!Allocates just one object. Memory allocated with this function
@@ -259,9 +259,9 @@ class node_allocator
void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
if(BOOST_UNLIKELY(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){
boost::container::throw_bad_alloc();
}
chain.incorporate_after( chain.before_begin()
@@ -275,8 +275,8 @@ class node_allocator
void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
{
BOOST_STATIC_ASSERT(( Version > 1 ));
boost_cont_memchain ch;
boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
dlmalloc_memchain ch;
dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
if(BOOST_UNLIKELY(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch))){
boost::container::throw_bad_alloc();
}
@@ -292,9 +292,9 @@ class node_allocator
void *first = &*chain.begin();
void *last = &*chain.last();
size_t num = chain.size();
boost_cont_memchain ch;
dlmalloc_memchain ch;
BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
boost_cont_multidealloc(&ch);
dlmalloc_multidealloc(&ch);
}
//!Swaps allocators. Does not throw. If each allocator is placed in a
@@ -319,7 +319,7 @@ class node_allocator
,pointer &reuse)
{
std::size_t const preferred_size = prefer_in_recvd_out_size;
boost_cont_command_ret_t ret = {0 , 0};
dlmalloc_command_ret_t ret = {0 , 0};
if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
return pointer();
}
@@ -328,7 +328,7 @@ class node_allocator
std::size_t r_size;
{
void* reuse_ptr_void = reuse;
ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
reuse = static_cast<T*>(reuse_ptr_void);
}
prefer_in_recvd_out_size = r_size/sizeof(T);

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_DEQUE_HPP
#define BOOST_CONTAINER_PMR_DEQUE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/deque.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
using deque = boost::container::deque<T, polymorphic_allocator<T>>;
#endif
template<class T>
struct deque_of
{
typedef boost::container::deque
< T, polymorphic_allocator<T> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_DEQUE_HPP

View File

@@ -0,0 +1,63 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_FLAT_MAP_HPP
#define BOOST_CONTAINER_PMR_FLAT_MAP_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/flat_map.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using flat_map = boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using flat_multimap = boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
#endif
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct flat_map_of
{
typedef boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
};
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct flat_multimap_of
{
typedef boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_FLAT_MAP_HPP

View File

@@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_SET_HPP
#define BOOST_CONTAINER_PMR_SET_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/flat_set.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using flat_set = boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> >;
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using flat_multiset = boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> >;
#endif
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct flat_set_of
{
typedef boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> > type;
};
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct flat_multiset_of
{
typedef boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_SET_HPP

View File

@@ -0,0 +1,66 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
#define BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/auto_link.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
/// @cond
class memory_resource;
/// @endcond
//! <b>Returns</b>: A pointer to a static-duration object of a type derived from
//! memory_resource that can serve as a resource for allocating memory using
//! global `operator new` and global `operator delete`. The same value is returned every time this function
//! is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.
BOOST_CONTAINER_DECL memory_resource* new_delete_resource() BOOST_NOEXCEPT;
//! <b>Returns</b>: A pointer to a static-duration object of a type derived from
//! memory_resource for which allocate() always throws bad_alloc and for which
//! deallocate() has no effect. The same value is returned every time this function
//! is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.
BOOST_CONTAINER_DECL memory_resource* null_memory_resource() BOOST_NOEXCEPT;
//! <b>Effects</b>: If r is non-null, sets the value of the default memory resource
//! pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
//!
//! <b>Postconditions</b>: get_default_resource() == r.
//!
//! <b>Returns</b>: The previous value of the default memory resource pointer.
//!
//! <b>Remarks</b>: Calling the set_default_resource and get_default_resource functions shall
//! not incur a data race. A call to the set_default_resource function shall synchronize
//! with subsequent calls to the set_default_resource and get_default_resource functions.
BOOST_CONTAINER_DECL memory_resource* set_default_resource(memory_resource* r) BOOST_NOEXCEPT;
//! <b>Returns</b>: The current value of the default
//! memory resource pointer.
BOOST_CONTAINER_DECL memory_resource* get_default_resource() BOOST_NOEXCEPT;
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_LIST_HPP
#define BOOST_CONTAINER_PMR_LIST_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/list.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
using list = boost::container::list<T, polymorphic_allocator<T>>;
#endif
template<class T>
struct list_of
{
typedef boost::container::list
< T, polymorphic_allocator<T> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP

View File

@@ -0,0 +1,63 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_MAP_HPP
#define BOOST_CONTAINER_PMR_MAP_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/map.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using map = boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using multimap = boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
#endif
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct map_of
{
typedef boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
};
template <class Key
,class T
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct multimap_of
{
typedef boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_MAP_HPP

View File

@@ -0,0 +1,101 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
#define BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/move/detail/type_traits.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//! The memory_resource class is an abstract interface to an
//! unbounded set of classes encapsulating memory resources.
class memory_resource
{
public:
// For exposition only
static BOOST_CONSTEXPR_OR_CONST std::size_t max_align =
boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
//! <b>Effects</b>: Destroys
//! this memory_resource.
virtual ~memory_resource(){}
//! <b>Effects</b>: Equivalent to
//! `return do_allocate(bytes, alignment);`
void* allocate(std::size_t bytes, std::size_t alignment = max_align)
{ return this->do_allocate(bytes, alignment); }
//! <b>Effects</b>: Equivalent to
//! `return do_deallocate(bytes, alignment);`
void deallocate(void* p, std::size_t bytes, std::size_t alignment = max_align)
{ return this->do_deallocate(p, bytes, alignment); }
//! <b>Effects</b>: Equivalent to
//! `return return do_is_equal(other);`
bool is_equal(const memory_resource& other) const BOOST_NOEXCEPT
{ return this->do_is_equal(other); }
//! <b>Returns</b>:
//! `&a == &b || a.is_equal(b)`.
friend bool operator==(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
{ return &a == &b || a.is_equal(b); }
//! <b>Returns</b>:
//! !(a == b).
friend bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
{ return !(a == b); }
protected:
//! <b>Requires</b>: Alignment shall be a power of two.
//!
//! <b>Returns</b>: A derived class shall implement this function to return a pointer
//! to allocated storage with a size of at least bytes. The returned storage is
//! aligned to the specified alignment, if such alignment is supported; otherwise
//! it is aligned to max_align.
//!
//! <b>Throws</b>: A derived class implementation shall throw an appropriate exception if
//! it is unable to allocate memory with the requested size and alignment.
virtual void* do_allocate(std::size_t bytes, std::size_t alignment) = 0;
//! <b>Requires</b>: p shall have been returned from a prior call to
//! `allocate(bytes, alignment)` on a memory resource equal to *this, and the storage
//! at p shall not yet have been deallocated.
//!
//! <b>Effects</b>: A derived class shall implement this function to dispose of allocated storage.
//!
//! <b>Throws</b>: Nothing.
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) = 0;
//! <b>Returns</b>: A derived class shall implement this function to return true if memory
//! allocated from this can be deallocated from other and vice-versa; otherwise it shall
//! return false. <i>[Note: The most-derived type of other might not match the type of this.
//! For a derived class, D, a typical implementation of this function will compute
//! `dynamic_cast<const D*>(&other)` and go no further (i.e., return false)
//! if it returns nullptr. - end note]</i>.
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT = 0;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP

View File

@@ -0,0 +1,180 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
#define BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/detail/block_slist.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//! A monotonic_buffer_resource is a special-purpose memory resource intended for
//! very fast memory allocations in situations where memory is used to build up a
//! few objects and then is released all at once when the memory resource object
//! is destroyed. It has the following qualities:
//!
//! - A call to deallocate has no effect, thus the amount of memory consumed
//! increases monotonically until the resource is destroyed.
//!
//! - The program can supply an initial buffer, which the allocator uses to satisfy
//! memory requests.
//!
//! - When the initial buffer (if any) is exhausted, it obtains additional buffers
//! from an upstream memory resource supplied at construction. Each additional
//! buffer is larger than the previous one, following a geometric progression.
//!
//! - It is intended for access from one thread of control at a time. Specifically,
//! calls to allocate and deallocate do not synchronize with one another.
//!
//! - It owns the allocated memory and frees it on destruction, even if deallocate has
//! not been called for some of the allocated blocks.
class BOOST_CONTAINER_DECL monotonic_buffer_resource
: public memory_resource
{
block_slist m_memory_blocks;
void* m_current_buffer;
std::size_t m_current_buffer_size;
std::size_t m_next_buffer_size;
/// @cond
void increase_next_buffer();
void increase_next_buffer_at_least_to(std::size_t minimum_size);
void *allocate_from_current(std::size_t aligner, std::size_t bytes);
/// @endcond
public:
//! The number of bytes that will be requested by the default in the first call
//! to the upstream allocator
//!
//! <b>Note</b>: Non-standard extension.
static const std::size_t initial_next_buffer_size = 32u*sizeof(void*);
//! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
//!
//! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
//! to get_default_resource() otherwise.
//! Sets the internal `current_buffer` to `nullptr` and the internal `next_buffer_size` to an
//! implementation-defined size.
explicit monotonic_buffer_resource(memory_resource* upstream = 0) BOOST_NOEXCEPT;
//! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
//! and `initial_size` shall be greater than zero.
//!
//! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
//! to get_default_resource() otherwise. Sets the internal `current_buffer` to `nullptr` and
//! `next_buffer_size` to at least `initial_size`.
explicit monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
//! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`,
//! `buffer_size` shall be no larger than the number of bytes in buffer.
//!
//! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
//! to get_default_resource() otherwise. Sets the internal `current_buffer` to `buffer`,
//! and `next_buffer_size` to `buffer_size` (but not less than an implementation-defined size),
//! then increases `next_buffer_size` by an implementation-defined growth factor (which need not be integral).
monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
monotonic_buffer_resource operator=(const monotonic_buffer_resource&) = delete;
#else
private:
monotonic_buffer_resource (const monotonic_buffer_resource&);
monotonic_buffer_resource operator=(const monotonic_buffer_resource&);
public:
#endif
//! <b>Effects</b>: Calls
//! `this->release()`.
virtual ~monotonic_buffer_resource();
//! <b>Effects</b>: `upstream_resource()->deallocate()` as necessary to release all allocated memory.
//! [Note: memory is released back to `upstream_resource()` even if some blocks that were allocated
//! from this have not been deallocated from this. - end note]
void release() BOOST_NOEXCEPT;
//! <b>Returns</b>: The value of
//! the internal resource.
memory_resource* upstream_resource() const BOOST_NOEXCEPT;
//! <b>Returns</b>:
//! The number of bytes of storage available for the specified alignment and
//! the number of bytes wasted due to the requested alignment.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t remaining_storage(std::size_t alignment, std::size_t &wasted_due_to_alignment) const BOOST_NOEXCEPT;
//! <b>Returns</b>:
//! The number of bytes of storage available for the specified alignment.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t remaining_storage(std::size_t alignment = 1u) const BOOST_NOEXCEPT;
//! <b>Returns</b>:
//! The number of bytes of storage available for the specified alignment.
//!
//! <b>Note</b>: Non-standard extension.
const void *current_buffer() const BOOST_NOEXCEPT;
//! <b>Returns</b>:
//! The number of bytes that will be requested for the next buffer once the
//! current one is exhausted.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t next_buffer_size() const BOOST_NOEXCEPT;
protected:
//! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`. The size
//! and alignment of the allocated memory shall meet the requirements for a class derived
//! from `memory_resource`.
//!
//! <b>Effects</b>: If the unused space in the internal `current_buffer` can fit a block with the specified
//! bytes and alignment, then allocate the return block from the internal `current_buffer`; otherwise sets
//! the internal `current_buffer` to `upstream_resource()->allocate(n, m)`, where `n` is not less than
//! `max(bytes, next_buffer_size)` and `m` is not less than alignment, and increase
//! `next_buffer_size` by an implementation-defined growth factor (which need not be integral),
//! then allocate the return block from the newly-allocated internal `current_buffer`.
//!
//! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
//! <b>Effects</b>: None
//!
//! <b>Throws</b>: Nothing
//!
//! <b>Remarks</b>: Memory used by this resource increases monotonically until its destruction.
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_NOEXCEPT;
//! <b>Returns</b>:
//! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP

View File

@@ -0,0 +1,166 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
#define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/move/detail/type_traits.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/container/detail/dispatch_uses_allocator.hpp>
#include <boost/container/new_allocator.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/pmr/global_resource.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//! A specialization of class template `polymorphic_allocator` conforms to the Allocator requirements.
//! Constructed with different memory resources, different instances of the same specialization of
//! `polymorphic_allocator` can exhibit entirely different allocation behavior. This runtime
//! polymorphism allows objects that use polymorphic_allocator to behave as if they used different
//! allocator types at run time even though they use the same static allocator type.
template <class T>
class polymorphic_allocator
{
public:
typedef T value_type;
//! <b>Effects</b>: Sets m_resource to
//! `get_default_resource()`.
polymorphic_allocator() BOOST_NOEXCEPT
: m_resource(::boost::container::pmr::get_default_resource())
{}
//! <b>Requires</b>: r is non-null.
//!
//! <b>Effects</b>: Sets m_resource to r.
//!
//! <b>Throws</b>: Nothing
//!
//! <b>Notes</b>: This constructor provides an implicit conversion from memory_resource*.
//! Non-standard extension: if r is null m_resource is set to get_default_resource().
polymorphic_allocator(memory_resource* r)
: m_resource(r ? r : ::boost::container::pmr::get_default_resource())
{}
//! <b>Effects</b>: Sets m_resource to
//! other.resource().
polymorphic_allocator(const polymorphic_allocator& other)
: m_resource(other.m_resource)
{}
//! <b>Effects</b>: Sets m_resource to
//! other.resource().
template <class U>
polymorphic_allocator(const polymorphic_allocator<U>& other) BOOST_NOEXCEPT
: m_resource(other.resource())
{}
//! <b>Effects</b>: Sets m_resource to
//! other.resource().
polymorphic_allocator& operator=(const polymorphic_allocator& other)
{ m_resource = other.m_resource; return *this; }
//! <b>Returns</b>: Equivalent to
//! `static_cast<T*>(m_resource->allocate(n * sizeof(T), alignof(T)))`.
T* allocate(size_t n)
{ return static_cast<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); }
//! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource,
//! using `x.allocate(n * sizeof(T), alignof(T))`.
//!
//! <b>Effects</b>: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)).
//!
//! <b>Throws</b>: Nothing.
void deallocate(T* p, size_t n)
{ m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of<T>::value); }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Requires</b>: Uses-allocator construction of T with allocator
//! `this->resource()` and constructor arguments `std::forward<Args>(args)...`
//! is well-formed. [Note: uses-allocator construction is always well formed for
//! types that do not use allocators. - end note]
//!
//! <b>Effects</b>: Construct a T object at p by uses-allocator construction with allocator
//! `this->resource()` and constructor arguments `std::forward<Args>(args)...`.
//!
//! <b>Throws</b>: Nothing unless the constructor for T throws.
template < typename U, class ...Args>
void construct(U* p, BOOST_FWD_REF(Args)...args)
{
new_allocator<U> na;
container_detail::dispatch_uses_allocator
(na, this->resource(), p, ::boost::forward<Args>(args)...);
}
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//Disable this overload if the first argument is pair as some compilers have
//overload selection problems when the first parameter is a pair.
#define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE(N) \
template < typename U BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
void construct(U* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
{\
new_allocator<U> na;\
container_detail::dispatch_uses_allocator\
(na, this->resource(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
}\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE)
#undef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>:
//! p->~U().
template <class U>
void destroy(U* p)
{ (void)p; p->~U(); }
//! <b>Returns</b>: Equivalent to
//! `polymorphic_allocator()`.
polymorphic_allocator select_on_container_copy_construction() const
{ return polymorphic_allocator(); }
//! <b>Returns</b>:
//! m_resource.
memory_resource* resource() const
{ return m_resource; }
private:
memory_resource* m_resource;
};
//! <b>Returns</b>:
//! `*a.resource() == *b.resource()`.
template <class T1, class T2>
bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
{ return *a.resource() == *b.resource(); }
//! <b>Returns</b>:
//! `! (a == b)`.
template <class T1, class T2>
bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
{ return *a.resource() != *b.resource(); }
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP

View File

@@ -0,0 +1,52 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
#define BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//! The members of pool_options comprise a set of constructor options for pool resources.
//! The effect of each option on the pool resource behavior is described below:
//!
//! - `std::size_t max_blocks_per_chunk`: The maximum number of blocks that will be allocated
//! at once from the upstream memory resource to replenish a pool. If the value of
//! `max_blocks_per_chunk` is zero or is greater than an implementation-defined limit,
//! that limit is used instead. The implementation may choose to use a smaller value
//! than is specified in this field and may use different values for different pools.
//!
//! - `std::size_t largest_required_pool_block`: The largest allocation size that is required
//! to be fulfilled using the pooling mechanism. Attempts to allocate a single block
//! larger than this threshold will be allocated directly from the upstream memory
//! resource. If largest_required_pool_block is zero or is greater than an
//! implementation-defined limit, that limit is used instead. The implementation may
//! choose a pass-through threshold larger than specified in this field.
struct pool_options
{
pool_options()
: max_blocks_per_chunk(0u), largest_required_pool_block(0u)
{}
std::size_t max_blocks_per_chunk;
std::size_t largest_required_pool_block;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP

View File

@@ -0,0 +1,193 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
#define BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/intrusive/detail/ebo_functor_holder.hpp>
#include <boost/move/utility_core.hpp>
namespace boost {
namespace container {
namespace pmr {
//! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
//! around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same
//! type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as
//! an alias to this class template such that Allocator is rebound to a char value type in every
//! specialization of the class template. The requirements on this class template are defined below.
//! In addition to the Allocator requirements, the parameter to resource_adaptor shall meet
//! the following additional requirements:
//!
//! - `typename allocator_traits<Allocator>:: pointer` shall be identical to
//! `typename allocator_traits<Allocator>:: value_type*`.
//!
//! - `typename allocator_traits<Allocator>:: const_pointer` shall be identical to
//! `typename allocator_traits<Allocator>:: value_type const*`.
//!
//! - `typename allocator_traits<Allocator>:: void_pointer` shall be identical to `void*`.
//!
//! - `typename allocator_traits<Allocator>:: const_void_pointer` shall be identical to `void const*`.
template <class Allocator>
class resource_adaptor_imp
: public memory_resource
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
, private ::boost::intrusive::detail::ebo_functor_holder<Allocator>
#endif
{
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
Allocator m_alloc;
#else
BOOST_COPYABLE_AND_MOVABLE(resource_adaptor_imp)
typedef ::boost::intrusive::detail::ebo_functor_holder<Allocator> ebo_alloc_t;
void static_assert_if_not_char_allocator() const
{
//This class can only be used with allocators type char
BOOST_STATIC_ASSERT((container_detail::is_same<typename Allocator::value_type, char>::value));
}
#endif
public:
typedef Allocator allocator_type;
//! <b>Effects</b>: Default constructs
//! m_alloc.
resource_adaptor_imp()
{ this->static_assert_if_not_char_allocator(); }
//! <b>Effects</b>: Copy constructs
//! m_alloc.
resource_adaptor_imp(const resource_adaptor_imp &other)
: ebo_alloc_t(other.ebo_alloc_t::get())
{}
//! <b>Effects</b>: Move constructs
//! m_alloc.
resource_adaptor_imp(BOOST_RV_REF(resource_adaptor_imp) other)
: ebo_alloc_t(::boost::move(other.get()))
{}
//! <b>Effects</b>: Initializes m_alloc with
//! a2.
explicit resource_adaptor_imp(const Allocator& a2)
: ebo_alloc_t(a2)
{ this->static_assert_if_not_char_allocator(); }
//! <b>Effects</b>: Initializes m_alloc with
//! a2.
explicit resource_adaptor_imp(BOOST_RV_REF(Allocator) a2)
: ebo_alloc_t(::boost::move(a2))
{ this->static_assert_if_not_char_allocator(); }
//! <b>Effects</b>: Copy assigns
//! m_alloc.
resource_adaptor_imp& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor_imp) other)
{ this->ebo_alloc_t::get() = other.ebo_alloc_t::get(); return *this; }
//! <b>Effects</b>: Move assigns
//! m_alloc.
resource_adaptor_imp& operator=(BOOST_RV_REF(resource_adaptor_imp) other)
{ this->ebo_alloc_t::get() = ::boost::move(other.ebo_alloc_t::get()); return *this; }
//! <b>Effects</b>: Returns m_alloc.
allocator_type &get_allocator()
{ return this->ebo_alloc_t::get(); }
//! <b>Effects</b>: Returns m_alloc.
const allocator_type &get_allocator() const
{ return this->ebo_alloc_t::get(); }
protected:
//! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
//! of the allocated memory shall meet the requirements for a class derived from memory_resource.
virtual void* do_allocate(size_t bytes, size_t alignment)
{ (void)alignment; return this->ebo_alloc_t::get().allocate(bytes); }
//! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
//! subsequently deallocated.
//!
//! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
virtual void do_deallocate(void* p, size_t bytes, size_t alignment)
{ (void)alignment; this->ebo_alloc_t::get().deallocate((char*)p, bytes); }
//! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
//!
//! <b>Returns</b>: false if p is null, otherwise the value of m_alloc == p->m_alloc.
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT
{
const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
}
};
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! `resource_adaptor<Allocator>` is rendered as an alias to resource_adaptor_imp class template
//! such that Allocator is rebound to a char value type.
template <class Allocator>
using resource_adaptor = resource_adaptor_imp
<typename allocator_traits<Allocator>::template rebind_alloc<char> >;
#else
template <class Allocator>
class resource_adaptor
: public resource_adaptor_imp
<typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type>
{
typedef resource_adaptor_imp
<typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type> base_t;
BOOST_COPYABLE_AND_MOVABLE(resource_adaptor)
public:
resource_adaptor()
: base_t()
{}
resource_adaptor(const resource_adaptor &other)
: base_t(other)
{}
resource_adaptor(BOOST_RV_REF(resource_adaptor) other)
: base_t(BOOST_MOVE_BASE(base_t, other))
{}
explicit resource_adaptor(const Allocator& a2)
: base_t(a2)
{}
explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
: base_t(BOOST_MOVE_BASE(base_t, a2))
{}
resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
{ return static_cast<resource_adaptor&>(this->base_t::operator=(other)); }
resource_adaptor& operator=(BOOST_RV_REF(resource_adaptor) other)
{ return static_cast<resource_adaptor&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, other))); }
//get_allocator and protected functions are properly inherited
};
#endif
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP

View File

@@ -0,0 +1,59 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_SET_HPP
#define BOOST_CONTAINER_PMR_SET_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/set.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using set = boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options>;
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
using multiset = boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options>;
#endif
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct set_of
{
typedef boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options> type;
};
template <class Key
,class Compare = std::less<Key>
,class Options = tree_assoc_defaults >
struct multiset_of
{
typedef boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options> type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_SET_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_SLIST_HPP
#define BOOST_CONTAINER_PMR_SLIST_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/slist.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
using slist = boost::container::slist<T, polymorphic_allocator<T>>;
#endif
template<class T>
struct slist_of
{
typedef boost::container::slist
< T, polymorphic_allocator<T> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
#define BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/small_vector.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T, std::size_t N>
using small_vector = boost::container::small_vector<T, N, polymorphic_allocator<T>>;
#endif
template<class T, std::size_t N>
struct small_vector_of
{
typedef boost::container::small_vector
< T, N, polymorphic_allocator<T> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
#define BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/stable_vector.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
using stable_vector = boost::container::stable_vector<T, polymorphic_allocator<T>>;
#endif
template<class T>
struct stable_vector_of
{
typedef boost::container::stable_vector
< T, polymorphic_allocator<T> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP

View File

@@ -0,0 +1,48 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_STRING_HPP
#define BOOST_CONTAINER_PMR_STRING_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/string.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class CharT, class Traits = std::char_traits<CharT> >
using basic_string =
boost::container::basic_string<CharT, Traits, polymorphic_allocator<CharT> >;
#endif
template <class CharT, class Traits = std::char_traits<CharT> >
struct basic_string_of
{
typedef boost::container::basic_string
<CharT, Traits, polymorphic_allocator<CharT> > type;
};
typedef basic_string_of<char>::type string;
typedef basic_string_of<wchar_t>::type wstring;
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_STRING_HPP

View File

@@ -0,0 +1,138 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
#define BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/detail/pool_resource.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//! A synchronized_pool_resource is a general-purpose memory resources having
//! the following qualities:
//!
//! - Each resource owns the allocated memory, and frees it on destruction,
//! even if deallocate has not been called for some of the allocated blocks.
//!
//! - A pool resource consists of a collection of pools, serving
//! requests for different block sizes. Each individual pool manages a
//! collection of chunks that are in turn divided into blocks of uniform size,
//! returned via calls to do_allocate. Each call to do_allocate(size, alignment)
//! is dispatched to the pool serving the smallest blocks accommodating at
//! least size bytes.
//!
//! - When a particular pool is exhausted, allocating a block from that pool
//! results in the allocation of an additional chunk of memory from the upstream
//! allocator (supplied at construction), thus replenishing the pool. With
//! each successive replenishment, the chunk size obtained increases
//! geometrically. [ Note: By allocating memory in chunks, the pooling strategy
//! increases the chance that consecutive allocations will be close together
//! in memory. - end note ]
//!
//! - Allocation requests that exceed the largest block size of any pool are
//! fulfilled directly from the upstream allocator.
//!
//! - A pool_options struct may be passed to the pool resource constructors to
//! tune the largest block size and the maximum chunk size.
//!
//! A synchronized_pool_resource may be accessed from multiple threads without
//! external synchronization and may have thread-specific pools to reduce
//! synchronization costs.
class BOOST_CONTAINER_DECL synchronized_pool_resource
: public memory_resource
{
pool_resource m_pool_resource;
void *m_opaque_sync;
public:
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options&,memory_resource*)
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource()
synchronized_pool_resource() BOOST_NOEXCEPT;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(memory_resource*)
explicit synchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options&)
explicit synchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
synchronized_pool_resource(const synchronized_pool_resource&) = delete;
synchronized_pool_resource operator=(const synchronized_pool_resource&) = delete;
#else
private:
synchronized_pool_resource (const synchronized_pool_resource&);
synchronized_pool_resource operator=(const synchronized_pool_resource&);
public:
#endif
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::~unsynchronized_pool_resource()
virtual ~synchronized_pool_resource();
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::release()
void release();
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::upstream_resource()const
memory_resource* upstream_resource() const;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::options()const
pool_options options() const;
protected:
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_allocate()
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_deallocate(void*,std::size_t,std::size_t)
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_is_equal(const memory_resource&)const
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
//Non-standard observers
public:
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_count()
std::size_t pool_count() const;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_index(std::size_t)const
std::size_t pool_index(std::size_t bytes) const;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_next_blocks_per_chunk(std::size_t)const
std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_block(std::size_t)const
std::size_t pool_block(std::size_t pool_idx) const;
//! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_cached_blocks(std::size_t)const
std::size_t pool_cached_blocks(std::size_t pool_idx) const;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP

View File

@@ -0,0 +1,194 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
#define BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/auto_link.hpp>
#include <boost/container/pmr/memory_resource.hpp>
#include <boost/container/detail/pool_resource.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace pmr {
//! A unsynchronized_pool_resource is a general-purpose memory resources having
//! the following qualities:
//!
//! - Each resource owns the allocated memory, and frees it on destruction,
//! even if deallocate has not been called for some of the allocated blocks.
//!
//! - A pool resource consists of a collection of pools, serving
//! requests for different block sizes. Each individual pool manages a
//! collection of chunks that are in turn divided into blocks of uniform size,
//! returned via calls to do_allocate. Each call to do_allocate(size, alignment)
//! is dispatched to the pool serving the smallest blocks accommodating at
//! least size bytes.
//!
//! - When a particular pool is exhausted, allocating a block from that pool
//! results in the allocation of an additional chunk of memory from the upstream
//! allocator (supplied at construction), thus replenishing the pool. With
//! each successive replenishment, the chunk size obtained increases
//! geometrically. [ Note: By allocating memory in chunks, the pooling strategy
//! increases the chance that consecutive allocations will be close together
//! in memory. - end note ]
//!
//! - Allocation requests that exceed the largest block size of any pool are
//! fulfilled directly from the upstream allocator.
//!
//! - A pool_options struct may be passed to the pool resource constructors to
//! tune the largest block size and the maximum chunk size.
//!
//! An unsynchronized_pool_resource class may not be accessed from multiple threads
//! simultaneously and thus avoids the cost of synchronization entirely in
//! single-threaded applications.
class BOOST_CONTAINER_DECL unsynchronized_pool_resource
: public memory_resource
{
pool_resource m_resource;
public:
//! <b>Requires</b>: `upstream` is the address of a valid memory resource.
//!
//! <b>Effects</b>: Constructs a pool resource object that will obtain memory
//! from upstream whenever the pool resource is unable to satisfy a memory
//! request from its own internal data structures. The resulting object will hold
//! a copy of upstream, but will not own the resource to which upstream points.
//! [ Note: The intention is that calls to upstream->allocate() will be
//! substantially fewer than calls to this->allocate() in most cases. - end note
//! The behavior of the pooling mechanism is tuned according to the value of
//! the opts argument.
//!
//! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if
//! or under what conditions this constructor calls upstream->allocate().
unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
//! <b>Effects</b>: Same as
//! `unsynchronized_pool_resource(pool_options(), get_default_resource())`.
unsynchronized_pool_resource() BOOST_NOEXCEPT;
//! <b>Effects</b>: Same as
//! `unsynchronized_pool_resource(pool_options(), upstream)`.
explicit unsynchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
//! <b>Effects</b>: Same as
//! `unsynchronized_pool_resource(opts, get_default_resource())`.
explicit unsynchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
unsynchronized_pool_resource operator=(const unsynchronized_pool_resource&) = delete;
#else
private:
unsynchronized_pool_resource (const unsynchronized_pool_resource&);
unsynchronized_pool_resource operator=(const unsynchronized_pool_resource&);
public:
#endif
//! <b>Effects</b>: Calls
//! `this->release()`.
virtual ~unsynchronized_pool_resource();
//! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary
//! to release all allocated memory. [ Note: memory is released back to
//! `upstream_resource()` even if deallocate has not been called for some
//! of the allocated blocks. - end note ]
void release();
//! <b>Returns</b>: The value of the upstream argument provided to the
//! constructor of this object.
memory_resource* upstream_resource() const;
//! <b>Returns</b>: The options that control the pooling behavior of this resource.
//! The values in the returned struct may differ from those supplied to the pool
//! resource constructor in that values of zero will be replaced with
//! implementation-defined defaults and sizes may be rounded to unspecified granularity.
pool_options options() const;
protected:
//! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`.
//! The size and alignment of the allocated memory shall meet the requirements for
//! a class derived from `memory_resource`.
//!
//! <b>Effects</b>: If the pool selected for a block of size bytes is unable to
//! satisfy the memory request from its own internal data structures, it will call
//! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger
//! than that which the largest pool can handle, then memory will be allocated
//! using `upstream_resource()->allocate()`.
//!
//! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
//! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under
//! what circumstances this operation will result in a call to
//! `upstream_resource()->deallocate()`.
//!
//! <b>Throws</b>: Nothing.
virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
//! <b>Returns</b>:
//! `this == dynamic_cast<const unsynchronized_pool_resource*>(&other)`.
virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
//Non-standard observers
public:
//! <b>Returns</b>: The number of pools that will be used in the pool resource.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_count() const;
//! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`.
//! Returns `pool_count()` if `bytes` is bigger
//! than `options().largest_required_pool_block` (no pool will be used to serve this).
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_index(std::size_t bytes) const;
//! <b>Requires</b>: `pool_idx < pool_index()`
//!
//! <b>Returns</b>: The number blocks that will be allocated in the next chunk
//! from the pool specified by `pool_idx`.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
//! <b>Requires</b>: `pool_idx < pool_index()`
//!
//! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_block(std::size_t pool_idx) const;
//! <b>Requires</b>: `pool_idx < pool_index()`
//!
//! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached
//! and will be served without calling the upstream_allocator.
//!
//! <b>Note</b>: Non-standard extension.
std::size_t pool_cached_blocks(std::size_t pool_idx) const;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP

View File

@@ -0,0 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_PMR_VECTOR_HPP
#define BOOST_CONTAINER_PMR_VECTOR_HPP
#if defined (_MSC_VER)
# pragma once
#endif
#include <boost/container/vector.hpp>
#include <boost/container/pmr/polymorphic_allocator.hpp>
namespace boost {
namespace container {
namespace pmr {
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
using vector = boost::container::vector<T, polymorphic_allocator<T>>;
#endif
template<class T>
struct vector_of
{
typedef boost::container::vector
< T, polymorphic_allocator<T> > type;
};
} //namespace pmr {
} //namespace container {
} //namespace boost {
#endif //BOOST_CONTAINER_PMR_VECTOR_HPP

View File

@@ -18,7 +18,7 @@
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
#if defined (_MSC_VER)
# pragma once
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
@@ -26,8 +26,8 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/scoped_allocator_fwd.hpp>
#include <boost/container/detail/dispatch_uses_allocator.hpp>
#include <boost/container/detail/addressof.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -42,143 +42,6 @@
namespace boost { namespace container {
//! <b>Remark</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, indicates that T may be constructed
//! with an allocator as its last constructor argument. Ideally, all constructors of T (including the
//! copy and move constructors) should have a variant that accepts a final argument of
//! allocator_type.
//!
//! <b>Requires</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, T must have a nested type,
//! allocator_type and at least one constructor for which allocator_type is the last
//! parameter. If not all constructors of T can be called with a final allocator_type argument,
//! and if T is used in a context where a container must call such a constructor, then the program is
//! ill-formed.
//!
//! <code>
//! template <class T, class Allocator = allocator<T> >
//! class Z {
//! public:
//! typedef Allocator allocator_type;
//!
//! // Default constructor with optional allocator suffix
//! Z(const allocator_type& a = allocator_type());
//!
//! // Copy constructor and allocator-extended copy constructor
//! Z(const Z& zz);
//! Z(const Z& zz, const allocator_type& a);
//! };
//!
//! // Specialize trait for class template Z
//! template <class T, class Allocator = allocator<T> >
//! struct constructible_with_allocator_suffix<Z<T,Allocator> >
//! { static const bool value = true; };
//! </code>
//!
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped A Model (Rev 2)"
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
//! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
//! Applications aiming portability with several compilers should always define this trait.
//!
//! In conforming C++11 compilers or compilers supporting SFINAE expressions
//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
//! to detect if a type should be constructed with suffix or prefix allocator arguments.
template <class T>
struct constructible_with_allocator_suffix
{ static const bool value = false; };
//! <b>Remark</b>: if a specialization constructible_with_allocator_prefix<X>::value is true, indicates that T may be constructed
//! with allocator_arg and T::allocator_type as its first two constructor arguments.
//! Ideally, all constructors of T (including the copy and move constructors) should have a variant
//! that accepts these two initial arguments.
//!
//! <b>Requires</b>: specialization constructible_with_allocator_prefix<X>::value is true, T must have a nested type,
//! allocator_type and at least one constructor for which allocator_arg_t is the first
//! parameter and allocator_type is the second parameter. If not all constructors of T can be
//! called with these initial arguments, and if T is used in a context where a container must call such
//! a constructor, then the program is ill-formed.
//!
//! <code>
//! template <class T, class Allocator = allocator<T> >
//! class Y {
//! public:
//! typedef Allocator allocator_type;
//!
//! // Default constructor with and allocator-extended default constructor
//! Y();
//! Y(allocator_arg_t, const allocator_type& a);
//!
//! // Copy constructor and allocator-extended copy constructor
//! Y(const Y& yy);
//! Y(allocator_arg_t, const allocator_type& a, const Y& yy);
//!
//! // Variadic constructor and allocator-extended variadic constructor
//! template<class ...Args> Y(Args&& args...);
//! template<class ...Args>
//! Y(allocator_arg_t, const allocator_type& a, BOOST_FWD_REF(Args)... args);
//! };
//!
//! // Specialize trait for class template Y
//! template <class T, class Allocator = allocator<T> >
//! struct constructible_with_allocator_prefix<Y<T,Allocator> >
//! { static const bool value = true; };
//!
//! </code>
//!
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
//! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
//! Applications aiming portability with several compilers should always define this trait.
//!
//! In conforming C++11 compilers or compilers supporting SFINAE expressions
//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
//! to detect if a type should be constructed with suffix or prefix allocator arguments.
template <class T>
struct constructible_with_allocator_prefix
{ static const bool value = false; };
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
template<typename T, typename Allocator>
struct uses_allocator_imp
{
// Use SFINAE (Substitution Failure Is Not An Error) to detect the
// presence of an 'allocator_type' nested type convertilble from Allocator.
private:
typedef char yes_type;
struct no_type{ char dummy[2]; };
// Match this function if TypeT::allocator_type exists and is
// implicitly convertible from Allocator
template <class U>
static yes_type test(typename U::allocator_type);
// Match this function if TypeT::allocator_type does not exist or is
// not convertible from Allocator.
template <typename U>
static no_type test(...);
static Allocator alloc; // Declared but not defined
public:
static const bool value = sizeof(test<T>(alloc)) == sizeof(yes_type);
};
} //namespace container_detail {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Remark</b>: Automatically detects if T has a nested allocator_type that is convertible from
//! Allocator. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
//! specialize this type to define uses_allocator<X>::value as true for a T of user-defined type if T does not
//! have a nested allocator_type but is nonetheless constructible using the specified Allocator.
//!
//! <b>Result</b>: uses_allocator<T, Allocator>::value== true if Convertible<Allocator,T::allocator_type>,
//! false otherwise.
template <typename T, typename Allocator>
struct uses_allocator
: container_detail::uses_allocator_imp<T, Allocator>
{};
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
@@ -249,198 +112,17 @@ struct outermost_allocator
{};
template <typename Allocator>
typename container_detail::outermost_allocator_imp<Allocator>::type &
typename outermost_allocator<Allocator>::type &
get_outermost_allocator(Allocator &a)
{ return container_detail::outermost_allocator_imp<Allocator>::get(a); }
{ return outermost_allocator<Allocator>::get(a); }
template <typename Allocator>
const typename container_detail::outermost_allocator_imp<Allocator>::type &
const typename outermost_allocator<Allocator>::type &
get_outermost_allocator(const Allocator &a)
{ return container_detail::outermost_allocator_imp<Allocator>::get(a); }
{ return outermost_allocator<Allocator>::get(a); }
namespace container_detail {
// Check if we can detect is_convertible using advanced SFINAE expressions
#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
//! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
//! Thanks Mathias!
//With variadic templates, we need a single class to implement the trait
template<class T, class ...Args>
struct is_constructible
{
typedef char yes_type;
struct no_type
{ char padding[2]; };
template<std::size_t N>
struct dummy;
template<class X>
static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
template<class X>
static no_type test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
};
template <class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_prefix
: is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
{};
#else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//Without advanced SFINAE expressions, we can't use is_constructible
//so backup to constructible_with_allocator_xxx
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_prefix
: constructible_with_allocator_prefix<T>
{};
template <class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_suffix
: constructible_with_allocator_suffix<T>
{};
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
struct is_constructible_with_allocator_prefix
: constructible_with_allocator_prefix<T>
{};
template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
struct is_constructible_with_allocator_suffix
: constructible_with_allocator_suffix<T>
{};
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
// allocator_arg_t
template < typename OutermostAlloc
, typename InnerAlloc
, typename T
, class ...Args
>
inline void dispatch_allocator_prefix_suffix
( true_type use_alloc_prefix, OutermostAlloc& outermost_alloc
, InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args) ...args)
{
(void)use_alloc_prefix;
allocator_traits<OutermostAlloc>::construct
( outermost_alloc, p, allocator_arg, inner_alloc, ::boost::forward<Args>(args)...);
}
// allocator suffix
template < typename OutermostAlloc
, typename InnerAlloc
, typename T
, class ...Args
>
inline void dispatch_allocator_prefix_suffix
( false_type use_alloc_prefix, OutermostAlloc& outermost_alloc
, InnerAlloc &inner_alloc, T* p, BOOST_FWD_REF(Args)...args)
{
(void)use_alloc_prefix;
allocator_traits<OutermostAlloc>::construct
(outermost_alloc, p, ::boost::forward<Args>(args)..., inner_alloc);
}
template < typename OutermostAlloc
, typename InnerAlloc
, typename T
, class ...Args
>
inline void dispatch_uses_allocator
( true_type uses_allocator, OutermostAlloc& outermost_alloc
, InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args)...args)
{
(void)uses_allocator;
//BOOST_STATIC_ASSERT((is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>::value ||
// is_constructible_with_allocator_suffix<T, InnerAlloc, Args...>::value ));
dispatch_allocator_prefix_suffix
( bool_< is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>::value>()
, outermost_alloc, inner_alloc, p, ::boost::forward<Args>(args)...);
}
template < typename OutermostAlloc
, typename InnerAlloc
, typename T
, class ...Args
>
inline void dispatch_uses_allocator
( false_type uses_allocator, OutermostAlloc & outermost_alloc
, InnerAlloc & inner_alloc
,T* p, BOOST_FWD_REF(Args)...args)
{
(void)uses_allocator; (void)inner_alloc;
allocator_traits<OutermostAlloc>::construct
(outermost_alloc, p, ::boost::forward<Args>(args)...);
}
#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
template < typename OutermostAlloc, typename InnerAlloc, typename T\
BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
inline void dispatch_allocator_prefix_suffix\
(true_type use_alloc_prefix, OutermostAlloc& outermost_alloc,\
InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
(void)use_alloc_prefix,\
allocator_traits<OutermostAlloc>::construct\
(outermost_alloc, p, allocator_arg, inner_alloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
\
template < typename OutermostAlloc, typename InnerAlloc, typename T\
BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline void dispatch_allocator_prefix_suffix\
(false_type use_alloc_prefix, OutermostAlloc& outermost_alloc,\
InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
(void)use_alloc_prefix;\
allocator_traits<OutermostAlloc>::construct\
(outermost_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, inner_alloc);\
}\
\
template < typename OutermostAlloc, typename InnerAlloc, typename T\
BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline void dispatch_uses_allocator\
(true_type uses_allocator, OutermostAlloc& outermost_alloc,\
InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
(void)uses_allocator;\
dispatch_allocator_prefix_suffix\
( bool_< is_constructible_with_allocator_prefix<T, InnerAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::value >()\
, outermost_alloc, inner_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
\
template < typename OutermostAlloc, typename InnerAlloc, typename T\
BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline void dispatch_uses_allocator\
(false_type uses_allocator, OutermostAlloc &outermost_alloc,\
InnerAlloc &inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
(void)uses_allocator; (void)inner_alloc;\
allocator_traits<OutermostAlloc>::construct(outermost_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename OuterAlloc, class ...InnerAllocs>
@@ -923,24 +605,24 @@ class scoped_allocator_adaptor
typedef typename outer_traits_type::void_pointer void_pointer;
typedef typename outer_traits_type::const_void_pointer const_void_pointer;
//! Type: A type with a constant boolean <code>value</code> == true if
//!`allocator_traits<Allocator>::propagate_on_container_copy_assignment::value` is
//!`allocator_traits<Allocator>:: propagate_on_container_copy_assignment::value` is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
//! Type: A type with a constant boolean <code>value</code> == true if
//!`allocator_traits<Allocator>::propagate_on_container_move_assignment::value` is
//!`allocator_traits<Allocator>:: propagate_on_container_move_assignment::value` is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
propagate_on_container_move_assignment propagate_on_container_move_assignment;
//! Type: A type with a constant boolean <code>value</code> == true if
//! `allocator_traits<Allocator>::propagate_on_container_swap::value` is
//! `allocator_traits<Allocator>:: propagate_on_container_swap::value` is
//! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
propagate_on_container_swap propagate_on_container_swap;
//! Type: A type with a constant boolean <code>value</code> == true if
//!`allocator_traits<Allocator>::is_always_equal::value` is
//!`allocator_traits<Allocator>:: is_always_equal::value` is
//! true for all <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
typedef typename base_type::
is_always_equal is_always_equal;
@@ -1053,12 +735,12 @@ class scoped_allocator_adaptor
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Returns</b>:
//! <code>allocator_traits<OuterAlloc>::max_size(outer_allocator())</code>.
//! <code>allocator_traits<OuterAlloc>:: max_size(outer_allocator())</code>.
size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
{ return outer_traits_type::max_size(this->outer_allocator()); }
//! <b>Effects</b>:
//! calls <code>OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)</code>.
//! calls <code>OUTERMOST_ALLOC_TRAITS(*this):: destroy(OUTERMOST(*this), p)</code>.
template <class T>
void destroy(T* p) BOOST_NOEXCEPT_OR_NOTHROW
{
@@ -1099,12 +781,12 @@ class scoped_allocator_adaptor
//! <b>Effects</b>:
//! 1) If <code>uses_allocator<T, inner_allocator_type>::value</code> is false calls
//! <code>OUTERMOST_ALLOC_TRAITS(*this)::construct
//! (OUTERMOST(*this), p, std::forward<Args>(args)...)</code>.
//! <code>OUTERMOST_ALLOC_TRAITS(*this)::
//! construct(OUTERMOST(*this), p, std::forward<Args>(args)...)</code>.
//!
//! 2) Otherwise, if <code>uses_allocator<T, inner_allocator_type>::value</code> is true and
//! <code>is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value</code> is true, calls
//! <code>OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg,
//! <code>is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>:: value</code> is true, calls
//! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p, allocator_arg,
//! inner_allocator(), std::forward<Args>(args)...)</code>.
//!
//! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't
@@ -1112,13 +794,13 @@ class scoped_allocator_adaptor
//! constructible_with_allocator_prefix<T>::value. -end note]
//!
//! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
//! <code>is_constructible<T, Args..., inner_allocator_type>::value</code> is true, calls
//! <code>OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p,
//! <code>is_constructible<T, Args..., inner_allocator_type>:: value</code> is true, calls
//! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p,
//! std::forward<Args>(args)..., inner_allocator())</code>.
//!
//! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't be
//! implemented so that condition will be replaced by
//! <code>constructible_with_allocator_suffix<T>::value</code>. -end note]
//! <code>constructible_with_allocator_suffix<T>:: value</code>. -end note]
//!
//! 4) Otherwise, the program is ill-formed.
//!
@@ -1126,18 +808,11 @@ class scoped_allocator_adaptor
//! to true but the specific constructor does not take an allocator. This definition prevents a silent
//! failure to pass an inner allocator to a contained element. -end note]
template < typename T, class ...Args>
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
void
#else
typename container_detail::enable_if<container_detail::is_not_pair<T> >::type
#endif
construct(T* p, BOOST_FWD_REF(Args)...args)
void construct(T* p, BOOST_FWD_REF(Args)...args)
{
container_detail::dispatch_uses_allocator
( container_detail::bool_<uses_allocator<T, inner_allocator_type>::value>()
, get_outermost_allocator(this->outer_allocator())
, this->inner_allocator()
, p, ::boost::forward<Args>(args)...);
( (get_outermost_allocator)(this->outer_allocator())
, this->inner_allocator(), p, ::boost::forward<Args>(args)...);
}
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1146,12 +821,10 @@ class scoped_allocator_adaptor
//overload selection problems when the first parameter is a pair.
#define BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \
template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
typename container_detail::enable_if< container_detail::is_not_pair<T> >::type\
construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
void construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
{\
container_detail::dispatch_uses_allocator\
( container_detail::bool_<uses_allocator<T, inner_allocator_type>::value>()\
, get_outermost_allocator(this->outer_allocator())\
( (get_outermost_allocator)(this->outer_allocator())\
, this->inner_allocator(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
}\
//
@@ -1160,81 +833,7 @@ class scoped_allocator_adaptor
#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class T1, class T2>
void construct(std::pair<T1,T2>* p)
{ this->construct_pair(p); }
template <class T1, class T2>
void construct(container_detail::pair<T1,T2>* p)
{ this->construct_pair(p); }
template <class T1, class T2, class U, class V>
void construct(std::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{ this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
template <class T1, class T2, class U, class V>
void construct(container_detail::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{ this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
template <class T1, class T2, class U, class V>
void construct(std::pair<T1, T2>* p, const std::pair<U, V>& x)
{ this->construct_pair(p, x); }
template <class T1, class T2, class U, class V>
void construct( container_detail::pair<T1, T2>* p
, const container_detail::pair<U, V>& x)
{ this->construct_pair(p, x); }
template <class T1, class T2, class U, class V>
void construct( std::pair<T1, T2>* p
, BOOST_RV_REF_BEG std::pair<U, V> BOOST_RV_REF_END x)
{ this->construct_pair(p, ::boost::move(x)); }
template <class T1, class T2, class U, class V>
void construct( container_detail::pair<T1, T2>* p
, BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
{ this->construct_pair(p, ::boost::move(x)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class Pair>
void construct_pair(Pair* p)
{
this->construct(container_detail::addressof(p->first));
BOOST_TRY{
this->construct(container_detail::addressof(p->second));
}
BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class Pair, class U, class V>
void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{
this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
BOOST_TRY{
this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
}
BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
BOOST_RETHROW
}
BOOST_CATCH_END
}
template <class Pair, class Pair2>
void construct_pair(Pair* p, const Pair2& pr)
{ this->construct_pair(p, pr.first, pr.second); }
template <class Pair, class Pair2>
void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
{ this->construct_pair(p, ::boost::move(pr.first), ::boost::move(pr.second)); }
//template <class T1, class T2, class... Args1, class... Args2>
//void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
public:
//Internal function
@@ -1246,6 +845,8 @@ class scoped_allocator_adaptor
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
/// @cond
template<bool ZeroInner>
struct scoped_allocator_operator_equal
{
@@ -1278,6 +879,7 @@ struct scoped_allocator_operator_equal<true>
{ return true; }
};
/// @endcond
template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a

View File

@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
// (C) Copyright Ion Gaztanaga 2015-2015. 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)
//
@@ -13,7 +13,6 @@
//! \file
//! This header file forward declares boost::container::scoped_allocator_adaptor
//! and defines the following types:
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
@@ -26,6 +25,7 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/std_fwd.hpp>
#include <boost/container/uses_allocator_fwd.hpp>
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/move/detail/fwd_macros.hpp>
@@ -59,38 +59,11 @@ namespace boost { namespace container {
#endif
template <int Dummy = 0>
struct std_allocator_arg_holder
{
static ::std::allocator_arg_t *dummy;
};
template <int Dummy>
::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy;
#else //BOOST_CONTAINER_DOXYGEN_INVOKED
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The allocator_arg_t struct is an empty structure type used as a unique type to
//! disambiguate constructor and function overloading. Specifically, several types
//! have constructors with allocator_arg_t as the first argument, immediately followed
//! by an argument of a type that satisfies Allocator requirements
typedef const std::allocator_arg_t & allocator_arg_t;
//! A instance of type allocator_arg_t
//!
static allocator_arg_t allocator_arg = BOOST_CONTAINER_DOC1ST(unspecified, *std_allocator_arg_holder<>::dummy);
template <class T>
struct constructible_with_allocator_suffix;
template <class T>
struct constructible_with_allocator_prefix;
template <typename T, typename Allocator>
struct uses_allocator;
}} // namespace boost { namespace container {
#include <boost/container/detail/config_end.hpp>

View File

@@ -0,0 +1,169 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_USES_ALLOCATOR_HPP
#define BOOST_CONTAINER_USES_ALLOCATOR_HPP
#include <boost/container/uses_allocator_fwd.hpp>
#include <boost/container/detail/type_traits.hpp>
namespace boost {
namespace container {
//! <b>Remark</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, indicates that T may be constructed
//! with an allocator as its last constructor argument. Ideally, all constructors of T (including the
//! copy and move constructors) should have a variant that accepts a final argument of
//! allocator_type.
//!
//! <b>Requires</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, T must have a nested type,
//! allocator_type and at least one constructor for which allocator_type is the last
//! parameter. If not all constructors of T can be called with a final allocator_type argument,
//! and if T is used in a context where a container must call such a constructor, then the program is
//! ill-formed.
//!
//! <code>
//! template <class T, class Allocator = allocator<T> >
//! class Z {
//! public:
//! typedef Allocator allocator_type;
//!
//! // Default constructor with optional allocator suffix
//! Z(const allocator_type& a = allocator_type());
//!
//! // Copy constructor and allocator-extended copy constructor
//! Z(const Z& zz);
//! Z(const Z& zz, const allocator_type& a);
//! };
//!
//! // Specialize trait for class template Z
//! template <class T, class Allocator = allocator<T> >
//! struct constructible_with_allocator_suffix<Z<T,Allocator> >
//! { static const bool value = true; };
//! </code>
//!
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped A Model (Rev 2)"
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
//! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
//! Applications aiming portability with several compilers should always define this trait.
//!
//! In conforming C++11 compilers or compilers supporting SFINAE expressions
//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
//! to detect if a type should be constructed with suffix or prefix allocator arguments.
template <class T>
struct constructible_with_allocator_suffix
{ static const bool value = false; };
//! <b>Remark</b>: if a specialization constructible_with_allocator_prefix<X>::value is true, indicates that T may be constructed
//! with allocator_arg and T::allocator_type as its first two constructor arguments.
//! Ideally, all constructors of T (including the copy and move constructors) should have a variant
//! that accepts these two initial arguments.
//!
//! <b>Requires</b>: specialization constructible_with_allocator_prefix<X>::value is true, T must have a nested type,
//! allocator_type and at least one constructor for which allocator_arg_t is the first
//! parameter and allocator_type is the second parameter. If not all constructors of T can be
//! called with these initial arguments, and if T is used in a context where a container must call such
//! a constructor, then the program is ill-formed.
//!
//! <code>
//! template <class T, class Allocator = allocator<T> >
//! class Y {
//! public:
//! typedef Allocator allocator_type;
//!
//! // Default constructor with and allocator-extended default constructor
//! Y();
//! Y(allocator_arg_t, const allocator_type& a);
//!
//! // Copy constructor and allocator-extended copy constructor
//! Y(const Y& yy);
//! Y(allocator_arg_t, const allocator_type& a, const Y& yy);
//!
//! // Variadic constructor and allocator-extended variadic constructor
//! template<class ...Args> Y(Args&& args...);
//! template<class ...Args>
//! Y(allocator_arg_t, const allocator_type& a, BOOST_FWD_REF(Args)... args);
//! };
//!
//! // Specialize trait for class template Y
//! template <class T, class Allocator = allocator<T> >
//! struct constructible_with_allocator_prefix<Y<T,Allocator> >
//! { static const bool value = true; };
//!
//! </code>
//!
//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
//! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
//! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
//! Applications aiming portability with several compilers should always define this trait.
//!
//! In conforming C++11 compilers or compilers supporting SFINAE expressions
//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
//! to detect if a type should be constructed with suffix or prefix allocator arguments.
template <class T>
struct constructible_with_allocator_prefix
{ static const bool value = false; };
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
template<typename T, typename Allocator>
struct uses_allocator_imp
{
// Use SFINAE (Substitution Failure Is Not An Error) to detect the
// presence of an 'allocator_type' nested type convertilble from Allocator.
private:
typedef char yes_type;
struct no_type{ char dummy[2]; };
// Match this function if T::allocator_type exists and is
// implicitly convertible from Allocator
template <class U>
static yes_type test(typename U::allocator_type);
// Match this function if T::allocator_type exists and it's type is `erased_type`.
template <class U, class V>
static typename container_detail::enable_if
< container_detail::is_same<typename U::allocator_type, erased_type>
, yes_type
>::type test(const V&);
// Match this function if TypeT::allocator_type does not exist or is
// not convertible from Allocator.
template <typename U>
static no_type test(...);
static Allocator alloc; // Declared but not defined
public:
static const bool value = sizeof(test<T>(alloc)) == sizeof(yes_type);
};
} //namespace container_detail {
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Remark</b>: Automatically detects whether T has a nested allocator_type that is convertible from
//! Allocator. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
//! specialize this type to define uses_allocator<X>::value as true for a T of user-defined type if T does not
//! have a nested allocator_type but is nonetheless constructible using the specified Allocator where either:
//! the first argument of a constructor has type allocator_arg_t and the second argument has type Alloc or
//! the last argument of a constructor has type Alloc.
//!
//! <b>Result</b>: uses_allocator<T, Allocator>::value== true if a type T::allocator_type
//! exists and either is_convertible<Alloc, T::allocator_type>::value != false or T::allocator_type
//! is an alias `erased_type`. False otherwise.
template <typename T, typename Allocator>
struct uses_allocator
: container_detail::uses_allocator_imp<T, Allocator>
{};
}} //namespace boost::container
#endif //BOOST_CONTAINER_USES_ALLOCATOR_HPP

View File

@@ -0,0 +1,73 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2015-2015. 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.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_USES_ALLOCATOR_FWD_HPP
#define BOOST_CONTAINER_USES_ALLOCATOR_FWD_HPP
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/std_fwd.hpp>
//! \file
//! This header forward declares boost::container::constructible_with_allocator_prefix,
//! boost::container::constructible_with_allocator_suffix and
//! boost::container::uses_allocator. Also defines the following types:
namespace boost {
namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <int Dummy = 0>
struct std_allocator_arg_holder
{
static ::std::allocator_arg_t *dummy;
};
template <int Dummy>
::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy;
typedef const std::allocator_arg_t & allocator_arg_t;
#else
//! The allocator_arg_t struct is an empty structure type used as a unique type to
//! disambiguate constructor and function overloading. Specifically, several types
//! have constructors with allocator_arg_t as the first argument, immediately followed
//! by an argument of a type that satisfies Allocator requirements
typedef unspecified allocator_arg_t;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The `erased_type` struct is an empty struct that serves as a placeholder for a type
//! T in situations where the actual type T is determined at runtime. For example,
//! the nested type, `allocator_type`, is an alias for `erased_type` in classes that
//! use type-erased allocators.
struct erased_type {};
//! A instance of type
//! allocator_arg_t
static allocator_arg_t allocator_arg = BOOST_CONTAINER_DOC1ST(unspecified, *std_allocator_arg_holder<>::dummy);
// @cond
template <class T>
struct constructible_with_allocator_suffix;
template <class T>
struct constructible_with_allocator_prefix;
template <typename T, typename Allocator>
struct uses_allocator;
// @endcond
}} // namespace boost { namespace container {
#endif //BOOST_CONTAINER_USES_ALLOCATOR_HPP