summaryrefslogtreecommitdiff
path: root/include/base/cef_scoped_typeref_mac.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/base/cef_scoped_typeref_mac.h')
-rw-r--r--include/base/cef_scoped_typeref_mac.h190
1 files changed, 190 insertions, 0 deletions
diff --git a/include/base/cef_scoped_typeref_mac.h b/include/base/cef_scoped_typeref_mac.h
new file mode 100644
index 00000000..65d16a1c
--- /dev/null
+++ b/include/base/cef_scoped_typeref_mac.h
@@ -0,0 +1,190 @@
+// 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.
+
+#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_logging.h"
+#include "include/base/internal/cef_scoped_policy.h"
+
+namespace base {
+
+template <typename T>
+struct ScopedTypeRefTraits;
+
+///
+/// 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:
+///
+/// <pre>
+/// template<>
+/// struct ScopedTypeRefTraits<CGLContextObj> {
+/// static CGLContextObj InvalidValue() { return nullptr; }
+/// static CGLContextObj Retain(CGLContextObj object) {
+/// CGLContextRetain(object);
+/// return object;
+/// }
+/// static void Release(CGLContextObj object) { CGLContextRelease(object); }
+/// };
+/// </pre>
+///
+/// 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:
+///
+/// <pre>
+/// base::ScopedTypeRef<CGLContextObj> context;
+/// CGLCreateContext(pixel_format, share_group, context.InitializeInto());
+/// </pre>
+///
+/// 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, typename Traits = ScopedTypeRefTraits<T>>
+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<T, Traits>& that) : object_(that.object_) {
+ if (object_) {
+ object_ = Traits::Retain(object_);
+ }
+ }
+
+ // This allows passing an object to a function that takes its superclass.
+ template <typename R, typename RTraits>
+ explicit ScopedTypeRef(const ScopedTypeRef<R, RTraits>& that_as_subclass)
+ : object_(that_as_subclass.get()) {
+ if (object_) {
+ object_ = Traits::Retain(object_);
+ }
+ }
+
+ ScopedTypeRef(ScopedTypeRef<T, Traits>&& that) : object_(that.object_) {
+ that.object_ = Traits::InvalidValue();
+ }
+
+ ~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.
+ [[nodiscard]] element_type* InitializeInto() {
+ DCHECK(!object_);
+ return &object_;
+ }
+
+ void reset(const ScopedTypeRef<T, Traits>& 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().
+ [[nodiscard]] element_type release() {
+ 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_