00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef ADOBE_MEMORY_HPP
00010 #define ADOBE_MEMORY_HPP
00011
00012 #include <adobe/config.hpp>
00013
00014 #include <cassert>
00015 #include <functional>
00016 #include <memory>
00017
00018 #include <boost/utility/enable_if.hpp>
00019 #include <boost/type_traits/is_const.hpp>
00020
00021 #include <adobe/conversion.hpp>
00022 #include <adobe/functional.hpp>
00023 #include <adobe/memory_fwd.hpp>
00024
00025
00026
00027 namespace adobe {
00028
00029
00030
00040 template <typename T>
00041 struct empty_ptr;
00042
00043
00044 template <typename T>
00045 struct empty_ptr<T*> : std::unary_function<T*, void>
00046 {
00047 bool operator () (const T* x) const throw()
00048 { return x == NULL; }
00049 };
00050
00051
00052 template <typename T>
00053 struct empty_ptr<T(*)[]> : std::unary_function<T*, void>
00054 {
00055 bool operator () (const T* x) const throw()
00056 { return x == NULL; }
00057 };
00058
00060
00061
00062
00063 template<typename X, class Traits> class auto_ptr;
00064 template<typename X, class Traits> class auto_resource;
00065
00066 template <typename ptrT>
00067 struct ptr_traits;
00068
00070 template <typename T>
00071 struct ptr_traits<T(*)[]>
00072 {
00073 typedef T element_type;
00074 typedef T* pointer_type;
00075 typedef const T* const_pointer_type;
00076
00077 template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
00078 enum { is_array = true };
00079
00080 static void delete_ptr(pointer_type x) throw() { adobe::delete_ptr<T(*)[]>()(x); }
00081 static bool empty_ptr(const_pointer_type x) throw() { return adobe::empty_ptr<T(*)[]>()(x); }
00082 };
00083
00145 template <typename T>
00146 struct ptr_traits<T*>
00147 {
00148 typedef T element_type;
00149 typedef T* pointer_type;
00150 typedef const pointer_type const_pointer_type;
00151
00152 template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
00153 enum { is_array = false };
00154
00155 static void delete_ptr(pointer_type x) throw() { adobe::delete_ptr<T*>()(x); }
00156 static bool empty_ptr(const_pointer_type x) throw() { return adobe::empty_ptr<T*>()(x); }
00157 };
00158
00160 template <typename T>
00161 struct ptr_traits<std::auto_ptr<T> >
00162 {
00163 typedef typename std::auto_ptr<T>::element_type element_type;
00164 typedef std::auto_ptr<T> pointer_type;
00165 typedef std::auto_ptr<const T> const_pointer_type;
00166
00167 template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
00168 enum { is_array = false };
00169 };
00170
00172 template <typename R, typename T>
00173 struct runtime_cast_t<R, std::auto_ptr<T> > {
00174 R operator()(std::auto_ptr<T>& x) const
00175 {
00176 typedef typename R::element_type* dest_type;
00177 dest_type result = dynamic_cast<dest_type>(x.get());
00178 if (result) x.release();
00179 return R(result);
00180 }
00181 };
00182
00184 template <typename T, class Traits>
00185 struct ptr_traits<auto_ptr<T, Traits> >
00186 {
00187 typedef typename auto_ptr<T, Traits>::element_type element_type;
00188 typedef auto_ptr<T, Traits> pointer_type;
00189 typedef auto_ptr<const T, Traits> const_pointer_type;
00190
00191 enum { is_array = Traits::is_array };
00192 };
00193
00195 template <typename R, typename T, typename Traits>
00196 struct runtime_cast_t<R, auto_ptr<T, Traits> > {
00197 R operator()(auto_ptr<T, Traits>& x) const
00198 {
00199 typedef typename R::element_type* dest_type;
00200 dest_type result = dynamic_cast<dest_type>(x.get());
00201 if (result) x.release();
00202 return R(result);
00203 }
00204 };
00205
00207 template <typename T, class Traits>
00208 struct ptr_traits<auto_resource<T, Traits> >
00209 {
00210 typedef typename Traits::element_type element_type;
00211 typedef auto_resource<T, Traits> pointer_type;
00212 typedef auto_resource<const T, Traits> const_pointer_type;
00213
00214 enum { is_array = Traits::is_array };
00215 };
00216
00218 template <typename R, typename T, typename Traits>
00219 struct runtime_cast_t<R, auto_resource<T, Traits> > {
00220 R operator()(auto_resource<T, Traits>& x) const
00221 {
00222 typedef typename R::element_type* dest_type;
00223 dest_type result = dynamic_cast<dest_type>(x.get());
00224 if (result) x.release();
00225 return R(result);
00226 }
00227 };
00228
00229
00230
00231
00232 #ifndef NO_DOCUMENTATION
00233
00234
00235
00236
00237
00238
00239 namespace implementation {
00240 template <bool x> struct adobe_static_assert;
00241 template <> struct adobe_static_assert<true> { };
00242 }
00243
00244 #endif
00245
00246
00247
00264 template <typename X, class Traits = ptr_traits<X> >
00265 class auto_resource
00266 {
00267 struct clear_type { };
00268 operator int() const;
00269
00270 public:
00271 typedef Traits traits_type;
00272 typedef typename traits_type::element_type element_type;
00273 typedef typename traits_type::pointer_type pointer_type;
00274
00275
00276 explicit auto_resource(pointer_type p = 0) throw();
00277
00278 auto_resource(auto_resource&) throw();
00279 template <typename Y> auto_resource(const auto_resource<Y, typename traits_type::template rebind<Y>::other>&) throw();
00280
00281 auto_resource& operator=(auto_resource&) throw();
00282 template<typename Y> auto_resource& operator=(auto_resource<Y, typename traits_type::template rebind<Y>::other>) throw();
00283
00284 ~auto_resource() throw();
00285
00286
00287 auto_resource& operator=(const clear_type*) throw();
00288
00289
00290 pointer_type get() const throw();
00291 pointer_type release() throw();
00292 void reset(pointer_type p = 0) throw();
00293
00294
00295 operator bool () const throw() { return (pointer_m != NULL); }
00296 bool operator!() const throw();
00297
00298 private:
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309 #ifndef BOOST_MSVC
00310 template <typename Y> struct error_on_const_auto_type;
00311 template <typename Y> struct error_on_const_auto_type<auto_resource<Y, typename traits_type::template rebind<Y>::other> const>
00312 { typedef typename auto_resource<Y, typename traits_type::template rebind<Y>::other>::const_auto_type_is_not_allowed type; };
00313
00314 template <class Y>
00315 auto_resource(Y& rhs, typename error_on_const_auto_type<Y>::type = 0);
00316 #endif
00317 pointer_type pointer_m;
00318 };
00319
00320
00321
00380 template<typename X, class Traits = ptr_traits<X*> >
00381 class auto_ptr : public auto_resource<X*, Traits>
00382 {
00383 typedef auto_resource<X*, Traits> inherited;
00384 struct clear_type { };
00385
00386 public:
00387 typedef Traits traits_type;
00388 typedef typename traits_type::element_type element_type;
00389 typedef typename traits_type::pointer_type pointer_type;
00390
00391 explicit auto_ptr(pointer_type p = 0) throw();
00392
00393 auto_ptr(auto_ptr&) throw();
00394 template <typename Y> auto_ptr(const auto_ptr<Y, typename traits_type::template rebind<Y*>::other>&) throw();
00395
00396 auto_ptr& operator=(auto_ptr&) throw();
00397 template<typename Y> auto_ptr& operator=(auto_ptr<Y, typename traits_type::template rebind<Y*>::other>) throw();
00398
00399
00400 auto_ptr& operator=(const clear_type*) throw();
00401
00402
00403 auto_ptr(std::auto_ptr<X> r) throw();
00404 template <typename Y> auto_ptr(std::auto_ptr<Y> r) throw();
00405
00406 auto_ptr& operator=(std::auto_ptr<X>) throw();
00407 template<typename Y> auto_ptr& operator=(std::auto_ptr<Y>) throw();
00408
00409 operator std::auto_ptr<X> () throw() { return std::auto_ptr<X>(inherited::release()); }
00410
00411
00412 element_type& operator * () const throw();
00413 pointer_type operator -> () const throw();
00414 element_type& operator [] (std::size_t index) const throw();
00415
00416 private:
00417 template <typename Y> struct error_on_const_auto_type;
00418 template <typename Y> struct error_on_const_auto_type<auto_ptr<Y, typename traits_type::template rebind<Y*>::other> const>
00419 { typedef typename auto_ptr<Y, typename traits_type::template rebind<Y*>::other>::const_auto_type_is_not_allowed type; };
00420
00421 template <class U>
00422 auto_ptr(U& rhs, typename error_on_const_auto_type<U>::type = 0);
00423 };
00424
00426
00427
00428
00429 template <typename X, class Traits>
00430 inline auto_resource<X, Traits>::auto_resource(pointer_type p) throw() :
00431 pointer_m(p)
00432 { }
00433
00434 template <typename X, class Traits>
00435 inline auto_resource<X, Traits>::auto_resource(auto_resource& x) throw() :
00436 pointer_m(x.release())
00437 { }
00438
00439 template <typename X, class Traits>
00440 template <typename Y>
00441 inline auto_resource <X, Traits>::auto_resource(auto_resource<Y, typename traits_type::template rebind<Y>::other> const& x) throw() :
00442 pointer_m(const_cast<auto_resource<Y, typename traits_type::template rebind<Y>::other>&>(x).release())
00443 { }
00444
00445 template <typename X, class Traits>
00446 inline auto_resource<X, Traits>& auto_resource<X, Traits>::operator=(auto_resource& x) throw()
00447 {
00448 reset(x.release());
00449 return *this;
00450 }
00451
00452 template <typename X, class Traits>
00453 template <typename Y>
00454 inline auto_resource<X, Traits>& auto_resource<X, Traits>::operator=(
00455 auto_resource<Y, typename traits_type::template rebind<Y>::other> x) throw()
00456 {
00457 reset(x.release());
00458 return *this;
00459 }
00460
00461 template <typename X, class Traits>
00462 inline auto_resource<X, Traits>::~auto_resource() throw()
00463 { traits_type::delete_ptr(pointer_m); }
00464
00465
00466
00467 template <typename X, class Traits>
00468 inline auto_resource<X, Traits>& auto_resource<X, Traits>::operator=(const clear_type*) throw()
00469 {
00470 reset();
00471 return *this;
00472 }
00473
00474
00475
00476 template <typename X, class Traits>
00477 inline typename auto_resource<X, Traits>::pointer_type auto_resource<X, Traits>::get() const throw()
00478 {
00479 return pointer_m;
00480 }
00481
00482 template <typename X, class Traits>
00483 inline typename auto_resource<X, Traits>::pointer_type auto_resource<X, Traits>::release() throw()
00484 {
00485 pointer_type result(pointer_m);
00486 pointer_m = NULL;
00487 return result;
00488 }
00489
00490 template <typename X, class Traits>
00491 inline void auto_resource<X, Traits>::reset(pointer_type p) throw()
00492 {
00493 if (pointer_m != p)
00494 {
00495 traits_type::delete_ptr(pointer_m);
00496 pointer_m = p;
00497 }
00498 }
00499
00500
00501
00502 template <typename X, class Traits>
00503 inline bool auto_resource<X, Traits>::operator!() const throw()
00504 {
00505 return !pointer_m;
00506 }
00507
00508
00509
00510
00511 template <typename X, class Traits>
00512 inline auto_ptr<X, Traits>::auto_ptr(pointer_type p) throw() :
00513 inherited(p)
00514 { }
00515
00516 template <typename X, class Traits>
00517 inline auto_ptr<X, Traits>::auto_ptr(auto_ptr& r) throw() :
00518 inherited(r)
00519 { }
00520
00521 template <typename X, class Traits>
00522 template <typename Y>
00523 inline auto_ptr<X, Traits>::auto_ptr(const auto_ptr<Y, typename traits_type::template rebind<Y*>::other>& r) throw() :
00524 inherited(const_cast<auto_ptr<Y, typename traits_type::template rebind<Y*>::other>&>(r))
00525 { }
00526
00527 template <typename X, class Traits>
00528 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(auto_ptr& r) throw()
00529 {
00530 inherited::operator=(r);
00531 return *this;
00532 }
00533
00534 template <typename X, class Traits>
00535 template<typename Y>
00536 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(
00537 auto_ptr<Y, typename traits_type::template rebind<Y*>::other> r) throw()
00538 {
00539 inherited::operator=(r);
00540 return *this;
00541 }
00542
00543
00544
00545 template <typename X, class Traits>
00546 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(const clear_type*) throw()
00547 {
00548 inherited::reset();
00549 return *this;
00550 }
00551
00552
00553
00554 template <typename X, class Traits>
00555 inline auto_ptr<X, Traits>::auto_ptr(std::auto_ptr<X> r) throw() :
00556 inherited(r.release())
00557 { }
00558
00559 template <typename X, class Traits>
00560 template <typename Y>
00561 inline auto_ptr<X, Traits>::auto_ptr(std::auto_ptr<Y> r) throw() :
00562 inherited(r.release())
00563 { }
00564
00565 template <typename X, class Traits>
00566 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(std::auto_ptr<X> r) throw()
00567 {
00568 inherited::reset(r.release());
00569 return *this;
00570 }
00571
00572 template <typename X, class Traits>
00573 template<typename Y>
00574 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(
00575 std::auto_ptr<Y> r) throw()
00576 {
00577 inherited::reset(r.release());
00578 return *this;
00579 }
00580
00581
00582
00583 template <typename X, class Traits>
00584 inline typename auto_ptr<X, Traits>::element_type& auto_ptr<X, Traits>::operator * () const throw()
00585 {
00586 assert(!traits_type::empty_ptr(this->get()));
00587 return *this->get();
00588 }
00589
00590 template <typename X, class Traits>
00591 inline typename auto_ptr<X, Traits>::pointer_type auto_ptr<X, Traits>::operator -> () const throw()
00592 {
00593 assert(!traits_type::empty_ptr(this->get()));
00594 return this->get();
00595 }
00596
00597 template <typename X, class Traits>
00598 inline typename auto_ptr<X, Traits>::element_type& auto_ptr<X, Traits>::operator [] (std::size_t index) const throw()
00599 {
00600 implementation::adobe_static_assert<traits_type::is_array>();
00601
00602 assert(!traits_type::empty_ptr(this->get()));
00603 return *(this->get() + index);
00604 }
00605
00606
00607
00608 template <typename T>
00609 inline void destroy(T* p) { p->~T(); }
00610
00611 template <typename T>
00612 inline void construct(T* p) { ::new(static_cast<void*>(p)) T(); }
00613
00614 template <typename T>
00615 inline void construct(T* p, const T& x) { ::new(static_cast<void*>(p)) T(x); }
00616
00617 template <typename F>
00618 inline void destroy(F f, F l)
00619 {
00620 while (f != l) {
00621 destroy(&*f);
00622 ++f;
00623 }
00624 }
00625
00626 #if 0
00627 template <typename A>
00628 typename A::value_type* alloc_default(A& a)
00629 {
00630 typename A::value_type* result = a.allocate(1);
00631 try {
00632 construct(result);
00633 } catch (...) {
00634 a.deallocate(result, 1);
00635 throw;
00636 }
00637 return result;
00638 }
00639
00640 template <typename A>
00641 typename A::value_type* alloc_copy(A& a, const typename A::value_type& x)
00642 {
00643 typename A::value_type* result = a.allocate(1);
00644 try {
00645 construct(result, x);
00646 } catch (...) {
00647 a.deallocate(result, 1);
00648 throw;
00649 }
00650 return result;
00651 }
00652
00653 template <typename A>
00654 typename A::value_type* alloc_move(A& a, typename A::value_type x)
00655 {
00656 typename A::value_type* result = a.allocate(1);
00657 try {
00658 move_construct(result, x);
00659 } catch (...) {
00660 a.deallocate(result, 1);
00661 throw;
00662 }
00663 return result;
00664 }
00665 #endif
00666
00667
00668
00669 namespace version_1 {
00670
00673
00674 struct new_delete_t
00675 {
00676 void* (*new_)(std::size_t);
00677 void (*delete_)(void*);
00678 };
00679
00680 extern const new_delete_t local_new_delete_g;
00681
00682 template < >
00683 class capture_allocator<void>
00684 {
00685 public:
00686 void* pointer;
00687 typedef const void* const_pointer;
00688 typedef void value_type;
00689 template <class U> struct rebind { typedef capture_allocator<U> other; };
00690
00691 friend inline bool operator==(const capture_allocator&, const capture_allocator&)
00692 { return true; }
00693
00694 friend inline bool operator!=(const capture_allocator&, const capture_allocator&)
00695 { return false; }
00696 };
00697
00698 template <typename T>
00699 class capture_allocator
00700 {
00701 public:
00702 typedef std::size_t size_type;
00703 typedef std::ptrdiff_t difference_type;
00704 typedef T* pointer;
00705 typedef const T* const_pointer;
00706 typedef T& reference;
00707 typedef const T& const_reference;
00708 typedef T value_type;
00709 template <typename U> struct rebind { typedef capture_allocator<U> other; };
00710
00711 capture_allocator() : new_delete_m(&local_new_delete_g) { }
00712 template <typename U>
00713 capture_allocator(const capture_allocator<U>& x) : new_delete_m(x.new_delete()) { }
00714
00715 pointer address(reference x) const { return &x; }
00716 const_pointer address(const_reference x) const { return &x; }
00717 pointer allocate(size_type n, capture_allocator<void>::const_pointer = 0)
00718 {
00719 if (n > max_size()) throw std::bad_alloc();
00720 pointer result = static_cast<pointer>(new_delete_m->new_(n * sizeof(T)));
00721 if (!result) throw std::bad_alloc();
00722 return result;
00723 }
00724 void deallocate(pointer p, size_type)
00725 {
00726 new_delete_m->delete_(p);
00727 }
00728 size_type max_size() const { return size_type(-1) / sizeof(T); }
00729 void construct(pointer p, const T& x) { adobe::construct(p, x); }
00730 void destroy(pointer p) { adobe::destroy(p); }
00731
00732 friend inline bool operator==(const capture_allocator& x, const capture_allocator& y)
00733 { return x.new_delete_m == y.new_delete_m; }
00734
00735 friend inline bool operator!=(const capture_allocator& x, const capture_allocator& y)
00736 { return x.new_delete_m != y.new_delete_m; }
00737
00738 const new_delete_t* new_delete() const { return new_delete_m; }
00739
00740 private:
00741 const new_delete_t* new_delete_m;
00742 };
00743
00745
00746
00747 }
00748
00749
00750
00751
00752
00753
00754
00755
00758 template <typename T>
00759 struct aligned_storage
00760 {
00761 aligned_storage() { construct(&get()); }
00762
00763 template <typename U>
00764 explicit aligned_storage(const U& x, typename copy_sink<U, T>::type = 0)
00765 { construct(&get(), x); }
00766 template <typename U>
00767 explicit aligned_storage(U x, typename move_sink<U, T>::type = 0)
00768 { move_construct(&get(), x); }
00769
00770 ~aligned_storage() { destroy(&get()); }
00771
00772 aligned_storage(const aligned_storage& x) { construct(&get(), x.get()); }
00773 aligned_storage(move_from<aligned_storage> x) { move_construct(&get(), x.source.get()); }
00774
00775 aligned_storage& operator=(aligned_storage x) { swap(*this, x); return *this; }
00776
00777 T& get() { return *static_cast<T*>(storage()); }
00778 const T& get() const { return *static_cast<const T*>(storage()); }
00779
00780 friend inline void swap(aligned_storage& x, aligned_storage& y)
00781 { swap(x.get(), y.get()); }
00782
00783 private:
00784 enum { word_size = 16 };
00785
00786 typedef double storage_t[((sizeof(T) + (word_size - 1)) / word_size) * (word_size / sizeof(double))];
00787
00788 void* storage() { return &data_m; }
00789 const void* storage() const { return &data_m; }
00790 storage_t data_m;
00791
00792 BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(storage_t));
00793 };
00794
00796
00797
00798
00799 }
00800
00801 ADOBE_NAME_TYPE_1("capture_allocator:version_1:adobe", adobe::version_1::capture_allocator<T0>)
00802
00803
00804
00805 #endif
00806
00807