// Copyright (c) 2021 Marshall A. Greenblatt. Portions copyright (c) 2013 // Google Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the name Chromium Embedded // Framework nor the names of its contributors may be used to endorse // or promote products derived from this software without specific prior // written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ScopedTypeRef<> is patterned after std::unique_ptr<>, but maintains 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 { // static CGLContextObj InvalidValue() { return nullptr; } // static CGLContextObj Retain(CGLContextObj object) { // CGLContextRetain(object); // return object; // } // static 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 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|. #ifndef CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_ #define CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_ #pragma once #if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. #include "base/mac/scoped_typeref.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. #include "include/base/cef_compiler_specific.h" #include "include/base/cef_logging.h" #include "include/base/internal/cef_scoped_policy.h" namespace base { template struct ScopedTypeRefTraits; template> class ScopedTypeRef { public: using element_type = T; explicit constexpr ScopedTypeRef( element_type object = Traits::InvalidValue(), base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) : object_(object) { if (object_ && policy == base::scoped_policy::RETAIN) object_ = Traits::Retain(object_); } ScopedTypeRef(const ScopedTypeRef& that) : object_(that.object_) { if (object_) object_ = Traits::Retain(object_); } // This allows passing an object to a function that takes its superclass. template explicit ScopedTypeRef(const ScopedTypeRef& that_as_subclass) : object_(that_as_subclass.get()) { if (object_) object_ = Traits::Retain(object_); } ScopedTypeRef(ScopedTypeRef&& that) : object_(that.object_) { that.object_ = Traits::InvalidValue(); } ~ScopedTypeRef() { if (object_) Traits::Release(object_); } ScopedTypeRef& operator=(const ScopedTypeRef& 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. element_type* InitializeInto() WARN_UNUSED_RESULT { DCHECK(!object_); return &object_; } void reset(const ScopedTypeRef& that) { reset(that.get(), base::scoped_policy::RETAIN); } void reset(element_type object = Traits::InvalidValue(), base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) { if (object && policy == base::scoped_policy::RETAIN) object = Traits::Retain(object); if (object_) Traits::Release(object_); object_ = object; } bool operator==(const element_type& that) const { return object_ == that; } bool operator!=(const element_type& that) const { return object_ != that; } operator element_type() const { return object_; } element_type get() const { return object_; } void swap(ScopedTypeRef& that) { element_type temp = that.object_; that.object_ = object_; object_ = temp; } // ScopedTypeRef<>::release() is like std::unique_ptr<>::release. It is NOT // a wrapper for Release(). To force a ScopedTypeRef<> object to call // Release(), use ScopedTypeRef<>::reset(). element_type release() WARN_UNUSED_RESULT { element_type temp = object_; object_ = Traits::InvalidValue(); return temp; } private: element_type object_; }; } // namespace base #endif // !USING_CHROMIUM_INCLUDES #endif // CEF_INCLUDE_BASE_CEF_SCOPED_TYPEREF_MAC_H_