/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#ifndef Weak_h
#define Weak_h
-#include "Assertions.h"
-#include "Handle.h"
-#include "HandleHeap.h"
-#include "JSGlobalData.h"
+#include <cstddef>
+#include <wtf/Noncopyable.h>
namespace JSC {
-// A weakly referenced handle that becomes 0 when the value it points to is garbage collected.
-template <typename T> class Weak : public Handle<T> {
- using Handle<T>::slot;
- using Handle<T>::setSlot;
+class WeakImpl;
+class WeakHandleOwner;
-public:
- typedef typename Handle<T>::ExternalType ExternalType;
+// This is a free function rather than a Weak<T> member function so we can put it in Weak.cpp.
+JS_EXPORT_PRIVATE void weakClearSlowCase(WeakImpl*&);
+template<typename T> class Weak {
+ WTF_MAKE_NONCOPYABLE(Weak);
+public:
Weak()
- : Handle<T>()
+ : m_impl(0)
{
}
- Weak(JSGlobalData& globalData, ExternalType value = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0)
- : Handle<T>(globalData.allocateGlobalHandle())
+ Weak(std::nullptr_t)
+ : m_impl(0)
{
- HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
- set(value);
}
- enum AdoptTag { Adopt };
- template<typename U> Weak(AdoptTag, Handle<U> handle)
- : Handle<T>(handle.slot())
- {
- validateCell(get());
- }
-
- Weak(const Weak& other)
- : Handle<T>()
- {
- if (!other.slot())
- return;
- setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
- }
+ Weak(T*, WeakHandleOwner* = 0, void* context = 0);
- template <typename U> Weak(const Weak<U>& other)
- : Handle<T>()
- {
- if (!other.slot())
- return;
- setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
- }
-
enum HashTableDeletedValueTag { HashTableDeletedValue };
- bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
- Weak(HashTableDeletedValueTag)
- : Handle<T>(hashTableDeletedValue())
- {
- }
+ bool isHashTableDeletedValue() const;
+ Weak(HashTableDeletedValueTag);
+
+ Weak(Weak&&);
~Weak()
{
clear();
}
- void swap(Weak& other)
- {
- Handle<T>::swap(other);
- }
+ void swap(Weak&);
- ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); }
-
- void clear()
- {
- if (!slot())
- return;
- HandleHeap::heapFor(slot())->deallocate(slot());
- setSlot(0);
- }
-
- void set(JSGlobalData& globalData, ExternalType value, WeakHandleOwner* weakOwner = 0, void* context = 0)
- {
- if (!slot()) {
- setSlot(globalData.allocateGlobalHandle());
- HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
- }
- ASSERT(HandleHeap::heapFor(slot())->hasWeakOwner(slot(), weakOwner));
- set(value);
- }
+ Weak& operator=(Weak&&);
- template <typename U> Weak& operator=(const Weak<U>& other)
- {
- clear();
- if (other.slot())
- setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
- return *this;
- }
+ bool operator!() const;
+ T* operator->() const;
+ T& operator*() const;
+ T* get() const;
- Weak& operator=(const Weak& other)
+ bool was(T*) const;
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef void* (Weak::*UnspecifiedBoolType);
+ operator UnspecifiedBoolType*() const;
+
+ WeakImpl* leakImpl() WARN_UNUSED_RETURN;
+ void clear()
{
- clear();
- if (other.slot())
- setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
- return *this;
+ if (!m_impl)
+ return;
+ weakClearSlowCase(m_impl);
}
- HandleSlot leakHandle()
- {
- ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot()));
- HandleSlot result = slot();
- setSlot(0);
- return result;
- }
-
private:
- static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
+ static WeakImpl* hashTableDeletedValue();
- void set(ExternalType externalType)
- {
- ASSERT(slot());
- JSValue value = HandleTypes<T>::toJSValue(externalType);
- ASSERT(!value || !value.isCell() || Heap::isMarked(value.asCell()));
- HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
- *slot() = value;
- }
+ WeakImpl* m_impl;
};
-template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
-{
- a.swap(b);
-}
-
} // namespace JSC
-namespace WTF {
-
-template<typename T> struct VectorTraits<JSC::Weak<T> > : SimpleClassVectorTraits {
- static const bool canCompareWithMemcmp = false;
-};
-
-template<typename P> struct HashTraits<JSC::Weak<P> > : SimpleClassHashTraits<JSC::Weak<P> > { };
-
-}
-
#endif // Weak_h