stlab.adobe.com Adobe Systems Incorporated

memory.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
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 #include <adobe/move.hpp>
00025 
00026 /*************************************************************************************************/
00027 
00028 namespace adobe {
00029 
00030 /*************************************************************************************************/
00031 
00041 template <typename T>
00042 struct empty_ptr;
00043 
00044 template <typename T>
00045 struct empty_ptr<T*> : std::unary_function<T*, bool>
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*, bool>
00054 {
00055     bool operator () (const T* x) const throw()
00056     { return x == NULL; }
00057 };
00058 
00059 /*
00060     REVISIT (sparent) : This is a hack - the new delete_ptr is not a template
00061     auto_ptr/auto_resource are too complicated with the traits classes -
00062     provide a delete op as a tempalte argument?
00063 */
00064 
00065 template <typename T>
00066 struct delete_ptr_trait;
00067 
00068 template <typename T>
00069 struct delete_ptr_trait<T*> : std::unary_function<T*, void>
00070 { void operator()(const T* x) const { delete x; } };
00071 
00072 template <typename T>
00073 struct delete_ptr_trait<T(*)[]> : std::unary_function<T*, void>
00074 { void operator()(const T* x) const { delete [] x; } };
00075 
00077 
00078 /*************************************************************************************************/
00079 
00080 template<typename X, class Traits> class auto_ptr;
00081 template<typename X, class Traits> class auto_resource;
00082 
00083 template <typename ptrT>
00084 struct ptr_traits;
00085 
00087 template <typename T>
00088 struct ptr_traits<T(*)[]>
00089 {
00090     typedef T           element_type;
00091     typedef T*          pointer_type;
00092     typedef const T*    const_pointer_type;
00093 
00094     template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
00095     enum { is_array = true };
00096     
00097     static void delete_ptr(pointer_type x) throw() { delete_ptr_trait<T(*)[]>()(x); }
00098     static bool empty_ptr(const_pointer_type x) throw() { return adobe::empty_ptr<T(*)[]>()(x); }
00099 };
00100 
00162 template <typename T>
00163 struct ptr_traits<T*>
00164 {
00165     typedef T           element_type;
00166     typedef T*          pointer_type;
00167     typedef const pointer_type  const_pointer_type;
00168     
00169     template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
00170     enum { is_array = false };
00171 
00172     static void delete_ptr(pointer_type x) throw() { adobe::delete_ptr_trait<T*>()(x); }
00173     static bool empty_ptr(const_pointer_type x) throw() { return adobe::empty_ptr<T*>()(x); }
00174 };
00175     
00177 template <typename T>
00178 struct ptr_traits<std::auto_ptr<T> >
00179 {
00180     typedef typename std::auto_ptr<T>::element_type element_type;
00181     typedef std::auto_ptr<T>                        pointer_type;
00182     typedef std::auto_ptr<const T>                  const_pointer_type;
00183     
00184     template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
00185     enum { is_array = false };
00186 };
00187 
00189 template <typename R, typename T>
00190 struct runtime_cast_t<R, std::auto_ptr<T> > {
00191     R operator()(std::auto_ptr<T>& x) const
00192     {
00193         typedef typename R::element_type* dest_type;
00194         dest_type result = dynamic_cast<dest_type>(x.get());
00195         if (result) x.release();
00196         return R(result);
00197     }
00198 };
00199     
00201 template <typename T, class Traits>
00202 struct ptr_traits<auto_ptr<T, Traits> >
00203 {
00204     typedef typename auto_ptr<T, Traits>::element_type   element_type;
00205     typedef auto_ptr<T, Traits>                          pointer_type;
00206     typedef auto_ptr<const T, Traits>                    const_pointer_type;
00207     
00208     enum { is_array = Traits::is_array };
00209 };
00210 
00212 template <typename R, typename T, typename Traits>
00213 struct runtime_cast_t<R, auto_ptr<T, Traits> > {
00214     R operator()(auto_ptr<T, Traits>& x) const
00215     {
00216         typedef typename R::element_type* dest_type;
00217         dest_type result = dynamic_cast<dest_type>(x.get());
00218         if (result) x.release();
00219         return R(result);
00220     }
00221 };
00222     
00224 template <typename T, class Traits>
00225 struct ptr_traits<auto_resource<T, Traits> >
00226 {
00227     typedef typename Traits::element_type           element_type;
00228     typedef auto_resource<T, Traits>         pointer_type;
00229     typedef auto_resource<const T, Traits>   const_pointer_type;
00230     
00231     enum { is_array = Traits::is_array };
00232 };
00233 
00235 template <typename R, typename T, typename Traits>
00236 struct runtime_cast_t<R, auto_resource<T, Traits> > {
00237     R operator()(auto_resource<T, Traits>& x) const
00238     {
00239         typedef typename R::element_type* dest_type;
00240         dest_type result = dynamic_cast<dest_type>(x.get());
00241         if (result) x.release();
00242         return R(result);
00243     }
00244 };
00245 
00246 
00247 /*************************************************************************************************/
00248 
00249 #ifndef NO_DOCUMENTATION
00250     
00251 /*
00252     REVISIT (sparent) : This could use boost::static_assert but it doesn't seem worth adding a
00253     boost dependency just for this case.
00254 */
00255 
00256 namespace implementation {
00257     template <bool x> struct adobe_static_assert;
00258     template <> struct adobe_static_assert<true> { };
00259 }
00260 
00261 #endif
00262 
00263 /*************************************************************************************************/
00264 
00281 template <typename X, class Traits = ptr_traits<X> >
00282 class auto_resource
00283 {
00284     struct clear_type { };
00285     operator int() const;
00286 
00287  public:
00288     typedef Traits                              traits_type;
00289     typedef typename traits_type::element_type  element_type;
00290     typedef typename traits_type::pointer_type  pointer_type;
00291     
00292     // 20.4.5.1 construct/copy/destroy:
00293     explicit auto_resource(pointer_type p = 0) throw();
00294                         
00295     auto_resource(auto_resource&) throw();
00296     template <typename Y> auto_resource(const auto_resource<Y, typename traits_type::template rebind<Y>::other>&) throw();
00297     
00298     auto_resource& operator=(auto_resource&) throw();
00299     template<typename Y> auto_resource& operator=(auto_resource<Y, typename traits_type::template rebind<Y>::other>) throw();
00300     
00301     ~auto_resource() throw();
00302     
00303     // assignment from NULL
00304     auto_resource& operator=(const clear_type*) throw();
00305     
00306     // 20.4.5.2 members:        
00307     pointer_type get() const throw();
00308     pointer_type release() throw();
00309     void reset(pointer_type p = 0) throw();
00310     
00311     // Safe bool conversion (private int conversion prevents unsafe use)
00312     operator bool () const throw() { return (pointer_m != NULL); }
00313     bool operator!() const throw();
00314     
00315  private:
00316     /*
00317         20.4.5.3 conversions:
00318     
00319         NOTE (spraent) : As per the recommendations on standard issue 463 the conversion
00320         operators through auto_ptr_ref have been removed in favor of using this conditional
00321         enabled trick.
00322     
00323         http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463
00324     */ 
00325 // VC 2003 internal compiler error workaround. Some misues of auto_resource will go undetected under MSVC until fixed.
00326 #ifndef BOOST_MSVC 
00327   template <typename Y> struct error_on_const_auto_type;
00328     template <typename Y> struct error_on_const_auto_type<auto_resource<Y, typename traits_type::template rebind<Y>::other> const>
00329     { typedef typename auto_resource<Y, typename traits_type::template rebind<Y>::other>::const_auto_type_is_not_allowed type; };
00330     
00331     template <class Y>
00332     auto_resource(Y& rhs, typename error_on_const_auto_type<Y>::type = 0);
00333 #endif
00334     pointer_type pointer_m;
00335 };
00336 
00337 /*************************************************************************************************/
00338 
00397 template<typename X, class Traits = ptr_traits<X*> >
00398 class auto_ptr : public auto_resource<X*, Traits>
00399 {
00400     typedef auto_resource<X*, Traits> inherited;
00401     struct clear_type { };
00402     
00403  public:
00404     typedef Traits                                              traits_type;
00405     typedef typename traits_type::element_type                  element_type;
00406     typedef typename traits_type::pointer_type                  pointer_type;
00407     // 20.4.5.1 construct/copy/destroy:
00408     explicit auto_ptr(pointer_type p = 0) throw();
00409                         
00410     auto_ptr(auto_ptr&) throw();
00411     template <typename Y> auto_ptr(const auto_ptr<Y, typename traits_type::template rebind<Y*>::other>&) throw();
00412     
00413     auto_ptr& operator=(auto_ptr&) throw();
00414     template<typename Y> auto_ptr& operator=(auto_ptr<Y, typename traits_type::template rebind<Y*>::other>) throw();
00415     
00416     // assignment from NULL
00417     auto_ptr& operator=(const clear_type*) throw();
00418     
00419     // additions for interop with std::auto_ptr                 
00420     auto_ptr(std::auto_ptr<X> r) throw();
00421     template <typename Y> auto_ptr(std::auto_ptr<Y> r) throw();
00422     
00423     auto_ptr& operator=(std::auto_ptr<X>) throw();
00424     template<typename Y> auto_ptr& operator=(std::auto_ptr<Y>) throw();
00425     
00426     operator std::auto_ptr<X> () throw() { return std::auto_ptr<X>(inherited::release()); }
00427         
00428     // 20.4.5.2 members:
00429     element_type& operator * () const throw();
00430     pointer_type operator -> () const throw();
00431     element_type& operator [] (std::size_t index) const throw(); // addition
00432             
00433  private:
00434     template <typename Y> struct error_on_const_auto_type;
00435     template <typename Y> struct error_on_const_auto_type<auto_ptr<Y, typename traits_type::template rebind<Y*>::other> const>
00436     { typedef typename auto_ptr<Y, typename traits_type::template rebind<Y*>::other>::const_auto_type_is_not_allowed type; };
00437     
00438     template <class U>
00439     auto_ptr(U& rhs, typename error_on_const_auto_type<U>::type = 0);
00440 };
00441 
00443 
00444 /*************************************************************************************************/
00445 
00446 template <typename X, class Traits>
00447 inline auto_resource<X, Traits>::auto_resource(pointer_type p) throw() :
00448     pointer_m(p)
00449 { }
00450 
00451 template <typename X, class Traits>
00452 inline auto_resource<X, Traits>::auto_resource(auto_resource& x) throw() :
00453     pointer_m(x.release())
00454 { }
00455 
00456 template <typename X, class Traits>
00457 template <typename Y>
00458 inline auto_resource <X, Traits>::auto_resource(auto_resource<Y, typename traits_type::template rebind<Y>::other> const& x) throw() :
00459     pointer_m(const_cast<auto_resource<Y, typename traits_type::template rebind<Y>::other>&>(x).release())
00460 { }
00461 
00462 template <typename X, class Traits>
00463 inline auto_resource<X, Traits>& auto_resource<X, Traits>::operator=(auto_resource& x) throw()
00464 {
00465     reset(x.release());
00466     return *this;
00467 }
00468 
00469 template <typename X, class Traits>
00470 template <typename Y>
00471 inline auto_resource<X, Traits>& auto_resource<X, Traits>::operator=(
00472         auto_resource<Y, typename traits_type::template rebind<Y>::other> x) throw()
00473 {
00474     reset(x.release());
00475     return *this;
00476 }
00477 
00478 template <typename X, class Traits>
00479 inline auto_resource<X, Traits>::~auto_resource() throw()
00480     { traits_type::delete_ptr(pointer_m); }
00481 
00482 /*************************************************************************************************/
00483 
00484 template <typename X, class Traits>
00485 inline auto_resource<X, Traits>& auto_resource<X, Traits>::operator=(const clear_type*) throw()
00486 {
00487     reset();
00488     return *this;
00489 }
00490 
00491 /*************************************************************************************************/
00492 
00493 template <typename X, class Traits>
00494 inline typename auto_resource<X, Traits>::pointer_type auto_resource<X, Traits>::get() const throw()
00495 {
00496     return pointer_m;
00497 }
00498 
00499 template <typename X, class Traits>
00500 inline typename auto_resource<X, Traits>::pointer_type auto_resource<X, Traits>::release() throw()
00501 {
00502     pointer_type result(pointer_m);
00503     pointer_m = NULL;
00504     return result;
00505 }
00506 
00507 template <typename X, class Traits>
00508 inline void auto_resource<X, Traits>::reset(pointer_type p) throw()
00509 {
00510     if (pointer_m != p)
00511     {
00512         traits_type::delete_ptr(pointer_m);
00513         pointer_m = p;
00514     }
00515 }
00516 
00517 /*************************************************************************************************/
00518 
00519 template <typename X, class Traits>
00520 inline bool auto_resource<X, Traits>::operator!() const throw()
00521 {
00522     return !pointer_m;
00523 }
00524 
00525 /*************************************************************************************************/
00526     
00527 
00528 template <typename X, class Traits>
00529 inline auto_ptr<X, Traits>::auto_ptr(pointer_type p) throw() :
00530     inherited(p)
00531 { }
00532 
00533 template <typename X, class Traits>                 
00534 inline auto_ptr<X, Traits>::auto_ptr(auto_ptr& r) throw() :
00535     inherited(r)
00536 { }
00537 
00538 template <typename X, class Traits>
00539 template <typename Y>
00540 inline auto_ptr<X, Traits>::auto_ptr(const auto_ptr<Y, typename traits_type::template rebind<Y*>::other>& r) throw() :
00541     inherited(const_cast<auto_ptr<Y, typename traits_type::template rebind<Y*>::other>&>(r))
00542 { }
00543 
00544 template <typename X, class Traits>
00545 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(auto_ptr& r) throw()
00546 {
00547     inherited::operator=(r);
00548     return *this;
00549 }
00550 
00551 template <typename X, class Traits>
00552 template<typename Y>
00553 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(
00554         auto_ptr<Y, typename traits_type::template rebind<Y*>::other> r) throw()
00555 {
00556     inherited::operator=(r);
00557     return *this;
00558 }
00559 
00560 /*************************************************************************************************/
00561 
00562 template <typename X, class Traits>
00563 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(const clear_type*) throw()
00564 {
00565     inherited::reset();
00566     return *this;
00567 }
00568 
00569 /*************************************************************************************************/
00570 
00571 template <typename X, class Traits>                 
00572 inline auto_ptr<X, Traits>::auto_ptr(std::auto_ptr<X> r) throw() :
00573     inherited(r.release())
00574 { }
00575 
00576 template <typename X, class Traits>
00577 template <typename Y>
00578 inline auto_ptr<X, Traits>::auto_ptr(std::auto_ptr<Y> r) throw() :
00579     inherited(r.release())
00580 { }
00581 
00582 template <typename X, class Traits>
00583 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(std::auto_ptr<X> r) throw()
00584 {
00585     inherited::reset(r.release());
00586     return *this;
00587 }
00588 
00589 template <typename X, class Traits>
00590 template<typename Y>
00591 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(
00592         std::auto_ptr<Y> r) throw()
00593 {
00594     inherited::reset(r.release());
00595     return *this;
00596 }
00597 
00598 /*************************************************************************************************/
00599 
00600 template <typename X, class Traits>
00601 inline typename auto_ptr<X, Traits>::element_type& auto_ptr<X, Traits>::operator * () const throw()
00602 {
00603     assert(!traits_type::empty_ptr(this->get()));
00604     return *this->get();
00605 }
00606 
00607 template <typename X, class Traits>
00608 inline typename auto_ptr<X, Traits>::pointer_type auto_ptr<X, Traits>::operator -> () const throw()
00609 {
00610     assert(!traits_type::empty_ptr(this->get()));
00611     return this->get();
00612 }
00613 
00614 template <typename X, class Traits>
00615 inline typename auto_ptr<X, Traits>::element_type& auto_ptr<X, Traits>::operator [] (std::size_t index) const throw()
00616 {
00617 implementation::adobe_static_assert<traits_type::is_array>();
00618 
00619 assert(!traits_type::empty_ptr(this->get()));
00620 return *(this->get() + index);
00621 }
00622 
00623 /*************************************************************************************************/
00624 
00625 template <typename T> // T models Regular
00626 inline void destroy(T* p) { p->~T(); }
00627 
00628 template <typename T> // T models Regular
00629 inline void construct(T* p) { ::new(static_cast<void*>(p)) T(); }
00630 
00631 template <typename T> // T models Regular
00632 inline void construct(T* p, T x) { ::new(static_cast<void*>(p)) T(adobe::move(x)); }
00633 
00634 template <typename F> // F models ForwardIterator
00635 inline void destroy(F f, F l)
00636 {
00637     while (f != l) {
00638         destroy(&*f);
00639         ++f;
00640     }
00641 }
00642 
00643 /*************************************************************************************************/
00644 
00648 template <typename I, // I models InputIterator
00649           typename F> // F models ForwardIterator
00650 F uninitialized_move(I f, I l, F r)
00651 {
00652     while (f != l) {
00653         construct(&*r, adobe::move(*f));
00654         ++f; ++r;
00655     }
00656     return r;
00657 }
00658 
00659 /*************************************************************************************************/
00660 
00661 namespace version_1 {
00662 
00665 
00666 struct new_delete_t
00667 {
00668     void* (*new_)(std::size_t);
00669     void (*delete_)(void*);
00670 };
00671 
00672 extern const new_delete_t local_new_delete_g;
00673 
00674 template < >
00675 class capture_allocator<void>
00676 {
00677   public:
00678     void*               pointer;
00679     typedef const void* const_pointer;
00680     typedef void        value_type;
00681     template <class U> struct rebind { typedef capture_allocator<U> other; };
00682 
00683     friend inline bool operator==(const capture_allocator&, const capture_allocator&)
00684     { return true; }
00685 
00686     friend inline bool operator!=(const capture_allocator&, const capture_allocator&)
00687     { return false; }
00688 };
00689 
00690 template <typename T>
00691 class capture_allocator
00692 {
00693  public:
00694     typedef std::size_t         size_type;
00695     typedef std::ptrdiff_t      difference_type;
00696     typedef T*                  pointer;
00697     typedef const T*            const_pointer;
00698     typedef T&                  reference;
00699     typedef const T&            const_reference;
00700     typedef T                   value_type;
00701     template <typename U> struct rebind { typedef capture_allocator<U> other; };
00702     
00703     capture_allocator() : new_delete_m(&local_new_delete_g) { }
00704     template <typename U>
00705     capture_allocator(const capture_allocator<U>& x) : new_delete_m(x.new_delete()) { }
00706     
00707     pointer address(reference x) const { return &x; }
00708     const_pointer address(const_reference x) const { return &x; }
00709     pointer allocate(size_type n, capture_allocator<void>::const_pointer = 0)
00710     {
00711         if (n > max_size()) throw std::bad_alloc();
00712         pointer result = static_cast<pointer>(new_delete_m->new_(n * sizeof(T)));
00713         if (!result) throw std::bad_alloc();
00714         return result;
00715     }
00716     void deallocate(pointer p, size_type)
00717     {
00718         new_delete_m->delete_(p);
00719     }
00720     size_type max_size() const { return size_type(-1) / sizeof(T); }
00721     void construct(pointer p, const T& x) { adobe::construct(p, x); }
00722     void destroy(pointer p) { adobe::destroy(p); }
00723 
00724     friend inline bool operator==(const capture_allocator& x, const capture_allocator& y)
00725     { return x.new_delete_m == y.new_delete_m; }
00726 
00727     friend inline bool operator!=(const capture_allocator& x, const capture_allocator& y)
00728     { return x.new_delete_m != y.new_delete_m; }
00729 
00730     const new_delete_t* new_delete() const { return new_delete_m; }
00731 
00732  private:
00733     const new_delete_t* new_delete_m;
00734 };
00735 
00737 /*************************************************************************************************/
00738 
00739 } // namespace version_1
00740 
00741 /*************************************************************************************************/
00742 
00743 /*
00744     Note (sparent) : The aligned storage class is intended to pad out an item of size_t such that 
00745     anything following it is aligned to the max alignement on the machine - in this case, quadword.
00746 */
00747     
00750 template <typename T>
00751 struct aligned_storage
00752 {
00753     aligned_storage() { construct(&get()); }
00754     
00755     explicit aligned_storage(T x)
00756         { construct(&get(), adobe::move(x)); }
00757         
00758     ~aligned_storage() { destroy(&get()); }
00759     
00760     aligned_storage(const aligned_storage& x) { construct(&get(), x.get()); }
00761     aligned_storage(move_from<aligned_storage> x) { construct(&get(), adobe::move(x.source.get())); }
00762     
00763     aligned_storage& operator=(aligned_storage x) { swap(*this, x); return *this; }
00764         
00765     T& get() { return *static_cast<T*>(storage()); }
00766     const T& get() const { return *static_cast<const T*>(storage()); }
00767     
00768     friend inline void swap(aligned_storage& x, aligned_storage& y)
00769     { swap(x.get(), y.get()); }
00770     
00771  private:
00772     enum { word_size = 16 }; // quad word alignment
00773     
00774     typedef double storage_t[((sizeof(T) + (word_size - 1)) / word_size) * (word_size / sizeof(double))];
00775     
00776     void* storage() { return &data_m; }
00777     const void* storage() const { return &data_m; }
00778     storage_t data_m;
00779     
00780     BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(storage_t));
00781 };
00782 
00784 
00785 /*************************************************************************************************/
00786 
00787 } // namespace adobe
00788 
00789 ADOBE_NAME_TYPE_1("capture_allocator:version_1:adobe", adobe::version_1::capture_allocator<T0>)
00790 
00791 /*************************************************************************************************/
00792 
00793 #endif
00794 
00795 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google