| /* |
| * Copyright (C) 2010 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 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 THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_PRIVATE_PTR_H_ |
| #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_PRIVATE_PTR_H_ |
| |
| #include "base/check.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "third_party/blink/renderer/platform/heap/cross_thread_persistent.h" // nogncheck |
| #include "third_party/blink/renderer/platform/heap/persistent.h" // nogncheck |
| #include "third_party/blink/renderer/platform/wtf/type_traits.h" // nogncheck |
| |
| #include <cstddef> |
| |
| namespace WTF { |
| template <class T, typename Traits> |
| class ThreadSafeRefCounted; |
| } |
| |
| namespace blink { |
| |
| // By default, the destruction of a WebPrivatePtrForGC and |
| // WebPrivatePtrForRefCounted must happen on the same thread that created it, |
| // but can optionally be allowed to happen on another thread. |
| enum class WebPrivatePtrDestruction { |
| kSameThread, |
| kCrossThread, |
| }; |
| |
| // The WebPrivatePtrForGC holds by default a strong reference to its Blink |
| // object, but Blink GC managed objects also support keeping a weak reference by |
| // way of WebPrivatePtrForGC. |
| enum class WebPrivatePtrStrength { |
| kNormal, |
| kWeak, |
| }; |
| |
| // WebPrivatePtrForRefCounted is an opaque reference to a Blink-internal class |
| // that can keep an object alive over the Blink API boundary. The object |
| // referred to must be reference counted. The pointer must be set and cleared |
| // from within Blink. Outside of Blink, WebPrivatePtrForRefCounted only allows |
| // constructing an empty reference and checking for an empty reference. |
| // |
| // A typical implementation of a class which uses WebPrivatePtrForRefCounted |
| // might look like this: |
| // |
| // // WebFoo.h |
| // class WebFoo { |
| // public: |
| // BLINK_EXPORT ~WebFoo(); |
| // WebFoo() = default; |
| // WebFoo(const WebFoo& other) { Assign(other); } |
| // WebFoo& operator=(const WebFoo& other) { |
| // Assign(other); |
| // return *this; |
| // } |
| // // Implemented in the .cc file as it requires full definition of Foo. |
| // BLINK_EXPORT void Assign(const WebFoo&); |
| // |
| // // Methods that are exposed to Chromium and which are specific to |
| // // WebFoo go here. |
| // BLINK_EXPORT DoWebFooThing(); |
| // |
| // // Methods that are used only by other Blink classes should only be |
| // // declared when INSIDE_BLINK is set. |
| // #if INSIDE_BLINK |
| // WebFoo(scoped_refptr<Foo>); |
| // #endif |
| // |
| // private: |
| // WebPrivatePtrForRefCounted<Foo> private_; |
| // }; |
| // |
| // // WebFoo.cpp |
| // WebFoo::~WebFoo() { private_.Reset(); } |
| // WebFoo::WebFoo() = default; |
| // WebFoo::WebFoo(const WebFoo& other) { Assign(other); } |
| // void WebFoo::Assign(const WebFoo& other) { ... } |
| // |
| template <typename T, |
| WebPrivatePtrDestruction PtrDestruction = |
| WebPrivatePtrDestruction::kSameThread> |
| class WebPrivatePtrForRefCounted final { |
| public: |
| WebPrivatePtrForRefCounted() = default; |
| |
| ~WebPrivatePtrForRefCounted() { |
| // We don't destruct the object pointed by storage_ here because we don't |
| // want to expose destructors of core classes to embedders which is the case |
| // for reference counted objects. The embedder should call Reset() manually |
| // in destructors of classes with WebPrivatePtrForRefCounted members. |
| CHECK(IsNull()); |
| } |
| |
| // Disable the copy constructor; classes that contain a |
| // WebPrivatePtrForRefCounted should implement their copy constructor using |
| // assign(). |
| WebPrivatePtrForRefCounted(const WebPrivatePtrForRefCounted&) = delete; |
| |
| bool IsNull() const { return !*reinterpret_cast<void* const*>(&storage_); } |
| |
| explicit operator bool() const { return !IsNull(); } |
| |
| #if INSIDE_BLINK |
| void Reset() { AsRefPtr().reset(); } |
| |
| T* Get() const { return AsRefPtr().get(); } |
| |
| T& operator*() const { |
| DCHECK(!IsNull()); |
| return *Get(); |
| } |
| |
| T* operator->() const { |
| DCHECK(!IsNull()); |
| return Get(); |
| } |
| |
| template <typename U> |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| WebPrivatePtrForRefCounted(U&& ptr) : WebPrivatePtrForRefCounted() { |
| static_assert( |
| PtrDestruction == WebPrivatePtrDestruction::kSameThread || |
| WTF::IsSubclassOfTemplate<T, WTF::ThreadSafeRefCounted>::value, |
| "Cross thread destructible class must derive from " |
| "ThreadSafeRefCounted<>"); |
| AsRefPtr() = std::forward<U>(ptr); |
| } |
| |
| template <typename U> |
| WebPrivatePtrForRefCounted& operator=(U&& ptr) { |
| AsRefPtr() = std::forward<U>(ptr); |
| return *this; |
| } |
| |
| WebPrivatePtrForRefCounted& operator=( |
| const WebPrivatePtrForRefCounted& other) { |
| AsRefPtr() = other.AsRefPtr(); |
| return *this; |
| } |
| |
| #else // !INSIDE_BLINK |
| // Disable the assignment operator; we define it above for when |
| // INSIDE_BLINK is set, but we need to make sure that it is not |
| // used outside there; the compiler-provided version won't handle reference |
| // counting properly. |
| WebPrivatePtrForRefCounted& operator=( |
| const WebPrivatePtrForRefCounted& other) = delete; |
| #endif // !INSIDE_BLINK |
| |
| private: |
| #if INSIDE_BLINK |
| scoped_refptr<T>& AsRefPtr() { |
| return *reinterpret_cast<scoped_refptr<T>*>(&storage_); |
| } |
| const scoped_refptr<T>& AsRefPtr() const { |
| return const_cast<WebPrivatePtrForRefCounted*>(this)->AsRefPtr(); |
| } |
| #endif // INSIDE_BLINK |
| |
| alignas(scoped_refptr<T>) std::byte storage_[sizeof(scoped_refptr<T>)] = { |
| std::byte{0}}; |
| }; |
| |
| // Translates WebPrivatePtrDestruction and WebPrivatePtrStrength to the |
| // appropriate Blink Persistent type. |
| template <typename T, WebPrivatePtrDestruction, WebPrivatePtrStrength> |
| struct WebPrivatePtrPersistentStorageType; |
| |
| #define TRAIT_TO_TYPE_LIST(V) \ |
| V(kSameThread, kNormal, Persistent<T>) \ |
| V(kSameThread, kWeak, WeakPersistent<T>) \ |
| V(kCrossThread, kNormal, CrossThreadPersistent<T>) \ |
| V(kCrossThread, kWeak, CrossThreadWeakPersistent<T>) |
| |
| #define DEFINE_TYPE_SPECIALIZATION(PtrDestruction, PtrStrengh, ReferenceType) \ |
| template <typename T> \ |
| struct WebPrivatePtrPersistentStorageType< \ |
| T, WebPrivatePtrDestruction::PtrDestruction, \ |
| WebPrivatePtrStrength::PtrStrengh> { \ |
| using Type = ReferenceType; \ |
| }; |
| |
| TRAIT_TO_TYPE_LIST(DEFINE_TYPE_SPECIALIZATION) |
| #undef DEFINE_TYPE_TRAIT |
| #undef TRAIT_TO_TYPE_LIST |
| |
| // For a general description see WebPrivatePtrForRefCounted. The difference is |
| // that WebPrivatePtrForGC points to a garbage collected object. The destructor |
| // of WebPrivatePtrForGC automatically clears the pointer as there's no |
| // immediate effect on other objects' destruction behavior. |
| // |
| // The implementation can use Blink handle types directly as the ctor/dtor can |
| // be used with forward declared types. |
| template <typename T, |
| WebPrivatePtrDestruction PtrDestruction = |
| WebPrivatePtrDestruction::kSameThread, |
| WebPrivatePtrStrength PtrStrength = WebPrivatePtrStrength::kNormal> |
| class WebPrivatePtrForGC final { |
| public: |
| explicit WebPrivatePtrForGC( |
| const PersistentLocation& loc = PERSISTENT_LOCATION_FROM_HERE) |
| : handle_(loc) {} |
| |
| // GCed pointers can be immediately destroyed as the don't directly invoke |
| // destructors of the value pointed to. For the same reason the destructor can |
| // also be used with forward declared types. |
| ~WebPrivatePtrForGC() = default; |
| |
| // Disable the copy constructor; classes that contain a WebPrivatePtrForGC |
| // should implement their copy constructor using assign(). |
| WebPrivatePtrForGC(const WebPrivatePtrForGC&) = delete; |
| |
| bool IsNull() const { return !static_cast<bool>(handle_); } |
| |
| explicit operator bool() const { return !IsNull(); } |
| |
| #if INSIDE_BLINK |
| void Reset() { handle_.Clear(); } |
| |
| T* Get() const { return handle_.Get(); } |
| |
| T& operator*() const { |
| DCHECK(!IsNull()); |
| return *Get(); |
| } |
| |
| T* operator->() const { |
| DCHECK(!IsNull()); |
| return Get(); |
| } |
| |
| template <typename U> |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| WebPrivatePtrForGC( |
| U&& ptr, |
| const PersistentLocation& loc = PERSISTENT_LOCATION_FROM_HERE) |
| : handle_(std::forward<U>(ptr), loc) { |
| static_assert(WTF::IsGarbageCollectedType<T>::value, |
| "WebPrivatePtrForGC can only be used on T inheriting from " |
| "GarbageCollected or GarbageCollectedMixin"); |
| } |
| |
| template <typename U> |
| WebPrivatePtrForGC& operator=(U&& ptr) { |
| handle_ = std::forward<U>(ptr); |
| return *this; |
| } |
| |
| WebPrivatePtrForGC& operator=(const WebPrivatePtrForGC& other) { |
| handle_ = other.handle_; |
| return *this; |
| } |
| |
| #else // !INSIDE_BLINK |
| // Disable the assignment operator; we define it above for when |
| // INSIDE_BLINK is set, but we need to make sure that it is not |
| // used outside there; the compiler-provided version won't handle reference |
| // counting properly. |
| WebPrivatePtrForGC& operator=(const WebPrivatePtrForGC& other) = delete; |
| #endif // !INSIDE_BLINK |
| |
| private: |
| using BlinkPtrType = |
| typename WebPrivatePtrPersistentStorageType<T, |
| PtrDestruction, |
| PtrStrength>::Type; |
| BlinkPtrType handle_; |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_PRIVATE_PTR_H_ |