ladybird/Libraries/LibGC/WeakBlock.h
Andreas Kling 25a5ed94d6 LibGC: Add GC::Weak<T> as an alternative to AK::WeakPtr<T>
This is a weak pointer that integrates with the garbage collector.
It has a number of differences compared to AK::WeakPtr, including:

- The "control block" is allocated from a well-packed WeakBlock owned by
  the GC heap, not just a generic malloc allocation.

- Pointers to dead cells are nulled out by the garbage collector
  immediately before running destructors.

- It works on any GC::Cell derived type, meaning you don't have to
  inherit from AK::Weakable for the ability to be weakly referenced.

- The Weak always points to a control block, even when "null" (it then
  points to a null WeakImpl), which means one less null check when
  chasing pointers.
2025-10-17 17:22:16 +02:00

45 lines
903 B
C++

/*
* Copyright (c) 2025, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/IntrusiveList.h>
#include <LibGC/Forward.h>
#include <LibGC/Weak.h>
namespace GC {
class GC_API WeakBlock {
public:
static constexpr size_t BLOCK_SIZE = 16 * KiB;
static WeakBlock* create();
WeakImpl* allocate(Cell*);
void deallocate(WeakImpl*);
bool can_allocate() const { return m_freelist != nullptr; }
void sweep();
private:
WeakBlock();
~WeakBlock();
IntrusiveListNode<WeakBlock> m_list_node;
public:
using List = IntrusiveList<&WeakBlock::m_list_node>;
WeakImpl* m_freelist { nullptr };
static constexpr size_t IMPL_COUNT = (BLOCK_SIZE - sizeof(m_list_node) - sizeof(WeakImpl*)) / sizeof(WeakImpl);
WeakImpl m_impls[IMPL_COUNT];
};
static_assert(sizeof(WeakBlock) <= WeakBlock::BLOCK_SIZE);
}