Index: base/mac/scoped_typeref.h |
diff --git a/base/mac/scoped_typeref.h b/base/mac/scoped_typeref.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e3469189c781bf5be553f45c74386c034d703dbc |
--- /dev/null |
+++ b/base/mac/scoped_typeref.h |
@@ -0,0 +1,132 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef BASE_MAC_SCOPED_TYPEREF_H_ |
+#define BASE_MAC_SCOPED_TYPEREF_H_ |
+ |
+#include "base/basictypes.h" |
+#include "base/compiler_specific.h" |
+#include "base/logging.h" |
+#include "base/memory/scoped_policy.h" |
+ |
+namespace base { |
+ |
+// ScopedTypeRef<> is patterend after scoped_ptr<>, but maintains a ownership |
Avi (use Gerrit)
2014/02/07 19:29:31
s/patterend/patterned/
ccameron
2014/02/07 20:58:04
Done.
|
+// of a reference to any type that is maintained by Retain and Release methods. |
+// |
+// The Traits structure must provide the Retain and Release methods for type T. |
+// A default ScopedTypeRefTraits is used but not defined, and should be defined |
+// for each type to use this interface. For example, an appropriate definition |
+// of ScopedTypeRefTraits for CGLContextObj would be: |
+// |
+// template<> |
+// struct ScopedTypeRefTraits<CGLContextObj> { |
+// void Retain(CGLContextObj object) { CGLContextRetain(object); } |
+// void Release(CGLContextObj object) { CGLContextRelease(object); } |
+// }; |
+// |
+// For initialization with an existing object, the caller may specify whether |
+// the ScopedTypeRef<> being initialized is assuming the caller's existing |
+// ownership of the object (and should not call Retain in initialization) or if |
+// it should not assume this ownership and must create its own (by calling |
+// Retain in initialization). This behavior is based on the |policy| parameter, |
+// with |ASSUME| for the former and |RETAIN| for the latter. The default policy |
+// is to |ASSUME|. |
+// |
+// For the many types that have pass-by-pointer create functions, the function |
+// ptr_for_init() is provided to allow direct initialization and assumption of |
+// ownership of the object. For example, continuing to use the above |
+// CGLContextObj specialization: |
+// |
+// base::ScopedTypeRef<CGLContextObj> context; |
+// CGLCreateContext(pixel_format, share_group, context.ptr_for_init()); |
+ |
+template<typename T> |
+struct ScopedTypeRefTraits; |
+ |
+template<typename T, typename Traits = ScopedTypeRefTraits<T> > |
Mark Mentovai
2014/02/07 19:53:40
The >> spelling option should be available here to
ccameron
2014/02/07 20:58:04
Done.
|
+class ScopedTypeRef { |
+ public: |
+ typedef T element_type; |
+ |
+ ScopedTypeRef( |
+ T object = NULL, |
+ base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) |
+ : object_(object) { |
+ if (object_ && policy == base::scoped_policy::RETAIN) |
+ Traits::Retain(object_); |
+ } |
+ |
+ ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) |
+ : object_(that.object_) { |
+ if (object_) |
+ Traits::Retain(object_); |
+ } |
+ |
+ virtual ~ScopedTypeRef() { |
Mark Mentovai
2014/02/07 19:53:40
Why is this virtual?
ccameron
2014/02/07 20:58:04
Not required for correctness (existant subclass ha
|
+ if (object_) |
+ Traits::Release(object_); |
+ } |
+ |
+ ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) { |
+ reset(that.get(), base::scoped_policy::RETAIN); |
+ return *this; |
+ } |
+ |
+ // This is to be used only to take ownership of objects that are created |
Mark Mentovai
2014/02/07 19:53:41
I like this. Less cumbersome than the existing pat
ccameron
2014/02/07 20:58:04
Thanks -- Done.
|
+ // by pass-by-pointer create functions. To enforce this, require that the |
+ // object be reset to NULL before this may be used. |
+ T* ptr_for_init() WARN_UNUSED_RESULT { |
+ DCHECK(!object_); |
+ return &object_; |
+ } |
+ |
+ void reset(T object = NULL, |
+ base::scoped_policy::OwnershipPolicy policy = |
+ base::scoped_policy::ASSUME) { |
+ if (object && policy == base::scoped_policy::RETAIN) |
+ Traits::Retain(object); |
+ if (object_) |
+ Traits::Release(object_); |
+ object_ = object; |
+ } |
+ |
+ bool operator==(T that) const { |
+ return object_ == that; |
+ } |
+ |
+ bool operator!=(T that) const { |
+ return object_ != that; |
+ } |
+ |
+ operator T() const { |
+ return object_; |
+ } |
+ |
+ T get() const { |
+ return object_; |
+ } |
+ |
+ void swap(ScopedTypeRef& that) { |
+ T temp = that.object_; |
+ that.object_ = object_; |
+ object_ = temp; |
+ } |
+ |
+ // ScopedTypeRef<>::release() is like scoped_ptr<>::release. It is NOT |
+ // a wrapper for Release(). To force a ScopedTypeRef<> object to call |
+ // Release(), use ScopedTypeRef<>::reset(). |
+ T release() WARN_UNUSED_RESULT { |
+ T temp = object_; |
+ object_ = NULL; |
+ return temp; |
+ } |
+ |
+ private: |
+ T object_; |
+}; |
+ |
+} // namespace base |
+ |
+#endif // BASE_MAC_SCOPED_TYPEREF_H_ |