Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66235 - sandbox/function/boost/function
From: dsaritz_at_[hidden]
Date: 2010-10-28 13:27:01


Author: psiha
Date: 2010-10-28 13:26:56 EDT (Thu, 28 Oct 2010)
New Revision: 66235
URL: http://svn.boost.org/trac/boost/changeset/66235

Log:
Fixed the functor_traits<> metafunction.
Fixed the manager_small<> class.
Fixed the cleaner::conditional_clear() member function.
Fixed another 'non-lazy GCC' compilation error.
Minor stylistic changes.
Text files modified:
   sandbox/function/boost/function/function_base.hpp | 75 ++++++++++++++++++++++-----------------
   sandbox/function/boost/function/function_template.hpp | 12 +++++
   2 files changed, 54 insertions(+), 33 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-28 13:26:56 EDT (Thu, 28 Oct 2010)
@@ -450,9 +450,8 @@
           allowsSmallObjectOptimization =
             is_msvc_exception_specified_function_pointer<Functor>::value ||
             (
- ( sizeof( Functor ) <= sizeof( function_buffer ) ) &&
- ( alignment_of<function_buffer>::value % alignment_of<Functor>::value == 0 ) &&
- allowsPODOptimization
+ ( sizeof( Functor ) <= sizeof( function_buffer ) ) &&
+ ( alignment_of<function_buffer>::value % alignment_of<Functor>::value == 0 )
             ));
 
           BOOST_STATIC_CONSTANT
@@ -460,9 +459,8 @@
           allowsPtrObjectOptimization =
             is_msvc_exception_specified_function_pointer<Functor>::value ||
             (
- ( sizeof( Functor ) <= sizeof( void * ) &&
- ( alignment_of<void *>::value % alignment_of<Functor>::value == 0 ) &&
- allowsPODOptimization)
+ ( sizeof( Functor ) <= sizeof( void * ) ) &&
+ ( alignment_of<void *>::value % alignment_of<Functor>::value == 0 )
             ));
 
           BOOST_STATIC_CONSTANT
@@ -570,7 +568,7 @@
           static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
           {
                       //...zzz...even with BF_ASSUME MSVC still generates branching code...
- //return assign( *functor_ptr( in_buffer ), out_buffer, dummy_allocator() );
+ //assign( *functor_ptr( in_buffer ), out_buffer, dummy_allocator() );
               out_buffer.obj_ptr = in_buffer.obj_ptr;
           }
 
@@ -605,7 +603,7 @@
 
           static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
           {
- return assign( in_buffer, out_buffer, dummy_allocator() );
+ assign( in_buffer, out_buffer, dummy_allocator() );
           }
 
           static void BF_FASTCALL_WORKAROUND move( function_buffer & in_buffer, function_buffer & out_buffer )
@@ -647,7 +645,7 @@
               function_buffer in_buffer;
               in_buffer.trivial_heap_obj.ptr = const_cast<Functor *>( &functor );
               in_buffer.trivial_heap_obj.size = sizeof( Functor );
- return clone( in_buffer, out_buffer );
+ clone( in_buffer, out_buffer );
           }
 
           static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
