| 1 | #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
|
|---|
| 2 | #define BOOST_MAKE_SHARED_HPP_INCLUDED
|
|---|
| 3 |
|
|---|
| 4 | //
|
|---|
| 5 | // make_shared.hpp
|
|---|
| 6 | //
|
|---|
| 7 | // Copyright (c) 2007 Peter Dimov
|
|---|
| 8 | //
|
|---|
| 9 | // Distributed under the Boost Software License, Version 1.0. (See
|
|---|
| 10 | // accompanying file LICENSE_1_0.txt or copy at
|
|---|
| 11 | // http://www.boost.org/LICENSE_1_0.txt)
|
|---|
| 12 | //
|
|---|
| 13 | // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
|
|---|
| 14 | //
|
|---|
| 15 |
|
|---|
| 16 | #include <boost/config.hpp>
|
|---|
| 17 | #include <boost/shared_ptr.hpp>
|
|---|
| 18 | #include <boost/type_traits/type_with_alignment.hpp>
|
|---|
| 19 | #include <boost/type_traits/alignment_of.hpp>
|
|---|
| 20 | #include <cstddef>
|
|---|
| 21 | #include <new>
|
|---|
| 22 |
|
|---|
| 23 | namespace boost
|
|---|
| 24 | {
|
|---|
| 25 | namespace detail
|
|---|
| 26 | {
|
|---|
| 27 | template< std::size_t N, std::size_t A > struct sp_aligned_storage
|
|---|
| 28 | {
|
|---|
| 29 | union type
|
|---|
| 30 | {
|
|---|
| 31 | char data_[ N ];
|
|---|
| 32 | typename boost::type_with_alignment< A >::type align_;
|
|---|
| 33 | };
|
|---|
| 34 | };
|
|---|
| 35 |
|
|---|
| 36 | template< class T > class sp_ms_deleter
|
|---|
| 37 | {
|
|---|
| 38 | private:
|
|---|
| 39 |
|
|---|
| 40 | typedef typename sp_aligned_storage< sizeof( T ), boost::alignment_of< T >::value >::type storage_type;
|
|---|
| 41 |
|
|---|
| 42 | bool initialized_;
|
|---|
| 43 | storage_type storage_;
|
|---|
| 44 |
|
|---|
| 45 | private:
|
|---|
| 46 |
|
|---|
| 47 | void destroy()
|
|---|
| 48 | {
|
|---|
| 49 | if( initialized_ )
|
|---|
| 50 | {
|
|---|
| 51 | reinterpret_cast< T* >( storage_.data_ )->~T();
|
|---|
| 52 | initialized_ = false;
|
|---|
| 53 | }
|
|---|
| 54 | }
|
|---|
| 55 |
|
|---|
| 56 | public:
|
|---|
| 57 |
|
|---|
| 58 | sp_ms_deleter(): initialized_( false )
|
|---|
| 59 | {
|
|---|
| 60 | }
|
|---|
| 61 |
|
|---|
| 62 | ~sp_ms_deleter()
|
|---|
| 63 | {
|
|---|
| 64 | destroy();
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | void operator()( T * )
|
|---|
| 68 | {
|
|---|
| 69 | destroy();
|
|---|
| 70 | }
|
|---|
| 71 |
|
|---|
| 72 | void * address()
|
|---|
| 73 | {
|
|---|
| 74 | return storage_.data_;
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | void set_initialized()
|
|---|
| 78 | {
|
|---|
| 79 | initialized_ = true;
|
|---|
| 80 | }
|
|---|
| 81 | };
|
|---|
| 82 | } // namespace detail
|
|---|
| 83 |
|
|---|
| 84 | // Zero-argument versions
|
|---|
| 85 | //
|
|---|
| 86 | // Used even when variadic templates are available because of the new T() vs new T issue
|
|---|
| 87 |
|
|---|
| 88 | template< class T > boost::shared_ptr< T > make_shared()
|
|---|
| 89 | {
|
|---|
| 90 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
|---|
| 91 |
|
|---|
| 92 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 93 |
|
|---|
| 94 | void * pv = pd->address();
|
|---|
| 95 |
|
|---|
| 96 | new( pv ) T();
|
|---|
| 97 | pd->set_initialized();
|
|---|
| 98 |
|
|---|
| 99 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 100 | }
|
|---|
| 101 |
|
|---|
| 102 | template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a )
|
|---|
| 103 | {
|
|---|
| 104 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
|---|
| 105 |
|
|---|
| 106 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 107 |
|
|---|
| 108 | void * pv = pd->address();
|
|---|
| 109 |
|
|---|
| 110 | new( pv ) T();
|
|---|
| 111 | pd->set_initialized();
|
|---|
| 112 |
|
|---|
| 113 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 114 | }
|
|---|
| 115 |
|
|---|
| 116 | // FIXME: boost doesn't seem to have a compiler agnostic replacement for __STRICT_ANSI__
|
|---|
| 117 | #if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) && !defined( __STRICT_ANSI__ )
|
|---|
| 118 |
|
|---|
| 119 | // Variadic templates, rvalue reference
|
|---|
| 120 |
|
|---|
| 121 | template< class T> T forward( T t )
|
|---|
| 122 | {
|
|---|
| 123 | return t;
|
|---|
| 124 | }
|
|---|
| 125 |
|
|---|
| 126 | template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args )
|
|---|
| 127 | {
|
|---|
| 128 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
|---|
| 129 |
|
|---|
| 130 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 131 |
|
|---|
| 132 | void * pv = pd->address();
|
|---|
| 133 |
|
|---|
| 134 | new( pv ) T( forward<Args>( args )... );
|
|---|
| 135 | pd->set_initialized();
|
|---|
| 136 |
|
|---|
| 137 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 138 | }
|
|---|
| 139 |
|
|---|
| 140 | template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args )
|
|---|
| 141 | {
|
|---|
| 142 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
|---|
| 143 |
|
|---|
| 144 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 145 |
|
|---|
| 146 | void * pv = pd->address();
|
|---|
| 147 |
|
|---|
| 148 | new( pv ) T( forward<Args>( args )... );
|
|---|
| 149 | pd->set_initialized();
|
|---|
| 150 |
|
|---|
| 151 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 152 | }
|
|---|
| 153 |
|
|---|
| 154 | #else
|
|---|
| 155 |
|
|---|
| 156 | // C++03 version
|
|---|
| 157 |
|
|---|
| 158 | template< class T, class A1 > boost::shared_ptr< T > make_shared( A1 const & a1 )
|
|---|
| 159 | {
|
|---|
| 160 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
|---|
| 161 |
|
|---|
| 162 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 163 |
|
|---|
| 164 | void * pv = pd->address();
|
|---|
| 165 |
|
|---|
| 166 | new( pv ) T( a1 );
|
|---|
| 167 | pd->set_initialized();
|
|---|
| 168 |
|
|---|
| 169 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 170 | }
|
|---|
| 171 |
|
|---|
| 172 | template< class T, class A, class A1 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 )
|
|---|
| 173 | {
|
|---|
| 174 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
|---|
| 175 |
|
|---|
| 176 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 177 |
|
|---|
| 178 | void * pv = pd->address();
|
|---|
| 179 |
|
|---|
| 180 | new( pv ) T( a1 );
|
|---|
| 181 | pd->set_initialized();
|
|---|
| 182 |
|
|---|
| 183 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 184 | }
|
|---|
| 185 |
|
|---|
| 186 | template< class T, class A1, class A2 > boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 )
|
|---|
| 187 | {
|
|---|
| 188 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
|---|
| 189 |
|
|---|
| 190 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 191 |
|
|---|
| 192 | void * pv = pd->address();
|
|---|
| 193 |
|
|---|
| 194 | new( pv ) T( a1, a2 );
|
|---|
| 195 | pd->set_initialized();
|
|---|
| 196 |
|
|---|
| 197 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 198 | }
|
|---|
| 199 |
|
|---|
| 200 | template< class T, class A, class A1, class A2 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 )
|
|---|
| 201 | {
|
|---|
| 202 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
|---|
| 203 |
|
|---|
| 204 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 205 |
|
|---|
| 206 | void * pv = pd->address();
|
|---|
| 207 |
|
|---|
| 208 | new( pv ) T( a1, a2 );
|
|---|
| 209 | pd->set_initialized();
|
|---|
| 210 |
|
|---|
| 211 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 212 | }
|
|---|
| 213 |
|
|---|
| 214 | template< class T, class A1, class A2, class A3 > boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 )
|
|---|
| 215 | {
|
|---|
| 216 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
|---|
| 217 |
|
|---|
| 218 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 219 |
|
|---|
| 220 | void * pv = pd->address();
|
|---|
| 221 |
|
|---|
| 222 | new( pv ) T( a1, a2, a3 );
|
|---|
| 223 | pd->set_initialized();
|
|---|
| 224 |
|
|---|
| 225 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 226 | }
|
|---|
| 227 |
|
|---|
| 228 | template< class T, class A, class A1, class A2, class A3 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 )
|
|---|
| 229 | {
|
|---|
| 230 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
|---|
| 231 |
|
|---|
| 232 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 233 |
|
|---|
| 234 | void * pv = pd->address();
|
|---|
| 235 |
|
|---|
| 236 | new( pv ) T( a1, a2, a3 );
|
|---|
| 237 | pd->set_initialized();
|
|---|
| 238 |
|
|---|
| 239 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 240 | }
|
|---|
| 241 |
|
|---|
| 242 | template< class T, class A1, class A2, class A3, class A4 > boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
|
|---|
| 243 | {
|
|---|
| 244 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
|
|---|
| 245 |
|
|---|
| 246 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 247 |
|
|---|
| 248 | void * pv = pd->address();
|
|---|
| 249 |
|
|---|
| 250 | new( pv ) T( a1, a2, a3, a4 );
|
|---|
| 251 | pd->set_initialized();
|
|---|
| 252 |
|
|---|
| 253 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 254 | }
|
|---|
| 255 |
|
|---|
| 256 | template< class T, class A, class A1, class A2, class A3, class A4 > boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
|
|---|
| 257 | {
|
|---|
| 258 | boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
|
|---|
| 259 |
|
|---|
| 260 | detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
|
|---|
| 261 |
|
|---|
| 262 | void * pv = pd->address();
|
|---|
| 263 |
|
|---|
| 264 | new( pv ) T( a1, a2, a3, a4 );
|
|---|
| 265 | pd->set_initialized();
|
|---|
| 266 |
|
|---|
| 267 | return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
|
|---|
| 268 | }
|
|---|
| 269 |
|
|---|
| 270 | #endif
|
|---|
| 271 |
|
|---|
| 272 | } // namespace boost
|
|---|
| 273 |
|
|---|
| 274 | #endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
|
|---|