Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r50642 - in sandbox/thread_safe_signals/trunk: boost/signals2 libs/signals2/doc/reference libs/signals2/test
From: fmhess_at_[hidden]
Date: 2009-01-16 15:55:42


Author: fmhess
Date: 2009-01-16 15:55:42 EST (Fri, 16 Jan 2009)
New Revision: 50642
URL: http://svn.boost.org/trac/boost/changeset/50642

Log:
Added boost::signals2::deconstruct, which is similar to boost::make_shared
except with postconstructible/predestructible support. All overloads of
deconstruct may be made a friend by making
boost::signals2::deconstruct_access a friend.

Added:
   sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct.hpp (contents, props changed)
Text files modified:
   sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct_ptr.hpp | 28 ++++++++++++++++---------
   sandbox/thread_safe_signals/trunk/boost/signals2/predestructible.hpp | 3 -
   sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/predestructible.xml | 3 ++
   sandbox/thread_safe_signals/trunk/libs/signals2/test/deconstruct_test.cpp | 43 +++++++++++++++++++++++++++++++++++++++
   4 files changed, 64 insertions(+), 13 deletions(-)

Added: sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct.hpp
==============================================================================
--- (empty file)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct.hpp 2009-01-16 15:55:42 EST (Fri, 16 Jan 2009)
@@ -0,0 +1,383 @@
+#ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP
+#define BOOST_SIGNALS2_DECONSTRUCT_HPP
+
+// deconstruct.hpp
+// based on make_shared.hpp and make_shared_access patch from Michael Marcin
+//
+// Copyright (c) 2007, 2008 Peter Dimov
+// Copyright (c) 2008 Michael Marcin
+// Copyright (c) 2009 Frank Mori Hess
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org
+// for more information
+
+#include <boost/config.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2/deconstruct_ptr.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <cstddef>
+#include <new>
+
+namespace boost
+{
+
+namespace signals2
+{
+
+namespace detail
+{
+
+template< std::size_t N, std::size_t A > struct sp_aligned_storage
+{
+ union type
+ {
+ char data_[ N ];
+ typename boost::type_with_alignment< A >::type align_;
+ };
+};
+
+template< class T > class sp_ms_deleter
+{
+private:
+
+ typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
+
+ bool initialized_;
+ storage_type storage_;
+
+private:
+
+ void destroy()
+ {
+ if( initialized_ )
+ {
+ T* p = reinterpret_cast< T* >( storage_.data_ );
+ detail::do_predestruct(p);
+ p->~T();
+ initialized_ = false;
+ }
+ }
+
+public:
+
+ sp_ms_deleter(): initialized_( false )
+ {
+ }
+
+ ~sp_ms_deleter()
+ {
+ destroy();
+ }
+
+ void operator()( T * )
+ {
+ destroy();
+ }
+
+ void * address()
+ {
+ return storage_.data_;
+ }
+
+ void set_initialized()
+ {
+ initialized_ = true;
+ }
+};
+
+template< class T > T forward( T t )
+{
+ return t;
+}
+
+class deconstruct_access
+{
+public:
+
+ template< class T >
+ static boost::shared_ptr< T > deconstruct()
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T();
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
+
+ // Variadic templates, rvalue reference
+
+ template< class T, class... Args >
+ static boost::shared_ptr< T > deconstruct( Args && ... args )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( detail::forward<Args>( args )... );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+#else
+
+ template< class T, class A1 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3, class A4 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3, a4 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3, class A4, class A5 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3, a4, a5 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3, a4, a5, a6 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+ template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
+ static boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
+ {
+ boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
+
+ detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
+
+ void * pv = pd->address();
+
+ new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
+ pd->set_initialized();
+
+ boost::shared_ptr< T > retval( pt, static_cast< T* >( pv ) );
+ detail::do_postconstruct(retval.get());
+ return retval;
+ }
+
+#endif
+};
+} // namespace detail
+
+// Zero-argument versions
+//
+// Used even when variadic templates are available because of the new T() vs new T issue
+
+template< class T > boost::shared_ptr< T > deconstruct()
+{
+ return detail::deconstruct_access::deconstruct<T>();
+}
+
+#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
+
+// Variadic templates, rvalue reference
+
+template< class T, class... Args > boost::shared_ptr< T > deconstruct( Args && ... args )
+{
+ return detail::deconstruct_access::deconstruct( detail::forward<Args>( args )... );
+}
+
+#else
+
+// C++03 version
+
+template< class T, class A1 >
+boost::shared_ptr< T > deconstruct( A1 const & a1 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1);
+}
+
+template< class T, class A1, class A2 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2);
+}
+
+template< class T, class A1, class A2, class A3 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3);
+}
+
+template< class T, class A1, class A2, class A3, class A4 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3,a4);
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5);
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6);
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7);
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8);
+}
+
+template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
+boost::shared_ptr< T > deconstruct( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
+{
+ return detail::deconstruct_access::deconstruct<T>(a1,a2,a3,a4,a5,a6,a7,a8,a9);
+}
+
+using detail::deconstruct_access;
+
+#endif
+
+} // namespace signals2
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SIGNALS2_DECONSTRUCT_HPP

