Compare commits

..

5 Commits

Author SHA1 Message Date
a397c16d4c used dtor_optimized in destroy for branch free destroy
[SVN r77238]
2012-03-05 19:43:14 +00:00
592795e00b has_trivial_copy and basic copy optimization done
[SVN r77237]
2012-03-05 19:13:54 +00:00
7ac0cbe617 has_trivial_destructor and dtor optimization done.
[SVN r77235]
2012-03-05 17:13:05 +00:00
cb9e852350 move m_initialized = false ; to destroy()
[SVN r77153]
2012-03-02 16:38:58 +00:00
776ed89fb3 optional_optimization branch
[SVN r77091]
2012-02-22 10:37:27 +00:00
3 changed files with 159 additions and 18 deletions

View File

@ -26,9 +26,14 @@
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/or.hpp>
#include <boost/detail/reference_content.hpp>
#include <boost/none.hpp>
#include <boost/utility/swap.hpp>
@ -168,6 +173,19 @@ struct types_when_is_ref
typedef raw_type& argument_type ;
} ;
template<typename T>
struct optional_dtor_optimized : has_trivial_destructor<T> {};
template<typename T>
struct optional_copy_optimized : mpl::or_<
is_reference<T>, // refs aren't copyable at all, but optional<T&> should be copy_optimized
mpl::and_<
has_trivial_copy<T>,
has_trivial_assign<T>,
mpl::bool_< (sizeof(T) <= 128) > // TODO make 128 configurable
>
> {};
struct optional_tag {} ;
template<class T>
@ -199,6 +217,8 @@ class optional_base : public optional_tag
public:
typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
typedef optional_dtor_optimized<T> dtor_optimized;
typedef optional_copy_optimized<T> copy_optimized;
protected:
typedef bool (this_type::*unspecified_bool_type)() const;
@ -242,9 +262,7 @@ class optional_base : public optional_tag
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional_base ( optional_base const& rhs )
:
m_initialized(false)
void optional_base_copy_ctor_impl ( optional_base const& rhs )
{
if ( rhs.is_initialized() )
construct(rhs.get_impl());
@ -265,7 +283,7 @@ class optional_base : public optional_tag
// No-throw (assuming T::~T() doesn't)
~optional_base() { destroy() ; }
//~optional_base() { destroy() ; }
// Assigns from another optional<T> (deep-copies the rhs value)
void assign ( optional_base const& rhs )
@ -435,9 +453,19 @@ class optional_base : public optional_tag
void destroy()
{
if ( m_initialized )
if( dtor_optimized::value )
m_initialized = false ;
else if ( m_initialized ){
destroy_impl(is_reference_predicate()) ;
m_initialized = false ;
}
}
void destructor_impl() // doesn't reset m_initialized
{
if(m_initialized)
destroy_impl(is_reference_predicate()) ;
}
template<typename Optional,bool dtor_optimized> friend class optional_dtor_mixin;
unspecified_bool_type safe_bool() const { return m_initialized ? &this_type::is_initialized : 0 ; }
@ -474,12 +502,12 @@ class optional_base : public optional_tag
reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; }
#else
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; m_initialized = false ; }
void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->T::~T() ; }
#endif
void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
void destroy_impl ( is_reference_tag ) { }
// If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
// Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
@ -493,12 +521,75 @@ class optional_base : public optional_tag
storage_type m_storage ;
} ;
template<class T,bool copy_optimized>
struct optional_copier : optional_base<T>
{
// does copy and assignment optimization
typedef optional_detail::optional_base<T> base ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
optional_copier () {}
optional_copier ( optional_copier const& rhs ) : base()
{
optional_base_copy_ctor_impl(rhs);
}
optional_copier& operator= ( optional_copier const& rhs )
{
this->assign( static_cast<base const&>(rhs) ) ;
return *this ;
}
template<class Expr>
explicit optional_copier ( Expr expr ) : base(expr) {}
template<class P1,class P2>
explicit optional_copier ( P1 p1 ,P2 p2 ) : base(p1,p2) {}
optional_copier ( bool cond, argument_type val ) : base(cond,val) {}
};
template<class T>
struct optional_copier<T, true> : optional_base<T>
{
// does copy and assignment optimization
typedef optional_detail::optional_base<T> base ;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
optional_copier () {}
//optional_copier ( optional_copier const& rhs ) // default impl does memcpy
//optional_copier& operator= ( optional_copier const& rhs ) // default impl does memcpy
template<class Expr>
explicit optional_copier ( Expr expr ) : base(expr) {}
template<class P1,class P2>
explicit optional_copier ( P1 p1 ,P2 p2 ) : base(p1,p2) {}
optional_copier ( bool cond, argument_type val ) : base(cond,val) {}
};
template<typename Optional,bool dtor_optimized>
struct optional_dtor_mixin{
~optional_dtor_mixin(){ static_cast<Optional*>(this)->destructor_impl() ; }
};
template<typename Optional>
struct optional_dtor_mixin<Optional, true > { };
} // namespace optional_detail
template<class T>
class optional : public optional_detail::optional_base<T>
class optional :
public optional_detail::optional_copier<T, optional_detail::optional_base<T>::copy_optimized::value >,
public optional_detail::optional_dtor_mixin<optional<T>, optional_detail::optional_base<T>::dtor_optimized::value >
{
typedef optional_detail::optional_base<T> base ;
typedef optional_detail::optional_copier<T, optional_detail::optional_base<T>::copy_optimized::value > base ;
typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ;
@ -561,10 +652,10 @@ class optional : public optional_detail::optional_base<T>
// Creates a deep copy of another optional<T>
// Can throw if T::T(T const&) does
optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
//optional ( optional const& rhs ) // default impl (see optional_copier)
// No-throw (assuming T::~T() doesn't)
~optional() {}
// No-throw (assuming T::~T() doesn't)
//~optional() {}
#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
// Assigns from an expression. See corresponding constructor.
@ -593,11 +684,7 @@ class optional : public optional_detail::optional_base<T>
// Assigns from another optional<T> (deep-copies the rhs value)
// Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
// (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
optional& operator= ( optional const& rhs )
{
this->assign( static_cast<base const&>(rhs) ) ;
return *this ;
}
//optional& operator= ( optional const& rhs ) // default impl (see optional_copier)
// Assigns from a T (deep-copies the rhs value)
// Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED

View File

@ -29,5 +29,6 @@ import testing ;
[ compile-fail optional_test_ref_fail4.cpp ]
[ compile-fail optional_test_inplace_fail.cpp ]
[ compile-fail optional_test_inplace_fail2.cpp ]
[ compile optional_test_trivial_assertions.cpp ]
;
}

