Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r66306 - sandbox/function/boost/function
From: dsaritz_at_[hidden]
Date: 2010-11-01 06:18:46


Author: psiha
Date: 2010-11-01 06:18:33 EDT (Mon, 01 Nov 2010)
New Revision: 66306
URL: http://svn.boost.org/trac/boost/changeset/66306

Log:
Replaced code that relied on a wrong function-alignment assumption with new working code.
Renamed policy classes to follow Boost naming conventions.
Text files modified:
   sandbox/function/boost/function/function_base.hpp | 58 ++++++++++++++-------------------------
   sandbox/function/boost/function/function_fwd.hpp | 4 +-
   sandbox/function/boost/function/function_template.hpp | 12 ++-----
   3 files changed, 27 insertions(+), 47 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-11-01 06:18:33 EDT (Mon, 01 Nov 2010)
@@ -970,17 +970,17 @@
       // address of the empty handler vtable for module B. This comparison will
       // obviously result in not-equal yielding the incorrect result.
       // Because of the above, 'is empty' information is additionally stored
- // in the vtable. To avoid adding another (bool) member, one of the
- // function pointers is mangled with the assumption that all of the
- // functions are at least two-byte aligned and that the LSB is safe to use
- // as storage. This obviously increases invocation overhead so the least
- // frequently used function should be chosen, get_typed_functor would be
- // the obvious choice but it need not exist (with BOOST_FUNCTION_NO_RTTI)
- // so do_move was chosen.
- // (31.10.2010.) (Domagoj Saric)
+ // in the vtable. For this an additional bool data member is added. The
+ // alternative would be to mangle/'tag' the vtable pointer but this would
+ // actually add much more overhead (in both size and speed) because of
+ // the inline-replicated demangling code. Mangling only a single, least
+ // often used function pointer from the vtable is also no-good because it
+ // would require functions-are-at-least-even-aligned assumption to hold
+ // which need not be the case.
+ // (01.11.2010.) (Domagoj Saric)
       struct vtable
       {
- bool is_empty_handler_vtable() const;
+ bool is_empty_handler_vtable() const { return is_empty_handler_vtable_; }
 
         typedef void ( function_buffer::* this_call_invoker_placeholder_type )( void );
         typedef void ( * free_call_invoker_placeholder_type )( void );
@@ -995,7 +995,7 @@
         TargetInvokerType const & invoker() const { return reinterpret_cast<TargetInvokerType const &>( void_invoker ); }
 
         void clone ( function_buffer const & in_buffer, function_buffer & out_buffer ) const { do_clone( in_buffer, out_buffer ); }
- void move ( function_buffer & in_buffer, function_buffer & out_buffer ) const;
+ void move ( function_buffer & in_buffer, function_buffer & out_buffer ) const { do_move ( in_buffer, out_buffer ); }
         BF_NOTHROW
         void destroy( function_buffer & buffer ) const { do_destroy( buffer ); }
 
@@ -1027,28 +1027,11 @@
 
       #endif // BOOST_FUNCTION_NO_RTTI
 
- typedef void (BF_FASTCALL_WORKAROUND * move_function_t )( function_buffer & in_buffer, function_buffer & out_buffer );
+ public: // "Private but not private" to enable aggregate-style initialization.
+ bool const is_empty_handler_vtable_;
       };
 
