blob: f56abebd803789c4c568a72a0afb0c94a0289f8c [file]
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
#pragma once
#include "Memory.h"
#include "RawPtr.hpp"
#include "SpecialRefRegistry.hpp"
#include "Utils.hpp"
namespace kotlin::mm {
class ThreadData;
// TODO(KT-67741): Unify different SpecialRefs
// Stable reference to a Kotlin object.
// Every stable reference makes Kotlin object be in the root set.
// Use `create` and `dispose` to create and destroy the stable reference.
class StableRef : private MoveOnly {
public:
StableRef() noexcept = default;
// Cast raw ref into a stable reference.
explicit StableRef(RawSpecialRef* raw) noexcept : node_(SpecialRefRegistry::Node::fromRaw(raw)) {}
// Cast stable reference into raw ref.
[[nodiscard("must be manually disposed")]] explicit operator RawSpecialRef*() && noexcept {
// Make sure to move out from node_.
auto node = std::move(node_);
return node->asRaw();
}
// Create new stable reference for `obj`.
[[nodiscard("must be manually disposed")]] static StableRef create(ObjHeader* obj) noexcept;
// Dispose stable reference.
void dispose() && noexcept {
std::move(*this).disposeImpl();
}
// Get the underlying object.
// Always safe, because the object is guaranteed to be in the root set.
[[nodiscard("expensive pure function")]] ObjHeader* operator*() const noexcept {
RuntimeAssert(node_, "operator* on null StableRef");
return node_->ref();
}
static StableRef& reinterpret(RawSpecialRef*& raw) noexcept { return reinterpret_cast<StableRef&>(raw); }
static const StableRef& reinterpret(RawSpecialRef* const& raw) noexcept { return reinterpret_cast<const StableRef&>(raw); }
private:
raw_ptr<SpecialRefRegistry::Node> disposeImpl() && noexcept {
RuntimeAssert(node_, "Disposing null StableRef");
// Make sure to move out from node_.
auto node = std::move(node_);
// Can be safely called with any thread state.
node->releaseRef();
// Can be safely called with any thread state.
node->dispose();
return node;
}
raw_ptr<SpecialRefRegistry::Node> node_;
};
static_assert(sizeof(StableRef) == sizeof(void*), "StableRef must be a thin wrapper around pointer");
static_assert(alignof(StableRef) == alignof(void*), "StableRef must be a thin wrapper around pointer");
static_assert(std::is_trivially_destructible_v<StableRef>, "StableRef must be trivially destructible. Destruction is manual via dispose()");
} // namespace kotlin::mm