|  | // 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 patterned after scoped_ptr<>, but maintains a ownership | 
|  | // 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 the many types that have pass-by-pointer create functions, the function | 
|  | // InitializeInto() 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.InitializeInto()); | 
|  | // | 
|  | // 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|. | 
|  |  | 
|  | template<typename T> | 
|  | struct ScopedTypeRefTraits; | 
|  |  | 
|  | template<typename T, typename Traits = ScopedTypeRefTraits<T>> | 
|  | 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_); | 
|  | } | 
|  |  | 
|  | ~ScopedTypeRef() { | 
|  | 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 | 
|  | // by pass-by-pointer create functions. To enforce this, require that the | 
|  | // object be reset to NULL before this may be used. | 
|  | T* InitializeInto() 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_ |