View File

@ -0,0 +1,53 @@
#include "boost/optional.hpp"
#include "boost/static_assert.hpp"
#include "boost/type_traits.hpp"
using namespace boost;
typedef optional<char> oc;
typedef optional<int> oi;
typedef optional<int&> of;
typedef optional<std::string> os;
BOOST_STATIC_ASSERT( sizeof(oc) <= 2*sizeof(char) );
BOOST_STATIC_ASSERT( sizeof(oi) <= 2*sizeof(int) );
BOOST_STATIC_ASSERT( !has_trivial_default_constructor<oi>::value ); //never true for optional
BOOST_STATIC_ASSERT( !has_trivial_default_constructor<os>::value );
BOOST_STATIC_ASSERT( has_trivial_destructor<oi>::value ); //should be true where has_trivial_destructor<T>
BOOST_STATIC_ASSERT( has_trivial_destructor<of>::value );
BOOST_STATIC_ASSERT( !has_trivial_destructor<os>::value );
BOOST_STATIC_ASSERT( has_trivial_copy<oi>::value ); //should be true where has_trivial_copy<T>
BOOST_STATIC_ASSERT( has_trivial_copy<of>::value );
BOOST_STATIC_ASSERT( !has_trivial_copy<os>::value );
BOOST_STATIC_ASSERT( has_trivial_assign<oi>::value ); //should be true where has_trivial_assign<T>
BOOST_STATIC_ASSERT( has_trivial_assign<of>::value );
BOOST_STATIC_ASSERT( !has_trivial_assign<os>::value );
BOOST_STATIC_ASSERT( oi::dtor_optimized::value );
BOOST_STATIC_ASSERT( oi::copy_optimized::value );
BOOST_STATIC_ASSERT( of::dtor_optimized::value );
BOOST_STATIC_ASSERT( of::copy_optimized::value );
/*
* The code generated below can be looked at with objdump to see if it is suboptimal
*/
void assign_optional_int(oi& x,oi& y){
x=y;
}
void reset_optional_int(oi& x){
x=boost::none;
}