Boost logo

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