Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66190 - sandbox/function/boost/function
From: dsaritz_at_[hidden]
Date: 2010-10-25 17:21:27


Author: psiha
Date: 2010-10-25 17:21:26 EDT (Mon, 25 Oct 2010)
New Revision: 66190
URL: http://svn.boost.org/trac/boost/changeset/66190

Log:
Added support/special handling for compilers with mem.fn. pointers larger than free fn. pointers.

Removed some ancient-compiler workarounds.
Removed a no longer needed include directive.

Minor other refactoring and stylistic changes.
Text files modified:
   sandbox/function/boost/function/function_base.hpp | 72 ++++++++++++++++++++++++++++-----------
   sandbox/function/boost/function/function_template.hpp | 35 +++++++++++++++---
   2 files changed, 80 insertions(+), 27 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-25 17:21:26 EDT (Mon, 25 Oct 2010)
@@ -121,6 +121,23 @@
   namespace detail {
     namespace function {
 
+ struct thiscall_optimization_available_helper
+ {
+ static void free_function () {}
+ void bound_function() {}
+
+ BOOST_STATIC_CONSTANT( bool, value = sizeof( &thiscall_optimization_available_helper::free_function ) == sizeof( &thiscall_optimization_available_helper::bound_function ) );
+ };
+
+ typedef mpl::bool_
+ <
+ //...zzz...MSVC10 does not like this...
+ //sizeof( &thiscall_optimization_available_helper::free_function )
+ // ==
+ //sizeof( &thiscall_optimization_available_helper::bound_function )
+ thiscall_optimization_available_helper::value
+ > thiscall_optimization_available;
+
     #ifndef BOOST_FUNCTION_NO_RTTI
       // For transferring stored function object type information back to the
       // interface side.
@@ -135,7 +152,7 @@
               const_qualified ( is_const <Functor>::value ),
               volatile_qualified( is_volatile<Functor>::value )
           {
- assert( pFunctor );
+ BOOST_ASSERT( pFunctor );
           }
 
           detail::sp_typeinfo const & functor_type_info() const { return type_id; }
@@ -143,8 +160,6 @@
           template <typename Functor>
           Functor * target()
           {
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
               return static_cast<Functor *>
                      (
                          get_functor_if_types_match
@@ -195,14 +210,14 @@
        */
       #ifdef BOOST_MSVC
         // http://msdn.microsoft.com/en-us/library/5ft82fed(VS.80).aspx (ad unions)
- #define RESTRICT __restrict
+ #define BF_AUX_RESTRICT __restrict
       #else
- #define RESTRICT
+ #define BF_AUX_RESTRICT
       #endif
       union function_buffer
       {
         // For pointers to function objects
- void * RESTRICT obj_ptr;
+ void * BF_AUX_RESTRICT obj_ptr;
 
         // For 'trivial' function objects (that can be managed without type
         // information) that must be allocated on the heap (we must only save
@@ -214,19 +229,19 @@
         } trivial_heap_obj;
 
         // For function pointers of all kinds
- void (* RESTRICT func_ptr)();
+ void (* BF_AUX_RESTRICT func_ptr)();
 
         // For bound member pointers
         struct bound_memfunc_ptr_t {
           class X;
- void (X::*memfunc_ptr)(int);
- void* obj_ptr;
+ void (X::* BF_AUX_RESTRICT memfunc_ptr)(int);
+ void * obj_ptr;
         } bound_memfunc_ptr;
 
         // To relax aliasing constraints
         char data;
       };
- #undef RESTRICT
+ #undef BF_AUX_RESTRICT
 
       // A simple wrapper to allow deriving and a thiscall invoker.
       struct function_buffer_holder { function_buffer buffer; };
@@ -607,11 +622,7 @@
 
           static Functor * & functor_ptr( function_buffer & buffer )
           {
- // 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.
- // ...recheck the above comment after all these changes...
- return (Functor * &)manager_trivial_heap::functor_ptr( buffer );
+ return static_cast<Functor * &>( manager_trivial_heap::functor_ptr( buffer ) );
           }
 
           static Functor * functor_ptr( function_buffer const & buffer )
@@ -886,7 +897,15 @@
       // class to catch such errors at compile-time.
       struct vtable
       {
- typedef void ( function_buffer::* invoker_placeholder_type )( void );
+ typedef void ( function_buffer::* this_call_invoker_placeholder_type )( void );
+ typedef void ( * free_call_invoker_placeholder_type )( void );
+ typedef mpl::if_
+ <
+ thiscall_optimization_available,
+ this_call_invoker_placeholder_type,
+ free_call_invoker_placeholder_type
+ >::type invoker_placeholder_type;
+
         template<typename TargetInvokerType>
         TargetInvokerType const & invoker() const { return reinterpret_cast<TargetInvokerType const &>( void_invoker ); }
 
@@ -914,7 +933,7 @@
         // get_typed_functor function as nothrow like this, explicitly (because
         // MSVC does not properly support exception specifications this is not a
         // pessimization...it is equivalent to __declspec( nothrow )).
- typed_functor (& get_typed_functor )( function_buffer const & )
+ typed_functor (& get_typed_functor)( function_buffer const & )
         #ifdef BOOST_MSVC
             throw()
         #endif // BOOST_MSVC
@@ -941,7 +960,20 @@
       };
 
       template <class Invoker, class Manager>
- struct vtable_holder { static vtable const stored_vtable; };
+ struct vtable_holder
+ {
+ static vtable::this_call_invoker_placeholder_type get_invoker_pointer( mpl::true_ /*this call*/ )
+ {
+ return reinterpret_cast<vtable::this_call_invoker_placeholder_type>( &Invoker::bound_invoke );
+ }
+
+ static vtable::free_call_invoker_placeholder_type get_invoker_pointer( mpl::false_ /*free call*/ )
+ {
+ return reinterpret_cast<vtable::free_call_invoker_placeholder_type>( &Invoker::free_invoke );
+ }
+
+ static vtable const stored_vtable;
+ };
 
       // Note: it is extremely important that this initialization use
       // static initialization. Otherwise, we will have a race
@@ -950,7 +982,7 @@
       template <class Invoker, class Manager>
       vtable const vtable_holder<Invoker, Manager>::stored_vtable =
       {
- reinterpret_cast<vtable::invoker_placeholder_type>( &Invoker::invoke ),
+ vtable_holder<Invoker, Manager>::get_invoker_pointer( thiscall_optimization_available() ),
           &Manager::clone,
           &Manager::move,
           &Manager::destroy
@@ -1344,7 +1376,7 @@
     #endif // BOOST_MSVC
     void throw_bad_call() const
     {
- boost::throw_exception(bad_function_call());
+ boost::throw_exception( bad_function_call() );
     }
 
 public:

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-25 17:21:26 EDT (Mon, 25 Oct 2010)
@@ -11,7 +11,6 @@
 // Note: this header is a header template and must NOT have multiple-inclusion
 // protection.
 #include <boost/function/detail/prologue.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
 
 #if defined(BOOST_MSVC)
 # pragma warning( push )
@@ -74,7 +73,7 @@
>
      struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER : public function_buffer_holder
      {
- R invoke( BOOST_FUNCTION_PARMS )
+ static R free_invoke( function_buffer & buffer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS )
        {
            // We provide the invoker with a manager with a minimum amount of
            // type information (because it already knows the stored function
@@ -98,6 +97,11 @@
            // the one from std::tr1, does not support callable objects.
            return unwrap_ref( functionObject )( BOOST_FUNCTION_ARGS );
        }
+
+ R bound_invoke( BOOST_FUNCTION_PARMS )
+ {
+ return free_invoke( buffer BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS );
+ }
      };
 
       template
@@ -108,12 +112,17 @@
>
       struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER : public function_buffer_holder
       {
- BOOST_FUNCTION_VOID_RETURN_TYPE invoke(BOOST_FUNCTION_PARMS)
+ static BOOST_FUNCTION_VOID_RETURN_TYPE free_invoke( function_buffer & buffer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS )
           {
               // See the above comments for the non-void invoker.
               FunctionObj & functionObject( *static_cast<FunctionObj *>( static_cast<void *>( FunctionObjManager::functor_ptr( buffer ) ) ) );
               BOOST_FUNCTION_RETURN( unwrap_ref( functionObject )( BOOST_FUNCTION_ARGS ) );
           }
+
+ BOOST_FUNCTION_VOID_RETURN_TYPE bound_invoke( BOOST_FUNCTION_PARMS )
+ {
+ BOOST_FUNCTION_RETURN( free_invoke( buffer BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS ) );
+ }
       };
     } // end namespace function
   } // end namespace detail
@@ -437,21 +446,33 @@
     #ifdef BOOST_MSVC
         __declspec( nothrow )
     #endif
- result_type invoke(BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::true_ /*no throw invoker*/) const
+ result_type invoke( BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::true_ /*no throw invoker*/ ) const
     #ifndef BOOST_MSVC
         throw()
     #endif
     {
- typedef result_type (detail::function::function_buffer::* invoker_type)(BOOST_FUNCTION_TEMPLATE_ARGS);
- return (functor.*(get_vtable().invoker<invoker_type>()))(BOOST_FUNCTION_ARGS);
+ return do_invoke( BOOST_FUNCTION_ARGS BOOST_FUNCTION_COMMA detail::function::thiscall_optimization_available() );
     }
 
- result_type invoke(BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::false_ /*throwable invoker*/) const
+ result_type invoke( BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::false_ /*throwable invoker*/ ) const
+ {
+ return do_invoke( BOOST_FUNCTION_ARGS BOOST_FUNCTION_COMMA detail::function::thiscall_optimization_available() );
+ }
+
+
+ result_type do_invoke( BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::true_ /*this call*/ ) const
     {
         typedef result_type (detail::function::function_buffer::* invoker_type)(BOOST_FUNCTION_TEMPLATE_ARGS);
         return (functor.*(get_vtable().invoker<invoker_type>()))(BOOST_FUNCTION_ARGS);
     }
 
+ result_type do_invoke( BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::false_ /*free call*/ ) const
+ {
+ typedef result_type (* invoker_type)(detail::function::function_buffer & BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS);
+ return get_vtable().invoker<invoker_type>()( functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS );
+ }
+
+
     // This overload should not actually be for a 'complete' BOOST_FUNCTION_FUNCTION as it is enough
         // 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


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