1 | /* |
---|---|

2 | * Copyright (C) 2009, 2012, 2013 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 WeakInlines_h |

27 | #define WeakInlines_h |

28 | |

29 | #include "JSCell.h" |

30 | #include "WeakSetInlines.h" |

31 | #include <wtf/Assertions.h> |

32 | #include <wtf/HashTraits.h> |

33 | |

34 | namespace JSC { |

35 | |

36 | template<typename T> inline Weak<T>::Weak(T* cell, WeakHandleOwner* weakOwner, void* context) |

37 | : m_impl(cell ? WeakSet::allocate(cell, weakOwner, context) : 0) |

38 | { |

39 | } |

40 | |

41 | template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const |

42 | { |

43 | return m_impl == hashTableDeletedValue(); |

44 | } |

45 | |

46 | template<typename T> inline Weak<T>::Weak(typename Weak<T>::HashTableDeletedValueTag) |

47 | : m_impl(hashTableDeletedValue()) |

48 | { |

49 | } |

50 | |

51 | template<typename T> inline Weak<T>::Weak(Weak&& other) |

52 | : m_impl(other.leakImpl()) |

53 | { |

54 | } |

55 | |

56 | template<class T> inline void swap(Weak<T>& a, Weak<T>& b) |

57 | { |

58 | a.swap(b); |

59 | } |

60 | |

61 | template<typename T> inline void Weak<T>::swap(Weak& other) |

62 | { |

63 | std::swap(m_impl, other.m_impl); |

64 | } |

65 | |

66 | template<typename T> inline auto Weak<T>::operator=(Weak&& other) -> Weak& |

67 | { |

68 | Weak weak = WTFMove(other); |

69 | swap(weak); |

70 | return *this; |

71 | } |

72 | |

73 | template<typename T> inline T* Weak<T>::operator->() const |

74 | { |

75 | ASSERT(m_impl && m_impl->state() == WeakImpl::Live); |

76 | return jsCast<T*>(m_impl->jsValue().asCell()); |

77 | } |

78 | |

79 | template<typename T> inline T& Weak<T>::operator*() const |

80 | { |

81 | ASSERT(m_impl && m_impl->state() == WeakImpl::Live); |

82 | return *jsCast<T*>(m_impl->jsValue().asCell()); |

83 | } |

84 | |

85 | template<typename T> inline T* Weak<T>::get() const |

86 | { |

87 | if (!m_impl || m_impl->state() != WeakImpl::Live) |

88 | return 0; |

89 | return jsCast<T*>(m_impl->jsValue().asCell()); |

90 | } |

91 | |

92 | template<typename T> inline bool Weak<T>::was(T* other) const |

93 | { |

94 | return static_cast<T*>(m_impl->jsValue().asCell()) == other; |

95 | } |

96 | |

97 | template<typename T> inline bool Weak<T>::operator!() const |

98 | { |

99 | return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live; |

100 | } |

101 | |

102 | template<typename T> inline Weak<T>::operator bool() const |

103 | { |

104 | return !!*this; |

105 | } |

106 | |

107 | template<typename T> inline WeakImpl* Weak<T>::leakImpl() |

108 | { |

109 | WeakImpl* impl = m_impl; |

110 | m_impl = nullptr; |

111 | return impl; |

112 | } |

113 | |

114 | template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue() |

115 | { |

116 | return reinterpret_cast<WeakImpl*>(-1); |

117 | } |

118 | |

119 | template <typename T> inline bool operator==(const Weak<T>& lhs, const Weak<T>& rhs) |

120 | { |

121 | return lhs.get() == rhs.get(); |

122 | } |

123 | |

124 | // This function helps avoid modifying a weak table while holding an iterator into it. (Object allocation |

125 | // can run a finalizer that modifies the table. We avoid that by requiring a pre-constructed object as our value.) |

126 | template<typename Map, typename Key, typename Value> inline void weakAdd(Map& map, const Key& key, Value&& value) |

127 | { |

128 | ASSERT(!map.get(key)); |

129 | map.set(key, std::forward<Value>(value)); // The table may still have a zombie for value. |

130 | } |

131 | |

132 | template<typename Map, typename Key, typename Value> inline void weakRemove(Map& map, const Key& key, Value value) |

133 | { |

134 | typename Map::iterator it = map.find(key); |

135 | ASSERT_UNUSED(value, value); |

136 | ASSERT(it != map.end()); |

137 | ASSERT(it->value.was(value)); |

138 | ASSERT(!it->value); |

139 | map.remove(it); |

140 | } |

141 | |

142 | template<typename T> inline void weakClear(Weak<T>& weak, T* cell) |

143 | { |

144 | ASSERT_UNUSED(cell, cell); |

145 | ASSERT(weak.was(cell)); |

146 | ASSERT(!weak); |

147 | weak.clear(); |

148 | } |

149 | |

150 | } // namespace JSC |

151 | |

152 | namespace WTF { |

153 | |

154 | template<typename T> struct VectorTraits<JSC::Weak<T>> : SimpleClassVectorTraits { |

155 | static const bool canCompareWithMemcmp = false; |

156 | }; |

157 | |

158 | template<typename T> struct HashTraits<JSC::Weak<T>> : SimpleClassHashTraits<JSC::Weak<T>> { |

159 | typedef JSC::Weak<T> StorageType; |

160 | |

161 | typedef std::nullptr_t EmptyValueType; |

162 | static EmptyValueType emptyValue() { return nullptr; } |

163 | |

164 | typedef T* PeekType; |

165 | static PeekType peek(const StorageType& value) { return value.get(); } |

166 | static PeekType peek(EmptyValueType) { return PeekType(); } |

167 | }; |

168 | |

169 | } // namespace WTF |

170 | |

171 | #endif // WeakInlines_h |

172 |