stlab.adobe.com Adobe Systems Incorporated
memory.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2005-2007 Adobe Systems Incorporated
3  Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
4  or a copy at http://stlab.adobe.com/licenses.html)
5 */
6 
7 /*************************************************************************************************/
8 
9 #ifndef ADOBE_MEMORY_HPP
10 #define ADOBE_MEMORY_HPP
11 
12 #include <adobe/config.hpp>
13 
14 #include <cassert>
15 #include <functional>
16 #include <memory>
17 
18 #include <boost/utility/enable_if.hpp>
19 #include <boost/type_traits/is_const.hpp>
20 
21 #include <adobe/conversion.hpp>
22 #include <adobe/functional.hpp>
23 #include <adobe/memory_fwd.hpp>
24 #include <adobe/move.hpp>
25 
26 /*************************************************************************************************/
27 
28 namespace adobe {
29 
30 /*************************************************************************************************/
31 
41 template <typename T>
42 struct empty_ptr;
43 
44 template <typename T>
45 struct empty_ptr<T*> : std::unary_function<T*, bool>
46 {
47  bool operator () (const T* x) const throw()
48  { return x == NULL; }
49 };
50 
51 
52 template <typename T>
53 struct empty_ptr<T(*)[]> : std::unary_function<T*, bool>
54 {
55  bool operator () (const T* x) const throw()
56  { return x == NULL; }
57 };
58 
59 /*
60  REVISIT (sparent) : This is a hack - the new delete_ptr is not a template
61  auto_ptr/auto_resource are too complicated with the traits classes -
62  provide a delete op as a tempalte argument?
63 */
64 
65 template <typename T>
66 struct delete_ptr_trait;
67 
68 template <typename T>
69 struct delete_ptr_trait<T*> : std::unary_function<T*, void>
70 { void operator()(const T* x) const { delete x; } };
71 
72 template <typename T>
73 struct delete_ptr_trait<T(*)[]> : std::unary_function<T*, void>
74 { void operator()(const T* x) const { delete [] x; } };
75 
77 
78 /*************************************************************************************************/
79 
80 template<typename X, class Traits> class auto_ptr;
81 template<typename X, class Traits> class auto_resource;
82 
83 template <typename ptrT>
84 struct ptr_traits;
85 
87 template <typename T>
88 struct ptr_traits<T(*)[]>
89 {
90  typedef T element_type;
91  typedef T* pointer_type;
92  typedef const T* const_pointer_type;
93 
94  template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
95  enum { is_array = true };
96 
97  static void delete_ptr(pointer_type x) throw() { delete_ptr_trait<T(*)[]>()(x); }
98  static bool empty_ptr(const_pointer_type x) throw() { return adobe::empty_ptr<T(*)[]>()(x); }
99 };
100 
162 template <typename T>
163 struct ptr_traits<T*>
164 {
165  typedef T element_type;
166  typedef T* pointer_type;
167  typedef const pointer_type const_pointer_type;
168 
169  template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
170  enum { is_array = false };
171 
172  static void delete_ptr(pointer_type x) throw() { adobe::delete_ptr_trait<T*>()(x); }
173  static bool empty_ptr(const_pointer_type x) throw() { return adobe::empty_ptr<T*>()(x); }
174 };
175 
177 template <typename T>
178 struct ptr_traits<std::auto_ptr<T> >
179 {
180  typedef typename std::auto_ptr<T>::element_type element_type;
181  typedef std::auto_ptr<T> pointer_type;
182  typedef std::auto_ptr<const T> const_pointer_type;
183 
184  template <class U> struct rebind { typedef adobe::ptr_traits<U> other; };
185  enum { is_array = false };
186 };
187 
189 template <typename R, typename T>
190 struct runtime_cast_t<R, std::auto_ptr<T> > {
191  R operator()(std::auto_ptr<T>& x) const
192  {
193  typedef typename R::element_type* dest_type;
194  dest_type result = dynamic_cast<dest_type>(x.get());
195  if (result) x.release();
196  return R(result);
197  }
198 };
199 
201 template <typename T, class Traits>
202 struct ptr_traits<auto_ptr<T, Traits> >
203 {
207 
208  enum { is_array = Traits::is_array };
209 };
210 
212 template <typename R, typename T, typename Traits>
213 struct runtime_cast_t<R, auto_ptr<T, Traits> > {
215  {
216  typedef typename R::element_type* dest_type;
217  dest_type result = dynamic_cast<dest_type>(x.get());
218  if (result) x.release();
219  return R(result);
220  }
221 };
222 
224 template <typename T, class Traits>
225 struct ptr_traits<auto_resource<T, Traits> >
226 {
227  typedef typename Traits::element_type element_type;
230 
231  enum { is_array = Traits::is_array };
232 };
233 
235 template <typename R, typename T, typename Traits>
236 struct runtime_cast_t<R, auto_resource<T, Traits> > {
238  {
239  typedef typename R::element_type* dest_type;
240  dest_type result = dynamic_cast<dest_type>(x.get());
241  if (result) x.release();
242  return R(result);
243  }
244 };
245 
246 
247 /*************************************************************************************************/
248 
249 #ifndef NO_DOCUMENTATION
250 
251 /*
252  REVISIT (sparent) : This could use boost::static_assert but it doesn't seem worth adding a
253  boost dependency just for this case.
254 */
255 
256 namespace implementation {
257  template <bool x> struct adobe_static_assert;
258  template <> struct adobe_static_assert<true> { };
259 }
260 
261 #endif
262 
263 /*************************************************************************************************/
264 
281 template <typename X, class Traits = ptr_traits<X> >
283 {
284  struct clear_type { };
285  operator int() const;
286 
287  public:
288  typedef Traits traits_type;
289  typedef typename traits_type::element_type element_type;
290  typedef typename traits_type::pointer_type pointer_type;
291 
292  // 20.4.5.1 construct/copy/destroy:
293  explicit auto_resource(pointer_type p = 0) throw();
294 
295  auto_resource(auto_resource&) throw();
296  template <typename Y> auto_resource(const auto_resource<Y, typename traits_type::template rebind<Y>::other>&) throw();
297 
298  auto_resource& operator=(auto_resource&) throw();
299  template<typename Y> auto_resource& operator=(auto_resource<Y, typename traits_type::template rebind<Y>::other>) throw();
300 
301  ~auto_resource() throw();
302 
303  // assignment from NULL
304  auto_resource& operator=(const clear_type*) throw();
305 
306  // 20.4.5.2 members:
307  pointer_type get() const throw();
308  pointer_type release() throw();
309  void reset(pointer_type p = 0) throw();
310 
311  // Safe bool conversion (private int conversion prevents unsafe use)
312  operator bool () const throw() { return (pointer_m != NULL); }
313  bool operator!() const throw();
314 
315  private:
316  /*
317  20.4.5.3 conversions:
318 
319  NOTE (spraent) : As per the recommendations on standard issue 463 the conversion
320  operators through auto_ptr_ref have been removed in favor of using this conditional
321  enabled trick.
322 
323  http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#463
324  */
325 // VC 2003 internal compiler error workaround. Some misues of auto_resource will go undetected under MSVC until fixed.
326 #ifndef BOOST_MSVC
327  template <typename Y> struct error_on_const_auto_type;
328  template <typename Y> struct error_on_const_auto_type<auto_resource<Y, typename traits_type::template rebind<Y>::other> const>
329  { typedef typename auto_resource<Y, typename traits_type::template rebind<Y>::other>::const_auto_type_is_not_allowed type; };
330 
331  template <class Y>
332  auto_resource(Y& rhs, typename error_on_const_auto_type<Y>::type = 0);
333 #endif
334  pointer_type pointer_m;
335 };
336 
337 /*************************************************************************************************/
338 
397 template<typename X, class Traits = ptr_traits<X*> >
398 class auto_ptr : public auto_resource<X*, Traits>
399 {
401  struct clear_type { };
402 
403  public:
404  typedef Traits traits_type;
405  typedef typename traits_type::element_type element_type;
406  typedef typename traits_type::pointer_type pointer_type;
407  // 20.4.5.1 construct/copy/destroy:
408  explicit auto_ptr(pointer_type p = 0) throw();
409 
410  auto_ptr(auto_ptr&) throw();
411  template <typename Y> auto_ptr(const auto_ptr<Y, typename traits_type::template rebind<Y*>::other>&) throw();
412 
413  auto_ptr& operator=(auto_ptr&) throw();
414  template<typename Y> auto_ptr& operator=(auto_ptr<Y, typename traits_type::template rebind<Y*>::other>) throw();
415 
416  // assignment from NULL
417  auto_ptr& operator=(const clear_type*) throw();
418 
419  // additions for interop with std::auto_ptr
420  auto_ptr(std::auto_ptr<X> r) throw();
421  template <typename Y> auto_ptr(std::auto_ptr<Y> r) throw();
422 
423  auto_ptr& operator=(std::auto_ptr<X>) throw();
424  template<typename Y> auto_ptr& operator=(std::auto_ptr<Y>) throw();
425 
426  operator std::auto_ptr<X> () throw() { return std::auto_ptr<X>(inherited::release()); }
427 
428  // 20.4.5.2 members:
429  element_type& operator * () const throw();
430  pointer_type operator -> () const throw();
431  element_type& operator [] (std::size_t index) const throw(); // addition
432 
433  private:
434  template <typename Y> struct error_on_const_auto_type;
435  template <typename Y> struct error_on_const_auto_type<auto_ptr<Y, typename traits_type::template rebind<Y*>::other> const>
436  { typedef typename auto_ptr<Y, typename traits_type::template rebind<Y*>::other>::const_auto_type_is_not_allowed type; };
437 
438  template <class U>
439  auto_ptr(U& rhs, typename error_on_const_auto_type<U>::type = 0);
440 };
441 
443 
444 /*************************************************************************************************/
445 
446 template <typename X, class Traits>
447 inline auto_resource<X, Traits>::auto_resource(pointer_type p) throw() :
448  pointer_m(p)
449 { }
450 
451 template <typename X, class Traits>
453  pointer_m(x.release())
454 { }
455 
456 template <typename X, class Traits>
457 template <typename Y>
459  pointer_m(const_cast<auto_resource<Y, typename traits_type::template rebind<Y>::other>&>(x).release())
460 { }
461 
462 template <typename X, class Traits>
464 {
465  reset(x.release());
466  return *this;
467 }
468 
469 template <typename X, class Traits>
470 template <typename Y>
472  auto_resource<Y, typename traits_type::template rebind<Y>::other> x) throw()
473 {
474  reset(x.release());
475  return *this;
476 }
477 
478 template <typename X, class Traits>
480  { traits_type::delete_ptr(pointer_m); }
481 
482 /*************************************************************************************************/
483 
484 template <typename X, class Traits>
486 {
487  reset();
488  return *this;
489 }
490 
491 /*************************************************************************************************/
492 
493 template <typename X, class Traits>
495 {
496  return pointer_m;
497 }
498 
499 template <typename X, class Traits>
501 {
502  pointer_type result(pointer_m);
503  pointer_m = NULL;
504  return result;
505 }
506 
507 template <typename X, class Traits>
508 inline void auto_resource<X, Traits>::reset(pointer_type p) throw()
509 {
510  if (pointer_m != p)
511  {
512  traits_type::delete_ptr(pointer_m);
513  pointer_m = p;
514  }
515 }
516 
517 /*************************************************************************************************/
518 
519 template <typename X, class Traits>
520 inline bool auto_resource<X, Traits>::operator!() const throw()
521 {
522  return !pointer_m;
523 }
524 
525 /*************************************************************************************************/
526 
527 
528 template <typename X, class Traits>
529 inline auto_ptr<X, Traits>::auto_ptr(pointer_type p) throw() :
530  inherited(p)
531 { }
532 
533 template <typename X, class Traits>
535  inherited(r)
536 { }
537 
538 template <typename X, class Traits>
539 template <typename Y>
540 inline auto_ptr<X, Traits>::auto_ptr(const auto_ptr<Y, typename traits_type::template rebind<Y*>::other>& r) throw() :
541  inherited(const_cast<auto_ptr<Y, typename traits_type::template rebind<Y*>::other>&>(r))
542 { }
543 
544 template <typename X, class Traits>
546 {
547  inherited::operator=(r);
548  return *this;
549 }
550 
551 template <typename X, class Traits>
552 template<typename Y>
554  auto_ptr<Y, typename traits_type::template rebind<Y*>::other> r) throw()
555 {
556  inherited::operator=(r);
557  return *this;
558 }
559 
560 /*************************************************************************************************/
561 
562 template <typename X, class Traits>
563 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(const clear_type*) throw()
564 {
565  inherited::reset();
566  return *this;
567 }
568 
569 /*************************************************************************************************/
570 
571 template <typename X, class Traits>
572 inline auto_ptr<X, Traits>::auto_ptr(std::auto_ptr<X> r) throw() :
573  inherited(r.release())
574 { }
575 
576 template <typename X, class Traits>
577 template <typename Y>
578 inline auto_ptr<X, Traits>::auto_ptr(std::auto_ptr<Y> r) throw() :
579  inherited(r.release())
580 { }
581 
582 template <typename X, class Traits>
583 inline auto_ptr<X, Traits>& auto_ptr<X, Traits>::operator=(std::auto_ptr<X> r) throw()
584 {
585  inherited::reset(r.release());
586  return *this;
587 }
588 
589 template <typename X, class Traits>
590 template<typename Y>
592  std::auto_ptr<Y> r) throw()
593 {
594  inherited::reset(r.release());
595  return *this;
596 }
597 
598 /*************************************************************************************************/
599 
600 template <typename X, class Traits>
602 {
603  assert(!traits_type::empty_ptr(this->get()));
604  return *this->get();
605 }
606 
607 template <typename X, class Traits>
609 {
610  assert(!traits_type::empty_ptr(this->get()));
611  return this->get();
612 }
613 
614 template <typename X, class Traits>
615 inline typename auto_ptr<X, Traits>::element_type& auto_ptr<X, Traits>::operator [] (std::size_t index) const throw()
616 {
617 implementation::adobe_static_assert<traits_type::is_array>();
618 
619 assert(!traits_type::empty_ptr(this->get()));
620 return *(this->get() + index);
621 }
622 
623 /*************************************************************************************************/
624 
625 template <typename T> // T models Regular
626 inline void destroy(T* p) { p->~T(); }
627 
628 template <typename T> // T models Regular
629 inline void construct(T* p) { ::new(static_cast<void*>(p)) T(); }
630 
631 template <typename T> // T models Regular
632 inline void construct(T* p, T x) { ::new(static_cast<void*>(p)) T(adobe::move(x)); }
633 
634 template <typename F> // F models ForwardIterator
635 inline void destroy(F f, F l)
636 {
637  while (f != l) {
638  destroy(&*f);
639  ++f;
640  }
641 }
642 
643 /*************************************************************************************************/
644 
648 template <typename I, // I models InputIterator
649  typename F> // F models ForwardIterator
650 F uninitialized_move(I f, I l, F r)
651 {
652  while (f != l) {
653  construct(&*r, adobe::move(*f));
654  ++f; ++r;
655  }
656  return r;
657 }
658 
659 /*************************************************************************************************/
660 
661 namespace version_1 {
662 
665 
667 {
668  void* (*new_)(std::size_t);
669  void (*delete_)(void*);
670 };
671 
672 extern const new_delete_t local_new_delete_g;
673 
674 template < >
675 class capture_allocator<void>
676 {
677  public:
678  void* pointer;
679  typedef const void* const_pointer;
680  typedef void value_type;
681  template <class U> struct rebind { typedef capture_allocator<U> other; };
682 
683  friend inline bool operator==(const capture_allocator&, const capture_allocator&)
684  { return true; }
685 
686  friend inline bool operator!=(const capture_allocator&, const capture_allocator&)
687  { return false; }
688 };
689 
690 template <typename T>
692 {
693  public:
694  typedef std::size_t size_type;
695  typedef std::ptrdiff_t difference_type;
696  typedef T* pointer;
697  typedef const T* const_pointer;
698  typedef T& reference;
699  typedef const T& const_reference;
700  typedef T value_type;
701  template <typename U> struct rebind { typedef capture_allocator<U> other; };
702 
703  capture_allocator() : new_delete_m(&local_new_delete_g) { }
704  template <typename U>
705  capture_allocator(const capture_allocator<U>& x) : new_delete_m(x.new_delete()) { }
706 
707  pointer address(reference x) const { return &x; }
708  const_pointer address(const_reference x) const { return &x; }
710  {
711  if (n > max_size()) throw std::bad_alloc();
712  pointer result = static_cast<pointer>(new_delete_m->new_(n * sizeof(T)));
713  if (!result) throw std::bad_alloc();
714  return result;
715  }
717  {
718  new_delete_m->delete_(p);
719  }
720  size_type max_size() const { return size_type(-1) / sizeof(T); }
721  void construct(pointer p, const T& x) { adobe::construct(p, x); }
723 
724  friend inline bool operator==(const capture_allocator& x, const capture_allocator& y)
725  { return x.new_delete_m == y.new_delete_m; }
726 
727  friend inline bool operator!=(const capture_allocator& x, const capture_allocator& y)
728  { return x.new_delete_m != y.new_delete_m; }
729 
730  const new_delete_t* new_delete() const { return new_delete_m; }
731 
732  private:
733  const new_delete_t* new_delete_m;
734 };
735 
737 /*************************************************************************************************/
738 
739 } // namespace version_1
740 
741 /*************************************************************************************************/
742 
743 /*
744  Note (sparent) : The aligned storage class is intended to pad out an item of size_t such that
745  anything following it is aligned to the max alignement on the machine - in this case, quadword.
746 */
747 
750 template <typename T>
752 {
753  aligned_storage() { construct(&get()); }
754 
755  explicit aligned_storage(T x)
756  { construct(&get(), adobe::move(x)); }
757 
758  ~aligned_storage() { destroy(&get()); }
759 
760  aligned_storage(const aligned_storage& x) { construct(&get(), x.get()); }
762 
763  aligned_storage& operator=(aligned_storage x) { swap(*this, x); return *this; }
764 
765  T& get() { return *static_cast<T*>(storage()); }
766  const T& get() const { return *static_cast<const T*>(storage()); }
767 
768  friend inline void swap(aligned_storage& x, aligned_storage& y)
769  { swap(x.get(), y.get()); }
770 
771  private:
772  enum { word_size = 16 }; // quad word alignment
773 
774  typedef double storage_t[((sizeof(T) + (word_size - 1)) / word_size) * (word_size / sizeof(double))];
775 
776  void* storage() { return &data_m; }
777  const void* storage() const { return &data_m; }
778  storage_t data_m;
779 
780  BOOST_STATIC_ASSERT(sizeof(T) <= sizeof(storage_t));
781 };
782 
784 
785 /*************************************************************************************************/
786 
787 } // namespace adobe
788 
789 ADOBE_NAME_TYPE_1("capture_allocator:version_1:adobe", adobe::version_1::capture_allocator<T0>)
790 
791 /*************************************************************************************************/
792 
793 #endif
794 
795 /*************************************************************************************************/

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