2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "JSGlobalData.h"
31 #include <wtf/HashMap.h>
35 // A HashMap for GC'd values that removes entries when the associated value
37 template <typename KeyType
, typename MappedType
> struct DefaultWeakGCMapFinalizerCallback
{
38 static void* finalizerContextFor(KeyType key
)
40 return reinterpret_cast<void*>(key
);
43 static KeyType
keyForFinalizer(void* context
, typename HandleTypes
<MappedType
>::ExternalType
)
45 return reinterpret_cast<KeyType
>(context
);
49 template<typename KeyType
, typename MappedType
, typename FinalizerCallback
= DefaultWeakGCMapFinalizerCallback
<KeyType
, MappedType
>, typename HashArg
= typename DefaultHash
<KeyType
>::Hash
, typename KeyTraitsArg
= HashTraits
<KeyType
> >
50 class WeakGCMap
: private WeakHandleOwner
{
51 WTF_MAKE_FAST_ALLOCATED
;
52 WTF_MAKE_NONCOPYABLE(WeakGCMap
);
54 typedef HashMap
<KeyType
, WeakImpl
*, HashArg
, KeyTraitsArg
> MapType
;
55 typedef typename HandleTypes
<MappedType
>::ExternalType ExternalType
;
56 typedef typename
MapType::iterator map_iterator
;
61 friend class WeakGCMap
;
62 iterator(map_iterator iter
)
67 std::pair
<KeyType
, ExternalType
> get() const { return std::make_pair(m_iterator
->first
, HandleTypes
<MappedType
>::getFromSlot(const_cast<JSValue
*>(&m_iterator
->second
->jsValue()))); }
69 iterator
& operator++() { ++m_iterator
; return *this; }
71 // postfix ++ intentionally omitted
74 bool operator==(const iterator
& other
) const { return m_iterator
== other
.m_iterator
; }
75 bool operator!=(const iterator
& other
) const { return m_iterator
!= other
.m_iterator
; }
78 map_iterator m_iterator
;
81 typedef WTF::HashTableAddResult
<iterator
> AddResult
;
87 bool isEmpty() { return m_map
.isEmpty(); }
90 map_iterator end
= m_map
.end();
91 for (map_iterator ptr
= m_map
.begin(); ptr
!= end
; ++ptr
)
92 WeakSet::deallocate(ptr
->second
);
96 bool contains(const KeyType
& key
) const
98 return m_map
.contains(key
);
101 iterator
find(const KeyType
& key
)
103 return m_map
.find(key
);
106 void remove(iterator iter
)
108 ASSERT(iter
.m_iterator
!= m_map
.end());
109 WeakImpl
* impl
= iter
.m_iterator
->second
;
111 WeakSet::deallocate(impl
);
112 m_map
.remove(iter
.m_iterator
);
115 ExternalType
get(const KeyType
& key
) const
117 return HandleTypes
<MappedType
>::getFromSlot(const_cast<JSValue
*>(&m_map
.get(key
)->jsValue()));
120 AddResult
add(JSGlobalData
&, const KeyType
& key
, ExternalType value
)
122 typename
MapType::AddResult result
= m_map
.add(key
, 0);
123 if (result
.isNewEntry
)
124 result
.iterator
->second
= WeakSet::allocate(value
, this, FinalizerCallback::finalizerContextFor(key
));
126 // WeakGCMap exposes a different iterator, so we need to wrap it and create our own AddResult.
127 return AddResult(iterator(result
.iterator
), result
.isNewEntry
);
130 void set(JSGlobalData
& globalData
, const KeyType
& key
, ExternalType value
)
132 ASSERT_UNUSED(globalData
, globalData
.apiLock().currentThreadIsHoldingLock());
133 typename
MapType::AddResult result
= m_map
.add(key
, 0);
134 if (!result
.isNewEntry
)
135 WeakSet::deallocate(result
.iterator
->second
);
136 result
.iterator
->second
= WeakSet::allocate(value
, this, FinalizerCallback::finalizerContextFor(key
));
139 ExternalType
take(const KeyType
& key
)
141 WeakImpl
* impl
= m_map
.take(key
);
143 return HashTraits
<ExternalType
>::emptyValue();
144 ExternalType result
= HandleTypes
<MappedType
>::getFromSlot(const_cast<JSValue
*>(&impl
->jsValue()));
145 WeakSet::deallocate(impl
);
149 size_t size() { return m_map
.size(); }
151 iterator
begin() { return iterator(m_map
.begin()); }
152 iterator
end() { return iterator(m_map
.end()); }
160 virtual void finalize(Handle
<Unknown
> handle
, void* context
)
162 WeakImpl
* impl
= m_map
.take(FinalizerCallback::keyForFinalizer(context
, HandleTypes
<MappedType
>::getFromSlot(handle
.slot())));
164 WeakSet::deallocate(impl
);
172 #endif // WeakGCMap_h