OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef WeakIdentifierMap_h | 5 #ifndef WeakIdentifierMap_h |
6 #define WeakIdentifierMap_h | 6 #define WeakIdentifierMap_h |
7 | 7 |
8 #include "platform/heap/Handle.h" | 8 #include "platform/heap/Handle.h" |
9 #include "wtf/Allocator.h" | 9 #include "wtf/Allocator.h" |
10 #include "wtf/HashMap.h" | 10 #include "wtf/HashMap.h" |
11 #include "wtf/Vector.h" | |
12 | 11 |
13 namespace blink { | 12 namespace blink { |
14 | 13 |
15 template<typename T> struct IdentifierGenerator; | 14 // TODO(sof): WeakIdentifierMap<> belongs (out) in wtf/, but |
| 15 // cannot until GarbageCollected<> can be used from WTF. |
16 | 16 |
17 template<> struct IdentifierGenerator<int> { | 17 template<typename T, typename IdentifierType, bool isGarbageCollected> |
18 STATIC_ONLY(IdentifierGenerator); | 18 class WeakIdentifierMapBase { |
19 using IdentifierType = int; | 19 USING_FAST_MALLOC(WeakIdentifierMapBase); |
20 static IdentifierType next() | 20 protected: |
21 { | |
22 static int s_lastId = 0; | |
23 return ++s_lastId; | |
24 } | |
25 }; | |
26 | |
27 template<typename T> struct WeakIdentifierMapTraits { | |
28 STATIC_ONLY(WeakIdentifierMapTraits); | |
29 static void removedFromIdentifierMap(T*) { } | |
30 static void addedToIdentifierMap(T*) { } | |
31 }; | |
32 | |
33 template<typename T, | |
34 typename Generator = IdentifierGenerator<int>, | |
35 typename Traits = WeakIdentifierMapTraits<T>, | |
36 bool isGarbageCollected = IsGarbageCollectedType<T>::value> class WeakIdenti
fierMap; | |
37 | |
38 template<typename T, typename Generator, typename Traits> class WeakIdentifierMa
p<T, Generator, Traits, false> { | |
39 USING_FAST_MALLOC(WeakIdentifierMap); | |
40 public: | |
41 using IdentifierType = typename Generator::IdentifierType; | |
42 | |
43 static IdentifierType identifier(T* object) | |
44 { | |
45 IdentifierType result = instance().m_objectToIdentifier.get(object); | |
46 | |
47 if (WTF::isHashTraitsEmptyValue<HashTraits<IdentifierType>>(result)) { | |
48 result = Generator::next(); | |
49 instance().put(object, result); | |
50 } | |
51 return result; | |
52 } | |
53 | |
54 static T* lookup(IdentifierType identifier) | |
55 { | |
56 return instance().m_identifierToObject.get(identifier); | |
57 } | |
58 | |
59 static void notifyObjectDestroyed(T* object) | |
60 { | |
61 instance().objectDestroyed(object); | |
62 } | |
63 | |
64 private: | |
65 static WeakIdentifierMap<T, Generator, Traits>& instance(); | |
66 WeakIdentifierMap() { } | |
67 ~WeakIdentifierMap(); | |
68 | |
69 void put(T* object, IdentifierType identifier) | |
70 { | |
71 DCHECK(object && !m_objectToIdentifier.contains(object)); | |
72 m_objectToIdentifier.set(object, identifier); | |
73 m_identifierToObject.set(identifier, object); | |
74 Traits::addedToIdentifierMap(object); | |
75 } | |
76 | |
77 void objectDestroyed(T* object) | |
78 { | |
79 IdentifierType identifier = m_objectToIdentifier.take(object); | |
80 if (!WTF::isHashTraitsEmptyValue<HashTraits<IdentifierType>>(identifier)
) | |
81 m_identifierToObject.remove(identifier); | |
82 } | |
83 | |
84 using ObjectToIdentifier = HashMap<T*, IdentifierType>; | 21 using ObjectToIdentifier = HashMap<T*, IdentifierType>; |
85 using IdentifierToObject = HashMap<IdentifierType, T*>; | 22 using IdentifierToObject = HashMap<IdentifierType, T*>; |
86 | 23 |
87 ObjectToIdentifier m_objectToIdentifier; | 24 ObjectToIdentifier m_objectToIdentifier; |
88 IdentifierToObject m_identifierToObject; | 25 IdentifierToObject m_identifierToObject; |
89 }; | 26 }; |
90 | 27 |
91 template<typename T, typename Generator, typename Traits> class WeakIdentifierMa
p<T, Generator, Traits, true> | 28 template<typename T, typename IdentifierType> |
92 : public GarbageCollected<WeakIdentifierMap<T, Generator, Traits, true>> { | 29 class WeakIdentifierMapBase<T, IdentifierType, true> : public GarbageCollected<W
eakIdentifierMapBase<T, IdentifierType, true>> { |
93 public: | 30 public: |
94 using IdentifierType = typename Generator::IdentifierType; | 31 DEFINE_INLINE_TRACE() |
| 32 { |
| 33 visitor->trace(m_objectToIdentifier); |
| 34 visitor->trace(m_identifierToObject); |
| 35 } |
| 36 protected: |
| 37 using ObjectToIdentifier = HeapHashMap<WeakMember<T>, IdentifierType>; |
| 38 using IdentifierToObject = HeapHashMap<IdentifierType, WeakMember<T>>; |
95 | 39 |
| 40 ObjectToIdentifier m_objectToIdentifier; |
| 41 IdentifierToObject m_identifierToObject; |
| 42 }; |
| 43 |
| 44 template<typename T, typename IdentifierType = int> |
| 45 class WeakIdentifierMap final : public WeakIdentifierMapBase<T, IdentifierType,
IsGarbageCollectedType<T>::value> { |
| 46 public: |
96 static IdentifierType identifier(T* object) | 47 static IdentifierType identifier(T* object) |
97 { | 48 { |
98 IdentifierType result = instance().m_objectToIdentifier->get(object); | 49 IdentifierType result = instance().m_objectToIdentifier.get(object); |
99 | 50 |
100 if (WTF::isHashTraitsEmptyValue<HashTraits<IdentifierType>>(result)) { | 51 if (WTF::isHashTraitsEmptyValue<HashTraits<IdentifierType>>(result)) { |
101 result = Generator::next(); | 52 result = next(); |
102 instance().put(object, result); | 53 instance().put(object, result); |
103 } | 54 } |
104 return result; | 55 return result; |
105 } | 56 } |
106 | 57 |
107 static T* lookup(IdentifierType identifier) | 58 static T* lookup(IdentifierType identifier) |
108 { | 59 { |
109 return instance().m_identifierToObject->get(identifier); | 60 return instance().m_identifierToObject.get(identifier); |
110 } | 61 } |
111 | 62 |
112 static void notifyObjectDestroyed(T* object) { } | 63 static void notifyObjectDestroyed(T* object) |
113 | |
114 DEFINE_INLINE_TRACE() | |
115 { | 64 { |
116 visitor->trace(m_objectToIdentifier); | 65 instance().objectDestroyed(object); |
117 visitor->trace(m_identifierToObject); | |
118 } | 66 } |
119 | 67 |
120 private: | 68 private: |
121 static WeakIdentifierMap<T, Generator, Traits>& instance(); | 69 static WeakIdentifierMap<T, IdentifierType>& instance(); |
122 | 70 |
123 WeakIdentifierMap() | 71 WeakIdentifierMap() { } |
124 : m_objectToIdentifier(new ObjectToIdentifier()) | 72 |
125 , m_identifierToObject(new IdentifierToObject()) | 73 static IdentifierType next() |
126 { | 74 { |
| 75 static IdentifierType s_lastId = 0; |
| 76 return ++s_lastId; |
127 } | 77 } |
128 | 78 |
129 void put(T* object, IdentifierType identifier) | 79 void put(T* object, IdentifierType identifier) |
130 { | 80 { |
131 DCHECK(object && !m_objectToIdentifier->contains(object)); | 81 DCHECK(object && !this->m_objectToIdentifier.contains(object)); |
132 m_objectToIdentifier->set(object, identifier); | 82 this->m_objectToIdentifier.set(object, identifier); |
133 m_identifierToObject->set(identifier, object); | 83 this->m_identifierToObject.set(identifier, object); |
134 } | 84 } |
135 | 85 |
136 using ObjectToIdentifier = HeapHashMap<WeakMember<T>, IdentifierType>; | 86 void objectDestroyed(T* object) |
137 using IdentifierToObject = HeapHashMap<IdentifierType, WeakMember<T>>; | 87 { |
138 | 88 IdentifierType identifier = this->m_objectToIdentifier.take(object); |
139 Member<ObjectToIdentifier> m_objectToIdentifier; | 89 if (!WTF::isHashTraitsEmptyValue<HashTraits<IdentifierType>>(identifier)
) |
140 Member<IdentifierToObject> m_identifierToObject; | 90 this->m_identifierToObject.remove(identifier); |
| 91 } |
141 }; | 92 }; |
142 | 93 |
143 #define DECLARE_WEAK_IDENTIFIER_MAP(T, ...) \ | 94 #define DECLARE_WEAK_IDENTIFIER_MAP(T, ...) \ |
144 template<> WeakIdentifierMap<T, ##__VA_ARGS__>& WeakIdentifierMap<T, ##__VA_
ARGS__>::instance(); \ | 95 template<> WeakIdentifierMap<T, ##__VA_ARGS__>& WeakIdentifierMap<T, ##__VA_
ARGS__>::instance(); \ |
145 extern template class WeakIdentifierMap<T, ##__VA_ARGS__>; | 96 extern template class WeakIdentifierMap<T, ##__VA_ARGS__>; |
146 | 97 |
147 #define DEFINE_WEAK_IDENTIFIER_MAP(T, ...) \ | 98 #define DEFINE_WEAK_IDENTIFIER_MAP(T, ...) \ |
148 template class WeakIdentifierMap<T, ##__VA_ARGS__>; \ | 99 template class WeakIdentifierMap<T, ##__VA_ARGS__>; \ |
149 template<> WeakIdentifierMap<T, ##__VA_ARGS__>& WeakIdentifierMap<T, ##__VA_
ARGS__>::instance() \ | 100 template<> WeakIdentifierMap<T, ##__VA_ARGS__>& WeakIdentifierMap<T, ##__VA_
ARGS__>::instance() \ |
150 { \ | 101 { \ |
151 using RefType = WeakIdentifierMap<T, ##__VA_ARGS__>; \ | 102 using RefType = WeakIdentifierMap<T, ##__VA_ARGS__>; \ |
152 DEFINE_STATIC_LOCAL(RefType, mapInstance, (new WeakIdentifierMap<T, ##__
VA_ARGS__>())); \ | 103 DEFINE_STATIC_LOCAL(RefType, mapInstance, (new WeakIdentifierMap<T, ##__
VA_ARGS__>())); \ |
153 return mapInstance; \ | 104 return mapInstance; \ |
154 } | 105 } |
155 | 106 |
156 } // namespace blink | 107 } // namespace blink |
157 | 108 |
158 #endif // WeakIdentifierMap_h | 109 #endif // WeakIdentifierMap_h |
OLD | NEW |