2011-04-07 Geoffrey Garen <ggaren@apple.com>
[WebKit-https.git] / Source / JavaScriptCore / runtime / WeakGCMap.h
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
29 #include "Handle.h"
30 #include "JSGlobalData.h"
31 #include <wtf/HashMap.h>
32
33 namespace JSC {
34
35 // A HashMap for GC'd values that removes entries when the associated value
36 // dies.
37 template<typename KeyType, typename MappedType> class WeakGCMap : private WeakHandleOwner {
38     WTF_MAKE_FAST_ALLOCATED;
39     WTF_MAKE_NONCOPYABLE(WeakGCMap);
40
41     typedef HashMap<KeyType, HandleSlot> MapType;
42     typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
43     typedef typename MapType::iterator map_iterator;
44
45 public:
46
47     struct iterator {
48         iterator(map_iterator iter)
49             : m_iterator(iter)
50         {
51         }
52         
53         std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); }
54         std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; }
55         
56         iterator& operator++() { ++m_iterator; return *this; }
57         
58         // postfix ++ intentionally omitted
59         
60         // Comparison.
61         bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
62         bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
63         
64     private:
65             map_iterator m_iterator;
66     };
67
68     WeakGCMap()
69     {
70     }
71
72     bool isEmpty() { return m_map.isEmpty(); }
73     void clear()
74     {
75         map_iterator end = m_map.end();
76         for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
77             HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
78         m_map.clear();
79     }
80
81     ExternalType get(const KeyType& key) const
82     {
83         return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
84     }
85
86     HandleSlot getSlot(const KeyType& key) const
87     {
88         return m_map.get(key);
89     }
90
91     void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
92     {
93         pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
94         HandleSlot slot = iter.first->second;
95         if (iter.second) {
96             slot = globalData.allocateGlobalHandle();
97             HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
98             iter.first->second = slot;
99         }
100         HandleHeap::heapFor(slot)->writeBarrier(slot, value);
101         *slot = value;
102     }
103
104     ExternalType take(const KeyType& key)
105     {
106         HandleSlot slot = m_map.take(key);
107         if (!slot)
108             return HashTraits<ExternalType>::emptyValue();
109         ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
110         HandleHeap::heapFor(slot)->deallocate(slot);
111         return result;
112     }
113
114     size_t size() { return m_map.size(); }
115
116     iterator begin() { return iterator(m_map.begin()); }
117     iterator end() { return iterator(m_map.end()); }
118     
119     ~WeakGCMap()
120     {
121         clear();
122     }
123     
124 private:
125     virtual void finalize(Handle<Unknown>, void* context)
126     {
127         HandleSlot slot = m_map.take(static_cast<KeyType>(context));
128         ASSERT(slot);
129         HandleHeap::heapFor(slot)->deallocate(slot);
130     }
131
132     MapType m_map;
133 };
134
135 } // namespace JSC
136
137 #endif // WeakGCMap_h