- inline bool vtable::is_empty_handler_vtable() const
- {
- return reinterpret_cast<std::size_t>( BF_VT_REF_TO_POINTER this->do_move ) & static_cast<std::size_t>( 0x01 );
- }
-
- inline void vtable::move( function_buffer & in_buffer, function_buffer & out_buffer ) const
- {
- BOOST_STATIC_ASSERT( sizeof( move_function_t ) == sizeof( std::size_t ) );
- move_function_t const move_function
- (
- reinterpret_cast<move_function_t>
- (
- reinterpret_cast<std::size_t>( BF_VT_REF_TO_POINTER this->do_move ) & ~static_cast<std::size_t>( 0x01 )
- )
- );
- move_function( in_buffer, out_buffer );
- }
-
- template <class Invoker, class Manager, bool is_empty_handler>
+ template <class Invoker, class Manager, class IsEmptyHandler>
       struct vtable_holder
       {
           static vtable::this_call_invoker_placeholder_type get_invoker_pointer( mpl::true_ /*this call*/ )
@@ -1068,16 +1051,17 @@
       // static initialization. Otherwise, we will have a race
       // condition here in multi-threaded code. See
       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
- template <class Invoker, class Manager, bool is_empty_handler>
- vtable const vtable_holder<Invoker, Manager, is_empty_handler>::stored_vtable =
+ template <class Invoker, class Manager, class IsEmptyHandler>
+ vtable const vtable_holder<Invoker, Manager, IsEmptyHandler>::stored_vtable =
       {
- vtable_holder<Invoker, Manager, is_empty_handler>::get_invoker_pointer( thiscall_optimization_available() ),
- BF_VT_DEREF &Manager::clone,
- BF_VT_DEREF reinterpret_cast<vtable::move_function_t>( reinterpret_cast<std::size_t>( &Manager::move ) | ( is_empty_handler * 0x01 ) ),
- BF_VT_DEREF &Manager::destroy
+ vtable_holder<Invoker, Manager, IsEmptyHandler>::get_invoker_pointer( thiscall_optimization_available() ),
+ BF_VT_DEREF &Manager::clone ,
+ BF_VT_DEREF &Manager::move ,
+ BF_VT_DEREF &Manager::destroy,
         #ifndef BOOST_FUNCTION_NO_RTTI
- ,BF_VT_DEREF &Manager::get_typed_functor
+ BF_VT_DEREF &Manager::get_typed_functor,
         #endif // BOOST_FUNCTION_NO_RTTI
+ IsEmptyHandler::value
       };
 
 

Modified: sandbox/function/boost/function/function_fwd.hpp
==============================================================================
--- sandbox/function/boost/function/function_fwd.hpp (original)
+++ sandbox/function/boost/function/function_fwd.hpp 2010-11-01 06:18:33 EDT (Mon, 01 Nov 2010)
@@ -43,8 +43,8 @@
 
   class bad_function_call;
 
- struct EmptyHandler {};
- struct Nothrow {};
+ struct empty_handler_t {};
+ struct is_no_throw_t {};
 
   typedef mpl::map0<> default_policies;
 

Modified: sandbox/function/boost/function/function_template.hpp
==============================================================================
--- sandbox/function/boost/function/function_template.hpp (original)
+++ sandbox/function/boost/function/function_template.hpp 2010-11-01 06:18:33 EDT (Mon, 01 Nov 2010)
@@ -169,8 +169,8 @@
     typedef throw_on_empty default_empty_handler ;
     typedef mpl::false_ default_nothrow_policy;
 
- typedef typename mpl::at<PolicyList, EmptyHandler>::type user_specified_empty_handler ;
- typedef typename mpl::at<PolicyList, Nothrow >::type user_specified_nothrow_policy;
+ typedef typename mpl::at<PolicyList, empty_handler_t>::type user_specified_empty_handler ;
+ typedef typename mpl::at<PolicyList, is_no_throw_t >::type user_specified_nothrow_policy;
 
   public: // Public typedefs/introspection section.
 #ifndef BOOST_NO_VOID_RETURNS
@@ -572,12 +572,8 @@
             ==
         is_same<StoredFunctor, my_empty_handler >::value
       ));
- // Implementation note:
- // Function alignment assumption verification. See the note for the
- // detail::function::vtable struct for more info.
- // (31.10.2010.) (Domagoj Saric)
- BOOST_ASSERT( ( reinterpret_cast<std::size_t>( &manager_type::move ) & static_cast<std::size_t>( 0x01 ) ) == 0 );
- return vtable_holder<invoker_type, manager_type, is_same<ActualFunctor, base_empty_handler>::value>::stored_vtable;
+ typedef is_same<ActualFunctor, base_empty_handler> is_empty_handler;
+ return vtable_holder<invoker_type, manager_type, is_empty_handler>::stored_vtable;
     }
 
 


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