blob: 6341de897cd9fca9b079fcc88b187171bfecca7e [file] [edit]
/*
* Copyright (C) 2013 Google, Inc. All rights reserved.
* Copyright (C) 2015-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <wtf/CompactRefPtrTuple.h>
#include <wtf/Forward.h>
#include <wtf/Packed.h>
#include <wtf/RefPtr.h>
#include <wtf/ThreadAssertions.h>
#include <wtf/WeakRef.h>
namespace WTF {
#define USING_CAN_MAKE_WEAKPTR(BASE) \
using BASE::weakImpl; \
using BASE::weakCount; \
using BASE::WeakValueType; \
using BASE::WeakPtrImplType;
// Note: you probably want to inherit from CanMakeWeakPtr rather than use this directly.
template<typename T, typename WeakPtrImpl = DefaultWeakPtrImpl>
class WeakPtrFactory {
WTF_MAKE_NONCOPYABLE(WeakPtrFactory);
WTF_DEPRECATED_MAKE_FAST_ALLOCATED(WeakPtrFactory);
public:
using ObjectType = T;
using WeakPtrImplType = WeakPtrImpl;
WeakPtrFactory()
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
: m_thread(currentThreadLike)
#endif
{
}
void prepareForUseOnlyOnMainThread()
{
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
m_thread = mainThreadLike;
#endif
}
void prepareForUseOnlyOnNonMainThread()
{
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
m_thread = anyThreadLike;
#endif
}
~WeakPtrFactory()
{
if (m_impl)
m_impl->clear();
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
m_thread = anyThreadLike;
#endif
}
WeakPtrImpl* impl() const LIFETIME_BOUND
{
return m_impl.get();
}
SUPPRESS_NODELETE void NODELETE initializeIfNeeded(const T& object) const
{
if (m_impl)
return;
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
assertIsCurrent(m_thread);
#endif
static_assert(std::is_final_v<WeakPtrImpl>);
m_impl = adoptRef(*new WeakPtrImpl(const_cast<T*>(&object)));
}
template<typename U> WeakPtr<U, WeakPtrImpl> createWeakPtr(U& object, EnableWeakPtrThreadingAssertions enableWeakPtrThreadingAssertions = EnableWeakPtrThreadingAssertions::Yes) const
{
initializeIfNeeded(object);
ASSERT(&object == m_impl->template get<T>());
return WeakPtr<U, WeakPtrImpl>(*m_impl, enableWeakPtrThreadingAssertions);
}
void revokeAll()
{
if (RefPtr impl = std::exchange(m_impl, nullptr))
impl->clear();
}
unsigned weakPtrCount() const
{
return m_impl ? m_impl->refCount() - 1 : 0u;
}
#if ASSERT_ENABLED
bool isInitialized() const { return m_impl; }
#endif
private:
template<typename, typename, typename> friend class WeakPtr;
template<typename, typename> friend class WeakRef;
mutable RefPtr<WeakPtrImpl> m_impl;
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
NO_UNIQUE_ADDRESS ThreadLikeAssertion m_thread;
#endif
};
// Note: you probably want to inherit from CanMakeWeakPtrWithBitField rather than use this directly.
template<typename T, typename WeakPtrImpl = DefaultWeakPtrImpl>
class WeakPtrFactoryWithBitField {
WTF_MAKE_NONCOPYABLE(WeakPtrFactoryWithBitField);
WTF_DEPRECATED_MAKE_FAST_ALLOCATED(WeakPtrFactoryWithBitField);
public:
using ObjectType = T;
using WeakPtrImplType = WeakPtrImpl;
WeakPtrFactoryWithBitField()
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
: m_thread(currentThreadLike)
#endif
{
}
~WeakPtrFactoryWithBitField()
{
if (auto* pointer = m_impl.pointer())
pointer->clear();
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
m_thread = anyThreadLike;
#endif
}
WeakPtrImpl* impl() const LIFETIME_BOUND
{
return m_impl.pointer();
}
SUPPRESS_NODELETE void NODELETE initializeIfNeeded(const T& object) const
{
if (m_impl.pointer())
return;
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
assertIsCurrent(m_thread);
#endif
static_assert(std::is_final_v<WeakPtrImpl>);
m_impl.setPointer(adoptRef(*new WeakPtrImpl(const_cast<T*>(&object))));
}
template<typename U> WeakPtr<U, WeakPtrImpl> createWeakPtr(U& object, EnableWeakPtrThreadingAssertions enableWeakPtrThreadingAssertions = EnableWeakPtrThreadingAssertions::Yes) const
{
initializeIfNeeded(object);
ASSERT(&object == m_impl.pointer()->template get<T>());
return WeakPtr<U, WeakPtrImpl>(*m_impl.pointer(), enableWeakPtrThreadingAssertions);
}
void revokeAll()
{
if (auto* pointer = m_impl.pointer()) {
pointer->clear();
m_impl.setPointer(nullptr);
}
}
unsigned weakPtrCount() const
{
if (auto* pointer = m_impl.pointer())
return pointer->refCount() - 1;
return 0;
}
#if ASSERT_ENABLED
bool isInitialized() const { return m_impl.pointer(); }
#endif
uint16_t bitfield() const { return m_impl.type(); }
void setBitfield(uint16_t value) const { return m_impl.setType(value); }
private:
template<typename, typename, typename> friend class WeakPtr;
template<typename, typename> friend class WeakRef;
mutable CompactRefPtrTuple<WeakPtrImpl, uint16_t> m_impl;
#if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
NO_UNIQUE_ADDRESS ThreadLikeAssertion m_thread;
#endif
};
// We use lazy initialization of the WeakPtrFactory by default to avoid unnecessary initialization. Eager
// initialization is however useful if you plan to call construct WeakPtrs from other threads.
enum class WeakPtrFactoryInitialization { Lazy, Eager };
} // namespace WTF
using WTF::WeakPtrFactory;
using WTF::WeakPtrFactoryInitialization;