Modified: sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct_ptr.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct_ptr.hpp (original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/deconstruct_ptr.hpp 2009-01-16 15:55:42 EST (Fri, 16 Jan 2009)
@@ -13,6 +13,7 @@
 #ifndef BOOST_SIGNALS2_DECONSTRUCT_PTR_HPP
 #define BOOST_SIGNALS2_DECONSTRUCT_PTR_HPP
 
+#include <boost/assert.hpp>
 #include <boost/checked_delete.hpp>
 #include <boost/signals2/postconstructible.hpp>
 #include <boost/signals2/predestructible.hpp>
@@ -32,24 +33,31 @@
       extern inline void do_postconstruct(...)
       {
       }
+ extern inline void do_predestruct(...)
+ {
+ }
+ extern inline void do_predestruct(const predestructible *ptr)
+ {
+ try
+ {
+ predestructible *nonconst_ptr = const_cast<predestructible*>(ptr);
+ nonconst_ptr->predestruct();
+ }
+ catch(...)
+ {
+ BOOST_ASSERT(false);
+ }
+ }
     }
+
     template<typename T> class predestructing_deleter
     {
     public:
       void operator()(const T *ptr) const
       {
- m_predestruct(ptr);
+ detail::do_predestruct(ptr);
         checked_delete(ptr);
       }
- private:
- static void m_predestruct(...)
- {
- }
- static void m_predestruct(const predestructible *ptr)
- {
- predestructible *nonconst_ptr = const_cast<predestructible*>(ptr);
- nonconst_ptr->predestruct();
- }
     };
 
     template<typename T>

Modified: sandbox/thread_safe_signals/trunk/boost/signals2/predestructible.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/predestructible.hpp (original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/predestructible.hpp 2009-01-16 15:55:42 EST (Fri, 16 Jan 2009)
@@ -23,9 +23,8 @@
     class predestructible
     {
     protected:
- template<typename T>
- friend class predestructing_deleter;
       predestructible() {}
+ public:
       virtual ~predestructible() {}
       virtual void predestruct() {}
     };

Modified: sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/predestructible.xml
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/predestructible.xml (original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/predestructible.xml 2009-01-16 15:55:42 EST (Fri, 16 Jan 2009)
@@ -9,6 +9,9 @@
         <purpose>A base class for classes with predestructors, used in conjunction with <functionname>deconstruct_ptr</functionname>().
         </purpose>
         <access name="protected">
+ <constructor/>
+ </access>
+ <access name="public">
           <destructor specifiers="virtual"/>
           <method name="predestruct" specifiers="virtual">
             <type>void</type>

Modified: sandbox/thread_safe_signals/trunk/libs/signals2/test/deconstruct_test.cpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/test/deconstruct_test.cpp (original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/test/deconstruct_test.cpp 2009-01-16 15:55:42 EST (Fri, 16 Jan 2009)
@@ -9,6 +9,7 @@
 
 #include <boost/shared_ptr.hpp>
 #include <boost/test/minimal.hpp>
+#include <boost/signals2/deconstruct.hpp>
 #include <boost/signals2/deconstruct_ptr.hpp>
 
 class X: public boost::signals2::postconstructible {
@@ -46,7 +47,25 @@
 class Z: public X, public Y
 {};
 
-int test_main(int, char*[])
+class by_deconstruct_only: public boost::signals2::postconstructible {
+public:
+ ~by_deconstruct_only()
+ {
+ BOOST_CHECK(_postconstructed);
+ }
+protected:
+ virtual void postconstruct()
+ {
+ _postconstructed = true;
+ }
+ bool _postconstructed;
+private:
+ friend class boost::signals2::deconstruct_access;
+ by_deconstruct_only(int): _postconstructed(false)
+ {}
+};
+
+void deconstruct_ptr_test()
 {
   {
     boost::shared_ptr<X> x = boost::signals2::deconstruct_ptr(new X);
@@ -57,5 +76,27 @@
   {
     boost::shared_ptr<Z> z = boost::signals2::deconstruct_ptr(new Z);
   }
+}
+
+void deconstruct_test()
+{
+ {
+ boost::shared_ptr<X> x = boost::signals2::deconstruct<X>();
+ }
+ {
+ boost::shared_ptr<Y> x = boost::signals2::deconstruct<Y>();
+ }
+ {
+ boost::shared_ptr<Z> z = boost::signals2::deconstruct<Z>();
+ }
+ {
+ boost::shared_ptr<by_deconstruct_only> a = boost::signals2::deconstruct<by_deconstruct_only>(1);
+ }
+}
+
+int test_main(int, char*[])
+{
+ deconstruct_ptr_test();
+ deconstruct_test();
   return 0;
 }


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