$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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