@@ -686,7 +684,8 @@
           static Functor * functor_ptr( function_buffer & buffer ) { return static_cast<Functor *>( manager_trivial_small::functor_ptr( buffer ) ); }
           static Functor const * functor_ptr( function_buffer const & buffer ) { return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
 
- static void assign( Functor const & functor, function_buffer & out_buffer )
+ template <typename Allocator>
+ static void assign( Functor const & functor, function_buffer & out_buffer, Allocator )
           {
               new ( functor_ptr( out_buffer ) ) Functor( functor );
           }
@@ -694,7 +693,7 @@
           static void BF_FASTCALL_WORKAROUND clone( function_buffer const & in_buffer, function_buffer & out_buffer )
           {
               Functor const & in_functor( *functor_ptr( in_buffer ) );
- return assign( in_functor, out_buffer );
+ assign( in_functor, out_buffer, dummy_allocator() );
           }
 
           static void BF_FASTCALL_WORKAROUND move( function_buffer & in_buffer, function_buffer & out_buffer )
@@ -1090,10 +1089,15 @@
               BOOST_ASSERT( pFunction_ );
               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<>?
+ //...zzz..remove completely or replace with a simple is_stateless<>?
               BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT
               (
- empty_handler_traits::allowsPODOptimization &&
+ // Implementation note:
+ // POD optimization detection erroneously fails on older GCCs
+ // (GCC 4.2.1) so it must be ignored. This is safe for now as
+ // the code supports this.
+ // (28.10.2010.) (Domagoj Saric)
+ //empty_handler_traits::allowsPODOptimization &&
                 empty_handler_traits::allowsSmallObjectOptimization
               );
               empty_handler_manager::assign( EmptyHandler(), pFunction_->functor_, fallocator<EmptyHandler>() );
@@ -1577,24 +1581,11 @@
 
 namespace detail {
   namespace function {
+
     BOOST_FUNCTION_ENABLE_IF_FUNCTION
     inline has_empty_target( Function const * const f )
     {
- return f->empty();
- }
-
- template <class FunctionObj>
- inline bool has_empty_target( reference_wrapper<FunctionObj> const * const f )
- {
- // Implementation note:
- // We save/assign a reference to a boost::function even if it is empty
- // and let the referenced function handle a possible empty invocation.
- // (28.10.2010.) (Domagoj Saric)
- BF_ASSUME( f != 0 );
- BF_ASSUME( f->get_pointer() != 0 );
- return is_base_of<function_base, FunctionObj>::value
- ? ( f == 0 )
- : has_empty_target( f->get_pointer() );
+ return f->empty();
     }
 
     template <class FunctionPtr>
@@ -1617,7 +1608,25 @@
     //inline bool has_empty_target(...)
     inline bool has_empty_target( void const * )
     {
- return false;
+ return false;
+ }
+
+ // Implementation note:
+ // This has to be after the void const * overload because of non-lazy
+ // compilers (e.g. GCC 4.2.1).
+ // (28.10.2010.) (Domagoj Saric)
+ template <class FunctionObj>
+ inline bool has_empty_target( reference_wrapper<FunctionObj> const * const f )
+ {
+ // Implementation note:
+ // We save/assign a reference to a boost::function even if it is empty
+ // and let the referenced function handle a possible empty invocation.
+ // (28.10.2010.) (Domagoj Saric)
+ BF_ASSUME( f != 0 );
+ BF_ASSUME( f->get_pointer() != 0 );
+ return is_base_of<function_base, FunctionObj>::value
+ ? ( f == 0 )
+ : has_empty_target( f->get_pointer() );
     }
 
     /* Just an experiment to show how can the current boost::mem_fn implementation
@@ -1669,9 +1678,11 @@
     }
     else
     {
- // 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).
+ /// \todo This can/should be rewritten because the
+ /// small-object-optimization condition is too strict, even heap
+ /// allocated targets can be assigned directly because they have a
+ /// nothrow swap operation..
+ /// (28.10.2010.) (Domagoj Saric)
         typedef mpl::bool_
         <
             ::boost::type_traits::ice_and

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-28 13:26:56 EDT (Thu, 28 Oct 2010)
@@ -248,7 +248,17 @@
 
     BOOST_FUNCTION_FUNCTION() : function_base( empty_handler_vtable() )
     {
- BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT( is_stateless<base_empty_handler>::value );
+ // Implementation note:
+ // The condition is relaxed for Clang and older GCC that simply seem
+ // to have a broken is_statless<> implementation. This should be (more
+ // than) safe, for now, because the current code works (or should work)
+ // even with non-stateless empty handlers.
+ // (28.10.2010.) (Domagoj Saric)
+ #if BOOST_WORKAROUND(BOOST_MSVC, >= 1500)
+ BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT( is_stateless<base_empty_handler>::value );
+ #else
+ BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT( is_empty<base_empty_handler>::value );
+ #endif // BOOST_MSVC
     }
 
     // MSVC chokes if the following two constructors are collapsed into


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