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 34namespace JSC { 35 36template<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 41template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const 42{ 43 return m_impl == hashTableDeletedValue(); 44} 45 46template<typename T> inline Weak<T>::Weak(typename Weak<T>::HashTableDeletedValueTag) 47 : m_impl(hashTableDeletedValue()) 48{ 49} 50 51template<typename T> inline Weak<T>::Weak(Weak&& other) 52 : m_impl(other.leakImpl()) 53{ 54} 55 56template<class T> inline void swap(Weak<T>& a, Weak<T>& b) 57{ 58 a.swap(b); 59} 60 61template<typename T> inline void Weak<T>::swap(Weak& other) 62{ 63 std::swap(m_impl, other.m_impl); 64} 65 66template<typename T> inline auto Weak<T>::operator=(Weak&& other) -> Weak& 67{ 68 Weak weak = WTF::move(other); 69 swap(weak); 70 return *this; 71} 72 73template<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 79template<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 85template<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 92template<typename T> inline bool Weak<T>::was(T* other) const 93{ 94 return static_cast<T*>(m_impl->jsValue().asCell()) == other; 95} 96 97template<typename T> inline bool Weak<T>::operator!() const 98{ 99 return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live; 100} 101 102template<typename T> inline Weak<T>::operator UnspecifiedBoolType*() const 103{ 104 return reinterpret_cast<UnspecifiedBoolType*>(!!*this); 105} 106 107template<typename T> inline WeakImpl* Weak<T>::leakImpl() 108{ 109 WeakImpl* impl = m_impl; 110 m_impl = nullptr; 111 return impl; 112} 113 114template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue() 115{ 116 return reinterpret_cast<WeakImpl*>(-1); 117} 118 119template <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.) 126template<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 132template<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 142template<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 152namespace WTF { 153 154template<typename T> struct VectorTraits<JSC::Weak<T>> : SimpleClassVectorTraits { 155 static const bool canCompareWithMemcmp = false; 156}; 157 158template<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