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 
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     REVISIT (sparent) : This could use boost::static_assert but it doesn't seem worth adding a
00236     boost dependency just for this case.
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     // 20.4.5.1 construct/copy/destroy:
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     // assignment from NULL
00287     auto_resource& operator=(const clear_type*) throw();
00288     
00289     // 20.4.5.2 members:        
00290     pointer_type get() const throw();
00291     pointer_type release() throw();
00292     void reset(pointer_type p = 0) throw();
00293     
00294     // Safe bool conversion (private int conversion prevents unsafe use)
00295     operator bool () const throw() { return (pointer_m != NULL); }
00296     bool operator!() const throw();
00297     
00298  private:
00299     /*
00300         20.4.5.3 conversions:
00301     
00302         NOTE (spraent) : As per the recommendations on standard issue 463 the conversion
00303         operators through auto_ptr_ref have been removed in favor of using this conditional
00304         enabled trick.
00305     
00306         http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463
00307     */ 
00308 // VC 2003 internal compiler error workaround. Some misues of auto_resource will go undetected under MSVC until fixed.
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     // 20.4.5.1 construct/copy/destroy:
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     // assignment from NULL
00400     auto_ptr& operator=(const clear_type*) throw();
00401     
00402     // additions for interop with std::auto_ptr                 
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     // 20.4.5.2 members:
00412     element_type& operator * () const throw();
00413     pointer_type operator -> () const throw();
00414     element_type& operator [] (std::size_t index) const throw(); // addition
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> // T models Regular
00609 inline void destroy(T* p) { p->~T(); }
00610 
00611 template <typename T> // T models Regular
00612 inline void construct(T* p) { ::new(static_cast<void*>(p)) T(); }
00613 
00614 template <typename T> // T models Regular
00615 inline void construct(T* p, const T& x) { ::new(static_cast<void*>(p)) T(x); }
00616 
00617 template <typename F> // F models ForwardIterator
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> // A models Allocator
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> // A models Allocator
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 } // namespace version_1
00748 
00749 /*************************************************************************************************/
00750 
00751 /*
00752     Note (sparent) : The aligned storage class is intended to pad out an item of size_t such that 
00753     anything following it is aligned to the max alignement on the machine - in this case, quadword.
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 }; // quad word alignment
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 } // namespace adobe
00800 
00801 ADOBE_NAME_TYPE_1("capture_allocator:version_1:adobe", adobe::version_1::capture_allocator<T0>)
00802 
00803 /*************************************************************************************************/
00804 
00805 #endif
00806 
00807 /*************************************************************************************************/

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