|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r66215 - sandbox/function/boost/function
From: dsaritz_at_[hidden]
Date: 2010-10-27 12:02:56
Author: psiha
Date: 2010-10-27 12:02:55 EDT (Wed, 27 Oct 2010)
New Revision: 66215
URL: http://svn.boost.org/trac/boost/changeset/66215
Log:
Added allocator support.
Text files modified:
sandbox/function/boost/function/function_base.hpp | 406 +++++++++++++++++++--------------------
sandbox/function/boost/function/function_template.hpp | 196 +++++++++----------
2 files changed, 294 insertions(+), 308 deletions(-)
Modified: sandbox/function/boost/function/function_base.hpp
==============================================================================
--- sandbox/function/boost/function/function_base.hpp (original)
+++ sandbox/function/boost/function/function_base.hpp 2010-10-27 12:02:55 EDT (Wed, 27 Oct 2010)
@@ -141,6 +141,46 @@
namespace detail {
namespace function {
+ template <typename T>
+ class fallocator
+ {
+ public:
+ typedef T value_type;
+
+ typedef value_type * pointer ;
+ typedef value_type & reference ;
+ typedef value_type const * const_pointer ;
+ typedef value_type const & const_reference;
+
+ typedef std::size_t size_type ;
+ typedef std::ptrdiff_t difference_type;
+
+ template <class Other>
+ struct rebind { typedef fallocator<Other> other; };
+
+ fallocator() {}
+
+ template <class Other>
+ fallocator( fallocator<Other> const & ) {}
+
+ static pointer address( reference value ) { return addressof( value ); }
+ static const_pointer address( const_reference value ) { return addressof( value ); }
+
+ template <class Other>
+ fallocator<Other> & operator=( fallocator<Other> const & ) { return *this; }
+
+ pointer allocate ( size_type const count, void const * /*p_hint*/ ) { return allocate( count ); }
+ pointer allocate ( size_type const count ) { return ::operator new( count * sizeof( T ) ); }
+ void deallocate( pointer const ptr , size_type const /*count*/ ) { ::operator delete( ptr ); }
+
+ void construct( pointer const ptr, T const & source ) { new ( ptr ) T( source ); }
+ void destroy ( pointer const ptr ) { ptr->~T(); }
+
+ static size_type max_size() { return std::numeric_limits<size_type>::max() / sizeof( T ); }
+ };
+
+ typedef fallocator<void *> dummy_allocator;
+
struct thiscall_optimization_available_helper
{
static void free_function () {}
@@ -359,23 +399,16 @@
typedef or_ref_tag type;
};
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template <typename F,typename A>
- struct functor_wrapper: public F, public A
+
+ template <typename F, typename A>
+ struct functor_and_allocator : public F, public A
{
- functor_wrapper( F f, A a ):
- F(f),
- A(a)
- {
- }
-
- functor_wrapper(const functor_wrapper& f) :
- F(static_cast<const F&>(f)),
- A(static_cast<const A&>(f))
- {
- }
+ functor_and_allocator( F const & f, A a ) : F( f ), A( a ) {}
+
+ F & functor () { return *this; }
+ A & allocator() { return *this; }
};
-*/
+
typedef boost::aligned_storage<sizeof( void * ) * 2, sizeof( void * ) * 2>::type trivial_heap_storage_atom;
@@ -492,11 +525,11 @@
struct manager_ptr
{
public:
- static void * * functor_ptr( function_buffer & buffer ) { BF_ASSUME( buffer.obj_ptr ); return &buffer.obj_ptr; }
- static void const * const * functor_ptr( function_buffer const & buffer ) { return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
+ static void * * functor_ptr( function_buffer & buffer ) { return &buffer.obj_ptr; }
+ static void const * const * functor_ptr( function_buffer const & buffer ) { BF_ASSUME( buffer.obj_ptr ); return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
- template <typename Functor>
- static void assign( Functor const & functor, function_buffer & out_buffer )
+ template <typename Functor, typename Allocator>
+ static void assign( Functor const & functor, function_buffer & out_buffer, Allocator )
{
BOOST_STATIC_ASSERT( functor_traits<Functor>::allowsPtrObjectOptimization );
new ( functor_ptr( out_buffer ) ) Functor( functor );
@@ -504,7 +537,7 @@
static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
{
- return assign( *functor_ptr( in_buffer ), out_buffer );
+ return assign( *functor_ptr( in_buffer ), out_buffer, dummy_allocator() );
}
static void BF_FASTCALL_WORKAROUND move( function_buffer & in_buffer, function_buffer & out_buffer )
@@ -525,8 +558,8 @@
public:
static void * functor_ptr( function_buffer & buffer ) { return &buffer; }
- template <typename Functor>
- static void assign( Functor const & functor, function_buffer & out_buffer )
+ template <typename Functor, typename Allocator>
+ static void assign( Functor const & functor, function_buffer & out_buffer, Allocator )
{
BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT
(
@@ -538,7 +571,7 @@
static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
{
- return assign( in_buffer, out_buffer );
+ return assign( in_buffer, out_buffer, dummy_allocator() );
}
static void BF_FASTCALL_WORKAROUND move( function_buffer & in_buffer, function_buffer & out_buffer )
@@ -553,38 +586,43 @@
}
};
- /// Manager for trivial objects that cannot live/fit in a function_buffer.
+ /// Manager for trivial objects that cannot live/fit in a function_buffer
+ /// and are used with 'empty' allocators.
+ template <typename Allocator>
struct manager_trivial_heap
{
public:
- typedef trivial_heap_storage_atom storage_atom;
+ typedef typename Allocator:: BOOST_NESTED_TEMPLATE rebind<unsigned char>::other trivial_allocator;
public:
- static void * & functor_ptr( function_buffer & buffer ) { BF_ASSUME( buffer.trivial_heap_obj.ptr ); return buffer.trivial_heap_obj.ptr; }
- static void * functor_ptr( function_buffer const & buffer ) { return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
+ static void * & functor_ptr( function_buffer & buffer ) { return buffer.trivial_heap_obj.ptr; }
+ static void * functor_ptr( function_buffer const & buffer ) { BF_ASSUME( buffer.trivial_heap_obj.ptr ); return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
template <typename Functor>
- static void assign( Functor const & functor, function_buffer & out_buffer )
+ static void assign( Functor const & functor, function_buffer & out_buffer, Allocator const a )
{
+ BOOST_ASSERT( a == trivial_allocator() );
+ ignore_unused_variable_warning( a );
+
BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT
(
functor_traits<Functor>::allowsPODOptimization &&
functor_traits<Functor>::hasDefaultAlignement
);
+
function_buffer in_buffer;
in_buffer.trivial_heap_obj.ptr = const_cast<Functor *>( &functor );
- in_buffer.trivial_heap_obj.size = ( sizeof( Functor ) / sizeof( storage_atom ) )
- +
- ( ( sizeof( Functor ) % sizeof( storage_atom ) ) ? 1 : 0 );
+ in_buffer.trivial_heap_obj.size = sizeof( Functor );
return clone( in_buffer, out_buffer );
}
static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
{
- std::size_t const storage_array_size( in_buffer.trivial_heap_obj.size );
- out_buffer.trivial_heap_obj.ptr = new storage_atom[ storage_array_size ];
- out_buffer.trivial_heap_obj.size = storage_array_size;
- std::memcpy( functor_ptr( out_buffer ), functor_ptr( in_buffer ), storage_array_size * sizeof( storage_atom ) );
+ trivial_allocator a;
+ std::size_t const storage_size( in_buffer.trivial_heap_obj.size );
+ out_buffer.trivial_heap_obj.ptr = a.allocate( storage_size );
+ out_buffer.trivial_heap_obj.size = storage_size;
+ std::memcpy( functor_ptr( out_buffer ), functor_ptr( in_buffer ), storage_size );
}
static void BF_FASTCALL_WORKAROUND move( function_buffer & in_buffer, function_buffer & out_buffer )
@@ -595,7 +633,8 @@
static void BF_FASTCALL_WORKAROUND destroy( function_buffer & buffer )
{
- delete [] static_cast<storage_atom *>( functor_ptr( buffer ) );
+ trivial_allocator a;
+ a.deallocate( functor_ptr( buffer ) );
//functor_ptr( buffer ) = 0;
}
};
@@ -636,55 +675,103 @@
/// Fully generic manager for non-trivial objects that cannot live/fit in
/// a function_buffer.
- template <typename FunctorParam>
+ template <typename FunctorParam, typename AllocatorParam>
struct manager_generic
{
public:
- typedef FunctorParam Functor;
+ typedef FunctorParam Functor ;
+ typedef AllocatorParam OriginalAllocator;
- static Functor * & functor_ptr( function_buffer & buffer )
+ typedef functor_and_allocator<Functor, OriginalAllocator> functor_and_allocator_t;
+ typedef typename OriginalAllocator:: BOOST_NESTED_TEMPLATE rebind<functor_and_allocator>::other wrapper_allocator_t ;
+ typedef typename OriginalAllocator:: BOOST_NESTED_TEMPLATE rebind<OriginalAllocator >::other allocator_allocator_t ;
+
+ static functor_and_allocator_t * & functor_ptr( function_buffer & buffer )
{
- return *static_cast<Functor * *>
+ return *static_cast<functor_and_allocator_t * *>
(
static_cast<void *>
(
- &manager_trivial_heap::functor_ptr( buffer )
+ &manager_trivial_heap<OriginalAllocator>::functor_ptr( buffer )
)
);
}
- static Functor * functor_ptr( function_buffer const & buffer )
+ static functor_and_allocator_t * functor_ptr( function_buffer const & buffer )
{
return functor_ptr( const_cast<function_buffer &>( buffer ) );
}
- static void assign( Functor const & functor, function_buffer & out_buffer )
+ static void assign( Functor const & functor, function_buffer & out_buffer, OriginalAllocator source_allocator )
{
- functor_ptr( out_buffer ) = new Functor( functor );
+ typedef ::boost::type_traits::ice_and
+ <
+ ::boost::has_nothrow_copy<Functor >::value,
+ ::boost::has_nothrow_copy<OriginalAllocator>::value
+ > does_not_need_guard_t;
+
+ typedef typename mpl::if_
+ <
+ does_not_need_guard_t,
+ functor_and_allocator_t *,
+ std::auto_ptr<functor_and_allocator_t>
+ >::type guard_t;
+ assign_aux<guard_t>( functor, out_buffer, source_allocator );
}
- static void clone( const function_buffer& in_buffer, function_buffer& out_buffer )
+ static void clone( function_buffer const & in_buffer, function_buffer & out_buffer )
{
- Functor const & in_functor( *functor_ptr( in_buffer ) );
- return assign( in_functor, out_buffer );
+ functor_and_allocator_t const & in_functor_and_allocator( *functor_ptr( in_buffer ) );
+ return assign( in_functor_and_allocator.functor(), out_buffer, in_functor_and_allocator.allocator() );
}
- static void move( function_buffer & in_buffer, function_buffer& out_buffer )
+ static void move( function_buffer & in_buffer, function_buffer & out_buffer )
{
- manager_trivial_heap::move( in_buffer, out_buffer );
+ manager_trivial_heap<OriginalAllocator>::move( in_buffer, out_buffer );
}
- static void destroy( function_buffer& buffer )
+ static void destroy( function_buffer & buffer )
{
- checked_delete( functor_ptr( buffer ) );
+ functor_and_allocator_t & in_functor_and_allocator( *functor_ptr( buffer ) );
+
+ OriginalAllocator original_allocator ( in_functor_and_allocator.allocator() );
+ allocator_allocator_t allocator_allocator( in_functor_and_allocator.allocator() );
+ wrapper_allocator_t full_allocator ( in_functor_and_allocator.allocator() );
+
+ original_allocator .destroy( &in_functor_and_allocator.functor () );
+ allocator_allocator.destroy( &in_functor_and_allocator.allocator() );
+
+ full_allocator.deallocate( &in_functor_and_allocator );
//functor_ptr( buffer ) = 0;
}
+
+ private:
+ template <typename Guard>
+ static functor_and_allocator_t * release( Guard & guard ) { return guard.release(); }
+ static functor_and_allocator_t * release( functor_and_allocator_t * const pointer ) { return pointer ; }
+
+ template <typename Guard>
+ static void assign_aux( Functor const & functor, function_buffer & out_buffer, OriginalAllocator source_allocator )
+ {
+ wrapper_allocator_t full_allocator ( source_allocator );
+ allocator_allocator_t allocator_allocator( source_allocator );
+
+ Guard p_placeholder ( full_allocator.allocate( 1 ) );
+ Functor * const p_functor_placeholder ( p_placeholder );
+ OriginalAllocator * const p_allocator_placeholder( p_placeholder );
+
+ source_allocator .construct( p_functor_placeholder , functor );
+ allocator_allocator.construct( p_allocator_placeholder, source_allocator );
+
+ functor_ptr( out_buffer ) = release( p_placeholder );
+ }
};
/// Helper metafunction for retrieving an appropriate functor manager.
template
<
typename Functor,
+ typename Allocator,
bool POD,
bool smallObj,
bool ptrSmall,
@@ -692,41 +779,42 @@
>
struct functor_manager
{
- typedef manager_generic<Functor> type;
+ typedef manager_generic<Functor, Allocator> type;
};
- template<typename Functor>
- struct functor_manager<Functor, true, false, false, true>
+ template <typename Functor, typename Allocator>
+ struct functor_manager<Functor, Allocator, true, false, false, true>
{
- typedef manager_trivial_heap type;
+ typedef manager_trivial_heap<Allocator> type;
};
- template<typename Functor, bool defaultAligned>
- struct functor_manager<Functor, true, true, false, defaultAligned>
+ template <typename Functor, typename Allocator, bool defaultAligned>
+ struct functor_manager<Functor, Allocator, true, true, false, defaultAligned>
{
typedef manager_trivial_small type;
};
- template<typename Functor, bool smallObj, bool defaultAligned>
- struct functor_manager<Functor, true, smallObj, true, defaultAligned>
+ template <typename Functor, typename Allocator, bool smallObj, bool defaultAligned>
+ struct functor_manager<Functor, Allocator, true, smallObj, true, defaultAligned>
{
typedef manager_ptr type;
};
- template<typename Functor, bool ptrSmall, bool defaultAligned>
- struct functor_manager<Functor, false, true, ptrSmall, defaultAligned>
+ template <typename Functor, typename Allocator, bool ptrSmall, bool defaultAligned>
+ struct functor_manager<Functor, Allocator, false, true, ptrSmall, defaultAligned>
{
typedef manager_small<Functor> type;
};
/// Metafunction for retrieving an appropriate functor manager with
/// minimal type information.
- template<typename StoredFunctor>
+ template<typename StoredFunctor, typename Allocator>
struct get_functor_manager
{
typedef typename functor_manager
<
StoredFunctor,
+ Allocator,
functor_traits<StoredFunctor>::allowsPODOptimization,
functor_traits<StoredFunctor>::allowsSmallObjectOptimization,
functor_traits<StoredFunctor>::allowsPtrObjectOptimization,
@@ -735,122 +823,17 @@
};
/// Metafunction for retrieving an appropriate fully typed functor manager.
- template<typename ActualFunctor, typename StoredFunctor>
+ template<typename ActualFunctor, typename StoredFunctor, typename Allocator>
struct get_typed_functor_manager
{
typedef typed_manager
<
- typename get_functor_manager<StoredFunctor>::type,
+ typename get_functor_manager<StoredFunctor, Allocator>::type,
ActualFunctor,
StoredFunctor
> type;
};
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template<typename Functor, typename Allocator>
- struct functor_manager_a
- {
- private:
- typedef Functor functor_type;
-
- // Function pointers
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_ptr_tag)
- {
- manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
- }
-
- // Function objects that fit in the small-object buffer.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, mpl::true_)
- {
- manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
- }
-
- // Function objects that require heap allocation
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, mpl::false_)
- {
- typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
- typedef typename Allocator::template rebind<functor_wrapper_type>::other
- wrapper_allocator_type;
- typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
-
- if (op == clone_functor_tag) {
- // Clone the functor
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
- const functor_wrapper_type* f =
- (const functor_wrapper_type*)(in_buffer.obj_ptr);
- wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
- wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
- wrapper_allocator.construct(copy, *f);
-
- // Get back to the original pointer type
- functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
- out_buffer.obj_ptr = new_f;
- } else if (op == move_functor_tag) {
- out_buffer.obj_ptr = in_buffer.obj_ptr;
- in_buffer.obj_ptr = 0;
- } else if (op == destroy_functor_tag) {
- // Cast from the void pointer to the functor_wrapper_type
- functor_wrapper_type* victim =
- static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
- wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
- wrapper_allocator.destroy(victim);
- wrapper_allocator.deallocate(victim,1);
- out_buffer.obj_ptr = 0;
- } else if (op == check_functor_type_tag) {
- const detail::sp_typeinfo& check_type
- = *out_buffer.type.type;
- if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
- out_buffer.obj_ptr = in_buffer.obj_ptr;
- else
- out_buffer.obj_ptr = 0;
- } else { // op == get_functor_type_tag
- out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
- out_buffer.type.const_qualified = false;
- out_buffer.type.volatile_qualified = false;
- }
- }
-
- // For function objects, we determine whether the function
- // object can use the small-object optimization buffer or
- // whether we need to allocate it on the heap.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_obj_tag)
- {
- manager(in_buffer, out_buffer, op,
- mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
- }
-
- public:
- // Dispatch to an appropriate manager based on whether we have a
- // function pointer or a function object pointer.
- static inline void
- manage(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- typedef typename get_function_tag<functor_type>::type tag_type;
- switch (op) {
- case get_functor_type_tag:
- out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
- out_buffer.type.const_qualified = false;
- out_buffer.type.volatile_qualified = false;
- return;
-
- default:
- manager(in_buffer, out_buffer, op, tag_type());
- return;
- }
- }
- };
-*/
-
// A type that is only used for comparisons against zero
struct useless_clear_type {};
@@ -1061,15 +1044,15 @@
if ( clear )
{
BOOST_ASSERT( pFunction_ );
- typedef functor_traits <EmptyHandler> empty_handler_traits ;
- typedef typename get_functor_manager<EmptyHandler>::type empty_handler_manager;
+ typedef functor_traits <EmptyHandler> empty_handler_traits ;
+ typedef typename get_functor_manager<EmptyHandler, fallocator<EmptyHandler> >::type empty_handler_manager;
// remove completely or replace with a simple is_stateless<>?
BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT
(
empty_handler_traits::allowsPODOptimization &&
empty_handler_traits::allowsSmallObjectOptimization
);
- empty_handler_manager::assign( EmptyHandler(), pFunction_->functor );
+ empty_handler_manager::assign( EmptyHandler(), pFunction_->functor, fallocator<EmptyHandler>() );
pFunction_->pVTable = &empty_handler_vtable_;
}
}
@@ -1166,7 +1149,13 @@
// is not necessary here but a simple
// this->pVTable = &empty_handler_vtable...
EmptyHandler /*const*/ emptyHandler;
- assign<false, EmptyHandler>( emptyHandler, empty_handler_vtable, empty_handler_vtable );
+ assign<false, EmptyHandler>
+ (
+ emptyHandler,
+ empty_handler_vtable,
+ empty_handler_vtable,
+ detail::function::fallocator<EmptyHandler>()
+ );
}
private: // Assignment from another boost function helpers.
@@ -1189,21 +1178,22 @@
protected:
// Assignment from another boost function.
- template<bool direct, typename EmptyHandler, typename FunctionObj>
+ template <bool direct, typename EmptyHandler, typename FunctionObj, typename Allocator>
typename enable_if<is_base_of<function_base, FunctionObj> >::type
assign
(
FunctionObj const & f,
detail::function::vtable const & functor_vtable,
- detail::function::vtable const & empty_handler_vtable
+ detail::function::vtable const & empty_handler_vtable,
+ Allocator
)
{
- assert( &functor_vtable == f.pVTable );
- boost::ignore_unused_variable_warning( functor_vtable );
+ BOOST_ASSERT( &functor_vtable == f.pVTable );
+ ignore_unused_variable_warning( functor_vtable );
if ( direct )
{
- assert( &static_cast<function_base const &>( f ) != this );
- assert( this->pVTable == &empty_handler_vtable );
+ BOOST_ASSERT( &static_cast<function_base const &>( f ) != this );
+ BOOST_ASSERT( this->pVTable == &empty_handler_vtable );
assign_direct( f );
}
else if( &static_cast<function_base const &>( f ) != this )
@@ -1213,46 +1203,49 @@
}
// General actual assignment.
- template<bool direct, typename EmptyHandler, typename FunctionObj>
+ template <bool direct, typename EmptyHandler, typename FunctionObj, typename Allocator>
typename disable_if<is_base_of<function_base, FunctionObj> >::type
assign
(
FunctionObj const & f,
detail::function::vtable const & functor_vtable,
- detail::function::vtable const & empty_handler_vtable
+ detail::function::vtable const & empty_handler_vtable,
+ Allocator
);
- template<typename EmptyHandler, typename FunctionObj>
+ template <typename EmptyHandler, typename FunctionObj, typename Allocator>
BF_NOTHROW
void actual_assign
(
- FunctionObj const & f,
+ FunctionObj const & f,
detail::function::vtable const & functor_vtable,
detail::function::vtable const & /*empty_handler_vtable*/,
+ Allocator const a,
mpl::true_ /*can use direct assign*/
)
{
- typedef typename detail::function::get_functor_manager<FunctionObj>::type functor_manager;
+ typedef typename detail::function::get_functor_manager<FunctionObj, Allocator>::type functor_manager;
this->destroy();
- functor_manager::assign( f, this->functor );
+ functor_manager::assign( f, this->functor, a );
this->pVTable = &functor_vtable;
}
- template<typename EmptyHandler, typename FunctionObj>
+ template<typename EmptyHandler, typename FunctionObj, typename Allocator>
void actual_assign
(
- FunctionObj const & f,
+ FunctionObj const & f,
detail::function::vtable const & functor_vtable,
detail::function::vtable const & empty_handler_vtable,
+ Allocator const a,
mpl::false_ /*must use safe assignment*/
)
{
// This most generic case needs to be reworked [currently uses redundant
// copying (generic one, through function pointers) and does not use all
// the type information it can...]...
- typedef typename detail::function::get_functor_manager<FunctionObj>::type functor_manager;
+ typedef typename detail::function::get_functor_manager<FunctionObj, Allocator>::type functor_manager;
function_base tmp( empty_handler_vtable );
- functor_manager::assign( f, tmp.functor );
+ functor_manager::assign( f, tmp.functor, a );
tmp.pVTable = &functor_vtable;
this->swap<EmptyHandler>( tmp, empty_handler_vtable );
}
@@ -1327,7 +1320,7 @@
template <class EmptyHandler>
void function_base::swap( function_base & other, detail::function::vtable const & empty_handler_vtable )
{
- if (&other == this)
+ if ( &other == this )
return;
function_base tmp( empty_handler_vtable );
@@ -1602,13 +1595,14 @@
} // end namespace detail
//...zzz...here because of has_empty_target()...GCC & Clang are not lazy enough
-template<bool direct, typename EmptyHandler, typename FunctionObj>
+template <bool direct, typename EmptyHandler, typename FunctionObj, typename Allocator>
typename disable_if<is_base_of<function_base, FunctionObj> >::type
function_base::assign
(
- FunctionObj const & f,
+ FunctionObj const & f,
detail::function::vtable const & functor_vtable,
- detail::function::vtable const & empty_handler_vtable
+ detail::function::vtable const & empty_handler_vtable,
+ Allocator const a
)
{
using namespace detail::function;
@@ -1619,8 +1613,8 @@
if ( direct )
{
BOOST_ASSERT( this->pVTable == &empty_handler_vtable );
- typedef typename get_functor_manager<FunctionObj>::type functor_manager;
- functor_manager::assign( f, this->functor );
+ typedef typename get_functor_manager<FunctionObj, Allocator>::type functor_manager;
+ functor_manager::assign( f, this->functor, a );
this->pVTable = &functor_vtable;
return;
}
@@ -1629,22 +1623,24 @@
// This can/should be rewritten because the small-object-optimization
// condition is too strict (requires a trivial destructor which is not
// needed for a no fail assignment).
+ typedef ::boost::type_traits::ice_and
+ <
+ functor_traits<FunctionObj>::allowsSmallObjectOptimization,
+ ::boost::type_traits::ice_or
+ <
+ ::boost::has_nothrow_copy<FunctionObj>::value,
+ ::boost::has_trivial_copy<FunctionObj>::value,
+ ::boost::detail::function::is_msvc_exception_specified_function_pointer<FunctionObj>::value
+ >::value
+ > has_no_fail_assignement_t;
actual_assign<EmptyHandler>
(
f,
functor_vtable,
empty_handler_vtable,
- mpl::bool_
- <
- //has_no_fail_assignement:
- functor_traits<FunctionObj>::allowsSmallObjectOptimization &&
- (
- has_nothrow_copy_constructor<FunctionObj>::value ||
- has_trivial_copy_constructor<FunctionObj>::value ||
- is_msvc_exception_specified_function_pointer<FunctionObj>::value
- )
- >()
+ a,
+ has_no_fail_assignement_t()
);
}
}
Modified: sandbox/function/boost/function/function_template.hpp
==============================================================================
--- sandbox/function/boost/function/function_template.hpp (original)
+++ sandbox/function/boost/function/function_template.hpp 2010-10-27 12:02:55 EDT (Wed, 27 Oct 2010)
@@ -240,35 +240,41 @@
// MSVC chokes if the following two constructors are collapsed into
// one with a default parameter.
- template<typename Functor>
- BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
-#ifndef BOOST_NO_SFINAE
- ,typename enable_if_c<
- (boost::type_traits::ice_not<
- (is_integral<Functor>::value)>::value),
- int>::type = 0
-#endif // BOOST_NO_SFINAE
- ) :
+ template <typename Functor>
+ BOOST_FUNCTION_FUNCTION
+ (
+ Functor BOOST_FUNCTION_TARGET_FIX(const &) f
+ #ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+ #endif // BOOST_NO_SFINAE
+ )
+ :
function_base( empty_handler_vtable() )
{
this->do_assign<true, Functor>( f );
}
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template<typename Functor,typename Allocator>
- BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
-#ifndef BOOST_NO_SFINAE
- ,typename enable_if_c<
- (boost::type_traits::ice_not<
- (is_integral<Functor>::value)>::value),
- int>::type = 0
-#endif // BOOST_NO_SFINAE
- ) :
+ template <typename Functor, typename Allocator>
+ BOOST_FUNCTION_FUNCTION
+ (
+ Functor BOOST_FUNCTION_TARGET_FIX(const &) f,
+ Allocator const a
+ #ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+ #endif // BOOST_NO_SFINAE
+ )
+ :
function_base( empty_handler_vtable() )
{
- this->assign_to_a(f,a);
+ this->do_assign<true, Functor>( f, a );
}
-*/
+
#ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base( empty_handler_vtable() ) { }
@@ -369,13 +375,12 @@
return *this;
}
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template<typename Functor,typename Allocator>
- void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
+ template <typename FunctionObj, typename Allocator>
+ void assign( FunctionObj BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator const a )
{
- this->assign_to_a(f,a);
+ this->do_assign<false, FunctionObj>( f, a );
}
-*/
+
#ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
@@ -403,7 +408,7 @@
bool operator!() const { return this->empty(); }
private:
- static vtable_type const & empty_handler_vtable() { return vtable_for_functor<base_empty_handler>( my_empty_handler() ); }
+ static vtable_type const & empty_handler_vtable() { return vtable_for_functor<detail::function::fallocator<base_empty_handler>, base_empty_handler>( my_empty_handler() ); }
template <class F>
static bool nothrow_test( F & f BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS )
@@ -484,14 +489,14 @@
// for the signature template parameter to be the same (and therefor the vtable is the same, with
// a possible exception being the case of an empty source as empty handler vtables depend on the
// policy as well as the signature).
- template <typename ActualFunctor>
+ template <typename Allocator, typename ActualFunctor>
static vtable_type const & vtable_for_functor( BOOST_FUNCTION_FUNCTION const & functor )
{
BOOST_STATIC_ASSERT(( is_base_of<BOOST_FUNCTION_FUNCTION, ActualFunctor>::value ));
return functor.get_vtable();
}
- template <typename ActualFunctor, typename StoredFunctor>
+ template <typename Allocator, typename ActualFunctor, typename StoredFunctor>
typename disable_if<is_base_of<BOOST_FUNCTION_FUNCTION, StoredFunctor>, vtable_type const &>::type
static vtable_for_functor( StoredFunctor const & /*functor*/ )
{
@@ -500,7 +505,8 @@
// A minimally typed manager is used for the invoker (anti-code-bloat).
typedef typename get_functor_manager
<
- StoredFunctor
+ StoredFunctor,
+ Allocator
>::type invoker_manager_type;
// For the empty handler we use the manager for the base_empty_handler not
@@ -515,7 +521,8 @@
is_same<ActualFunctor, base_empty_handler>,
ActualFunctor,
StoredFunctor
- >::type
+ >::type,
+ Allocator
>::type manager_type;
typedef typename mpl::if_
@@ -538,55 +545,34 @@
return vtable_holder<invoker_type, manager_type>::stored_vtable;
}
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template<typename Functor,typename Allocator>
- static vtable_type const & vtable_for_functor_a()
- {
- using detail::function::vtable_base;
-
- typedef typename detail::function::get_function_tag<Functor>::type tag;
- typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
- typedef typename get_invoker::
- template apply_a<Functor, R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS,
- Allocator>
- handler_type;
-
- typedef typename handler_type::invoker_type invoker_type;
- typedef typename boost::mpl::if_
- <
- boost::is_base_of<base_empty_handler, Functor>,
- detail::function::functor_manager<base_empty_handler>,
- detail::function::functor_manager_a<Functor, Allocator>
- >::type manager_type;
-
- return static_cast<vtable_type const &>( detail::function::vtable_holder<invoker_type, manager_type>::stored_vtable );
- }
-*/
+
// ...direct actually means whether to skip pre-destruction (when not
// assigning but constructing) so it should probably be renamed to
// pre_destroy or the whole thing solved in some smarter way...
- template<bool direct, typename FunctionObj>
- void do_assign( FunctionObj const & f )
+ template<bool direct, typename FunctionObj, typename Allocator>
+ void do_assign( FunctionObj const & f, Allocator const a )
{
typedef typename detail::function::get_function_tag<FunctionObj>::type tag;
- dispatch_assign<direct, FunctionObj>( f, tag() );
+ dispatch_assign<direct, FunctionObj>( f, a, tag() );
}
template<bool direct, typename FunctionObj>
- void dispatch_assign( FunctionObj const & f, detail::function::function_obj_tag ) { do_assign<direct, FunctionObj >( f , f ); }
- template<bool direct, typename FunctionObj>
- void dispatch_assign( FunctionObj const & f, detail::function::function_ptr_tag ) { do_assign<direct, FunctionObj >( f , f ); }
+ void do_assign( FunctionObj const & f ) { do_assign<direct>( f, detail::function::fallocator<FunctionObj>() ); }
+
+ template<bool direct, typename FunctionObj, typename Allocator>
+ void dispatch_assign( FunctionObj const & f, Allocator const a, detail::function::function_obj_tag ) { do_assign<direct, FunctionObj>( f , f , a ); }
+ template<bool direct, typename FunctionObj, typename Allocator>
+ void dispatch_assign( FunctionObj const & f, Allocator const a, detail::function::function_ptr_tag ) { do_assign<direct, FunctionObj>( f , f , a ); }
// DPG TBD: Add explicit support for member function
// objects, so we invoke through mem_fn() but we retain the
// right target_type() values.
- template<bool direct, typename FunctionObj>
- void dispatch_assign( FunctionObj const & f, detail::function::member_ptr_tag ) { do_assign<direct, FunctionObj >( f , mem_fn( f ) ); }
- template<bool direct, typename FunctionObj>
- void dispatch_assign( FunctionObj const & f, detail::function::function_obj_ref_tag ) { do_assign<direct, typename FunctionObj::type>( f.get(), f ); }
+ template<bool direct, typename FunctionObj, typename Allocator>
+ void dispatch_assign( FunctionObj const & f, Allocator const a, detail::function::member_ptr_tag ) { do_assign<direct, FunctionObj>( f , mem_fn( f ), a ); }
+ template<bool direct, typename FunctionObj, typename Allocator>
+ void dispatch_assign( FunctionObj const & f, Allocator const a, detail::function::function_obj_ref_tag ) { do_assign<direct, typename FunctionObj::type>( f.get(), f , a ); }
- template<bool direct, typename ActualFunctor, typename StoredFunctor>
- void do_assign( ActualFunctor const & original_functor, StoredFunctor const & stored_functor )
+ template<bool direct, typename ActualFunctor, typename StoredFunctor, typename ActualFunctorAllocator>
+ void do_assign( ActualFunctor const & original_functor, StoredFunctor const & stored_functor, ActualFunctorAllocator const a )
{
if
(
@@ -611,24 +597,23 @@
(
emptyHandler,
empty_handler_vtable(),
- empty_handler_vtable()
+ empty_handler_vtable(),
+ detail::function::fallocator<base_empty_handler>()
);
emptyHandler. BOOST_NESTED_TEMPLATE handle_empty_invoke<R>();
}
else
+ {
+ typedef typename ActualFunctorAllocator:: BOOST_NESTED_TEMPLATE rebind<StoredFunctor>::other StoredFunctorAllocator;
function_base::assign<direct, base_empty_handler>
(
stored_functor,
- vtable_for_functor<ActualFunctor>( stored_functor ),
- empty_handler_vtable()
+ vtable_for_functor<StoredFunctorAllocator, ActualFunctor>( stored_functor ),
+ empty_handler_vtable(),
+ StoredFunctorAllocator( a )
);
+ }
}
-
-
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template<typename Functor,typename Allocator>
- void assign_to_a(Functor f,Allocator a) { assert( !"Implement" ); }
-*/
};
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, class PolicyList>
@@ -681,32 +666,37 @@
public:
function() {}
- template<typename Functor>
- function(Functor const & f
-#ifndef BOOST_NO_SFINAE
- ,typename enable_if_c<
- (boost::type_traits::ice_not<
- (is_integral<Functor>::value)>::value),
- int>::type = 0
-#endif
- ) :
- base_type(f)
- {
- }
-/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
- template<typename Functor,typename Allocator>
- function(Functor f, Allocator a
-#ifndef BOOST_NO_SFINAE
- ,typename enable_if_c<
- (boost::type_traits::ice_not<
- (is_integral<Functor>::value)>::value),
- int>::type = 0
-#endif
- ) :
- base_type(f,a)
- {
- }
-*/
+ template <typename Functor>
+ function
+ (
+ Functor const & f
+ #ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+ #endif
+ )
+ :
+ base_type( f )
+ {}
+
+ template <typename Functor, typename Allocator>
+ function
+ (
+ Functor const & f,
+ Allocator const a
+ #ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+ #endif
+ )
+ :
+ base_type( f, a )
+ {}
+
#ifndef BOOST_NO_SFINAE
function(clear_type*) : base_type() {}
#endif
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk