1 | /* |
2 | * Copyright (C) 2013-2018 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #include <wtf/DumbPtrTraits.h> |
29 | #include <wtf/HashCountedSet.h> |
30 | #include <wtf/RefPtr.h> |
31 | |
32 | namespace WebCore { |
33 | |
34 | class Node; |
35 | |
36 | class GCReachableRefMap { |
37 | public: |
38 | static inline bool contains(Node& node) { return map().contains(&node); } |
39 | static inline void add(Node& node) { map().add(&node); } |
40 | static inline void remove(Node& node) { map().remove(&node); } |
41 | |
42 | private: |
43 | static HashCountedSet<Node*>& map(); |
44 | }; |
45 | |
46 | template <typename T, typename = std::enable_if_t<std::is_same<T, typename std::remove_const<T>::type>::value>> |
47 | class GCReachableRef { |
48 | WTF_MAKE_NONCOPYABLE(GCReachableRef); |
49 | public: |
50 | |
51 | template<typename = std::enable_if_t<std::is_base_of<Node, T>::value>> |
52 | GCReachableRef(T& object) |
53 | : m_ptr(&object) |
54 | { |
55 | GCReachableRefMap::add(*m_ptr); |
56 | } |
57 | |
58 | ~GCReachableRef() |
59 | { |
60 | if (m_ptr) |
61 | GCReachableRefMap::remove(*m_ptr); |
62 | } |
63 | |
64 | GCReachableRef(GCReachableRef&& other) |
65 | : m_ptr(WTFMove(other.m_ptr)) |
66 | { |
67 | } |
68 | |
69 | T* operator->() const { return &get(); } |
70 | T* ptr() const RETURNS_NONNULL { return &get(); } |
71 | T& get() const { ASSERT(m_ptr); return *m_ptr; } |
72 | operator T&() const { return get(); } |
73 | bool operator!() const { return !get(); } |
74 | |
75 | // Hash table deleted values, which are only constructed and never copied or destroyed. |
76 | GCReachableRef(WTF::HashTableDeletedValueType) |
77 | : m_ptr(RefPtr<T>::hashTableDeletedValue()) |
78 | { } |
79 | bool isHashTableDeletedValue() const { return m_ptr.isHashTableDeletedValue(); } |
80 | |
81 | GCReachableRef(WTF::HashTableEmptyValueType) |
82 | : m_ptr(nullptr) |
83 | { } |
84 | bool isHashTableEmptyValue() const { return !m_ptr; } |
85 | |
86 | const T* ptrAllowingHashTableEmptyValue() const { ASSERT(m_ptr || isHashTableEmptyValue()); return m_ptr.get(); } |
87 | T* ptrAllowingHashTableEmptyValue() { ASSERT(m_ptr || isHashTableEmptyValue()); return m_ptr.get(); } |
88 | |
89 | void assignToHashTableEmptyValue(GCReachableRef&& reference) |
90 | { |
91 | ASSERT(!m_ptr); |
92 | m_ptr = WTFMove(reference.m_ptr); |
93 | ASSERT(m_ptr); |
94 | } |
95 | |
96 | private: |
97 | RefPtr<T> m_ptr; |
98 | }; |
99 | |
100 | } // namespace WebCore |
101 | |
102 | namespace WTF { |
103 | |
104 | template<typename P> struct HashTraits<WebCore::GCReachableRef<P>> : SimpleClassHashTraits<WebCore::GCReachableRef<P>> { |
105 | static const bool emptyValueIsZero = true; |
106 | static WebCore::GCReachableRef<P> emptyValue() { return HashTableEmptyValue; } |
107 | |
108 | template <typename> |
109 | static void constructEmptyValue(WebCore::GCReachableRef<P>& slot) |
110 | { |
111 | new (NotNull, std::addressof(slot)) WebCore::GCReachableRef<P>(HashTableEmptyValue); |
112 | } |
113 | |
114 | static const bool hasIsEmptyValueFunction = true; |
115 | static bool isEmptyValue(const WebCore::GCReachableRef<P>& value) { return value.isHashTableEmptyValue(); } |
116 | |
117 | static void assignToEmpty(WebCore::GCReachableRef<P>& emptyValue, WebCore::GCReachableRef<P>&& newValue) |
118 | { |
119 | ASSERT(isEmptyValue(emptyValue)); |
120 | emptyValue.assignToHashTableEmptyValue(WTFMove(newValue)); |
121 | } |
122 | |
123 | typedef P* PeekType; |
124 | static PeekType peek(const Ref<P>& value) { return const_cast<PeekType>(value.ptrAllowingHashTableEmptyValue()); } |
125 | static PeekType peek(P* value) { return value; } |
126 | |
127 | typedef Optional<Ref<P>> TakeType; |
128 | static TakeType take(Ref<P>&& value) { return isEmptyValue(value) ? WTF::nullopt : Optional<Ref<P>>(WTFMove(value)); } |
129 | }; |
130 | |
131 | template <typename T, typename U> |
132 | struct GetPtrHelper<WebCore::GCReachableRef<T, U>> { |
133 | typedef T* PtrType; |
134 | static T* getPtr(const WebCore::GCReachableRef<T, U>& reference) { return const_cast<T*>(reference.ptr()); } |
135 | }; |
136 | |
137 | template <typename T, typename U> |
138 | struct IsSmartPtr<WebCore::GCReachableRef<T, U>> { |
139 | static const bool value = true; |
140 | }; |
141 | |
142 | template<typename P> struct PtrHash<WebCore::GCReachableRef<P>> : PtrHashBase<WebCore::GCReachableRef<P>, IsSmartPtr<WebCore::GCReachableRef<P>>::value> { |
143 | static const bool safeToCompareToEmptyOrDeleted = false; |
144 | }; |
145 | |
146 | template<typename P> struct DefaultHash<WebCore::GCReachableRef<P>> { |
147 | typedef PtrHash<WebCore::GCReachableRef<P>> Hash; |
148 | }; |
149 | |
150 | } // namespace WTF |
151 | |
152 | |