• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
object_(object)56       : object_(object) {
57     if (object_ && policy == base::scoped_policy::RETAIN)
58       Traits::Retain(object_);
59   }
60 
ScopedTypeRef(const ScopedTypeRef<T,Traits> & that)61   ScopedTypeRef(const ScopedTypeRef<T, Traits>& that)
62       : object_(that.object_) {
63     if (object_)
64       Traits::Retain(object_);
65   }
66 
~ScopedTypeRef()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.
InitializeInto()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 
T()103   operator T() const {
104     return object_;
105   }
106 
get()107   T get() const {
108     return object_;
109   }
110 
swap(ScopedTypeRef & that)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().
release()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