Commit | Line | Data |
---|---|---|
f9bf01c6 A |
1 | /* |
2 | * Copyright (C) 2009 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 | #ifndef WeakGCMap_h | |
27 | #define WeakGCMap_h | |
28 | ||
81345200 A |
29 | #include "Weak.h" |
30 | #include "WeakInlines.h" | |
f9bf01c6 A |
31 | #include <wtf/HashMap.h> |
32 | ||
33 | namespace JSC { | |
34 | ||
93a37866 | 35 | // A HashMap with Weak<JSCell> values, which automatically removes values once they're garbage collected. |
f9bf01c6 | 36 | |
81345200 A |
37 | template<typename KeyArg, typename ValueArg, typename HashArg = typename DefaultHash<KeyArg>::Hash, |
38 | typename KeyTraitsArg = HashTraits<KeyArg>> | |
39 | class WeakGCMap { | |
40 | WTF_MAKE_FAST_ALLOCATED; | |
41 | typedef Weak<ValueArg> ValueType; | |
42 | typedef HashMap<KeyArg, ValueType, HashArg, KeyTraitsArg> HashMapType; | |
f9bf01c6 A |
43 | |
44 | public: | |
81345200 A |
45 | typedef typename HashMapType::KeyType KeyType; |
46 | typedef typename HashMapType::AddResult AddResult; | |
47 | typedef typename HashMapType::iterator iterator; | |
48 | typedef typename HashMapType::const_iterator const_iterator; | |
6fe7ccc8 | 49 | |
14957cd0 | 50 | WeakGCMap() |
93a37866 | 51 | : m_gcThreshold(minGCThreshold) |
14957cd0 A |
52 | { |
53 | } | |
54 | ||
81345200 A |
55 | ValueArg* get(const KeyType& key) const |
56 | { | |
57 | return m_map.get(key); | |
58 | } | |
59 | ||
60 | AddResult set(const KeyType& key, ValueType value) | |
14957cd0 | 61 | { |
93a37866 | 62 | gcMapIfNeeded(); |
81345200 | 63 | return m_map.set(key, WTF::move(value)); |
14957cd0 | 64 | } |
f9bf01c6 | 65 | |
81345200 | 66 | ALWAYS_INLINE AddResult add(const KeyType& key, ValueType value) |
14957cd0 | 67 | { |
93a37866 | 68 | gcMapIfNeeded(); |
81345200 | 69 | AddResult addResult = m_map.fastAdd(key, nullptr); |
93a37866 A |
70 | if (!addResult.iterator->value) { // New value or found a zombie value. |
71 | addResult.isNewEntry = true; | |
81345200 | 72 | addResult.iterator->value = WTF::move(value); |
93a37866 A |
73 | } |
74 | return addResult; | |
14957cd0 | 75 | } |
f9bf01c6 | 76 | |
81345200 A |
77 | bool remove(const KeyType& key) |
78 | { | |
79 | return m_map.remove(key); | |
80 | } | |
81 | ||
82 | void clear() | |
83 | { | |
84 | m_map.clear(); | |
85 | } | |
86 | ||
14957cd0 A |
87 | iterator find(const KeyType& key) |
88 | { | |
81345200 A |
89 | iterator it = m_map.find(key); |
90 | iterator end = m_map.end(); | |
93a37866 A |
91 | if (it != end && !it->value) // Found a zombie value. |
92 | return end; | |
93 | return it; | |
14957cd0 | 94 | } |
f9bf01c6 | 95 | |
93a37866 | 96 | const_iterator find(const KeyType& key) const |
14957cd0 | 97 | { |
81345200 | 98 | return const_cast<WeakGCMap*>(this)->find(key); |
14957cd0 | 99 | } |
f9bf01c6 | 100 | |
93a37866 | 101 | bool contains(const KeyType& key) const |
14957cd0 | 102 | { |
81345200 | 103 | return find(key) != m_map.end(); |
14957cd0 | 104 | } |
f9bf01c6 | 105 | |
93a37866 A |
106 | private: |
107 | static const int minGCThreshold = 3; | |
f9bf01c6 | 108 | |
81345200 | 109 | NEVER_INLINE void gcMap() |
14957cd0 | 110 | { |
93a37866 | 111 | Vector<KeyType, 4> zombies; |
81345200 A |
112 | |
113 | for (iterator it = m_map.begin(), end = m_map.end(); it != end; ++it) { | |
93a37866 A |
114 | if (!it->value) |
115 | zombies.append(it->key); | |
116 | } | |
81345200 | 117 | |
93a37866 | 118 | for (size_t i = 0; i < zombies.size(); ++i) |
81345200 | 119 | m_map.remove(zombies[i]); |
14957cd0 A |
120 | } |
121 | ||
93a37866 | 122 | void gcMapIfNeeded() |
14957cd0 | 123 | { |
81345200 | 124 | if (m_map.size() < m_gcThreshold) |
93a37866 | 125 | return; |
14957cd0 | 126 | |
93a37866 | 127 | gcMap(); |
81345200 | 128 | m_gcThreshold = std::max(minGCThreshold, m_map.size() * 2 - 1); |
14957cd0 A |
129 | } |
130 | ||
81345200 | 131 | HashMapType m_map; |
93a37866 | 132 | int m_gcThreshold; |
14957cd0 | 133 | }; |
f9bf01c6 | 134 | |
93a37866 A |
135 | template<typename KeyArg, typename RawMappedArg, typename HashArg, typename KeyTraitsArg> |
136 | const int WeakGCMap<KeyArg, RawMappedArg, HashArg, KeyTraitsArg>::minGCThreshold; | |
137 | ||
f9bf01c6 A |
138 | } // namespace JSC |
139 | ||
140 | #endif // WeakGCMap_h |