Home | History | Annotate | Download | only in mac
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_MAC_SCOPED_TYPEREF_H_
      6 #define BASE_MAC_SCOPED_TYPEREF_H_
      7 
      8 #include "base/basictypes.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/logging.h"
     11 #include "base/memory/scoped_policy.h"
     12 
     13 namespace base {
     14 
     15 // ScopedTypeRef<> is patterned after scoped_ptr<>, but maintains a ownership
     16 // of a reference to any type that is maintained by Retain and Release methods.
     17 //
     18 // The Traits structure must provide the Retain and Release methods for type T.
     19 // A default ScopedTypeRefTraits is used but not defined, and should be defined
     20 // for each type to use this interface. For example, an appropriate definition
     21 // of ScopedTypeRefTraits for CGLContextObj would be:
     22 //
     23 //   template<>
     24 //   struct ScopedTypeRefTraits<CGLContextObj> {
     25 //     void Retain(CGLContextObj object) { CGLContextRetain(object); }
     26 //     void Release(CGLContextObj object) { CGLContextRelease(object); }
     27 //   };
     28 //
     29 // For the many types that have pass-by-pointer create functions, the function
     30 // InitializeInto() is provided to allow direct initialization and assumption
     31 // of ownership of the object. For example, continuing to use the above
     32 // CGLContextObj specialization:
     33 //
     34 //   base::ScopedTypeRef<CGLContextObj> context;
     35 //   CGLCreateContext(pixel_format, share_group, context.InitializeInto());
     36 //
     37 // For initialization with an existing object, the caller may specify whether
     38 // the ScopedTypeRef<> being initialized is assuming the caller's existing
     39 // ownership of the object (and should not call Retain in initialization) or if
     40 // it should not assume this ownership and must create its own (by calling
     41 // Retain in initialization). This behavior is based on the |policy| parameter,
     42 // with |ASSUME| for the former and |RETAIN| for the latter. The default policy
     43 // is to |ASSUME|.
     44 
     45 template<typename T>
     46 struct ScopedTypeRefTraits;
     47 
     48 template<typename T, typename Traits = ScopedTypeRefTraits<T>>
     49 class ScopedTypeRef {
     50  public:
     51   typedef T element_type;
     52 
     53   ScopedTypeRef(
     54       T object = NULL,
     55       base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
     56       : object_(object) {
     57     if (object_ && policy == base::scoped_policy::RETAIN)
     58       Traits::Retain(object_);
     59   }
     60 
     61   ScopedTypeRef(const ScopedTypeRef<T, Traits>& that)
     62       : object_(that.object_) {
     63     if (object_)
     64       Traits::Retain(object_);
     65   }
     66 
     67   ~ScopedTypeRef() {
     68     if (object_)
     69       Traits::Release(object_);
     70   }
     71 
     72   ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) {
     73     reset(that.get(), base::scoped_policy::RETAIN);
     74     return *this;
     75   }
     76 
     77   // This is to be used only to take ownership of objects that are created
     78   // by pass-by-pointer create functions. To enforce this, require that the
     79   // object be reset to NULL before this may be used.
     80   T* InitializeInto() WARN_UNUSED_RESULT {
     81     DCHECK(!object_);
     82     return &object_;
     83   }
     84 
     85   void reset(T object = NULL,
     86              base::scoped_policy::OwnershipPolicy policy =
     87                 base::scoped_policy::ASSUME) {
     88     if (object && policy == base::scoped_policy::RETAIN)
     89       Traits::Retain(object);
     90     if (object_)
     91       Traits::Release(object_);
     92     object_ = object;
     93   }
     94 
     95   bool operator==(T that) const {
     96     return object_ == that;
     97   }
     98 
     99   bool operator!=(T that) const {
    100     return object_ != that;
    101   }
    102 
    103   operator T() const {
    104     return object_;
    105   }
    106 
    107   T get() const {
    108     return object_;
    109   }
    110 
    111   void swap(ScopedTypeRef& that) {
    112     T temp = that.object_;
    113     that.object_ = object_;
    114     object_ = temp;
    115   }
    116 
    117   // ScopedTypeRef<>::release() is like scoped_ptr<>::release.  It is NOT
    118   // a wrapper for Release().  To force a ScopedTypeRef<> object to call
    119   // Release(), use ScopedTypeRef<>::reset().
    120   T release() WARN_UNUSED_RESULT {
    121     T temp = object_;
    122     object_ = NULL;
    123     return temp;
    124   }
    125 
    126  private:
    127   T object_;
    128 };
    129 
    130 }  // namespace base
    131 
    132 #endif  // BASE_MAC_SCOPED_TYPEREF_H_
    133