+ xo-alloc + xo-object + xo-alloc docs + GC utests
This commit is contained in:
parent
8970f51dbd
commit
5f46b51f12
32 changed files with 2903 additions and 82 deletions
9
docs/CMakeLists.txt
Normal file
9
docs/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# xo-alloc/docs/CMakeLists.txt
|
||||
|
||||
xo_doxygen_collect_deps()
|
||||
xo_docdir_doxygen_config()
|
||||
xo_docdir_sphinx_config(
|
||||
index.rst install.rst introduction.rst implementation.rst)
|
||||
|
||||
# see xo-reader/doc or xo-unit/doc for working examples
|
||||
# example.rst install.rst implementation.rst
|
||||
41
docs/README
Normal file
41
docs/README
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
standalone build
|
||||
|
||||
+-----------------------------------------------+
|
||||
| cmake |
|
||||
| CMakeLists.txt |
|
||||
| $PREFIX/share/cmake/xo_macros/xo_cxx.cmake |
|
||||
+-----------------------------------------------+
|
||||
|
|
||||
| +----------------------+
|
||||
+------------------------------------------------->| .build/docs/Doxyfile |
|
||||
| +----------------------+
|
||||
| ^
|
||||
| (cmake) |
|
||||
| /------------/
|
||||
| |
|
||||
| +---------------------------------------+ +-----------------+
|
||||
+---->| doxygen |--------->| .build/docs/dox |
|
||||
| | $PREFIX/share/xo-macros/Doxyfile.in | (doxygen)| +- html/ |
|
||||
| +---------------------------------------+ | +- xml/ |
|
||||
| +-----------------+
|
||||
| |
|
||||
| |(sphinx)
|
||||
| |
|
||||
| v
|
||||
| +---------------------------------------+ +--------------------+
|
||||
\---->| sphinx |------->| .build/docs/sphinx |
|
||||
| +- conf.py | | +- html/ |
|
||||
| +- _static/ | +--------------------+
|
||||
| +- *.rst |
|
||||
+---------------------------------------+
|
||||
|
||||
umbrella build relies on top-level cmake macros
|
||||
|
||||
files
|
||||
|
||||
README this file
|
||||
CMakeLists.txt build entry point
|
||||
conf.py sphinx config
|
||||
_static static files for sphinx
|
||||
|
||||
index.rst toplevel sphinx document; entry point
|
||||
1
docs/_static/README
vendored
Normal file
1
docs/_static/README
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
add any static {.html, .js, ..} files for sphinx to pickup here
|
||||
BIN
docs/_static/img/favicon.ico
vendored
Normal file
BIN
docs/_static/img/favicon.ico
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 303 KiB |
39
docs/conf.py
Normal file
39
docs/conf.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# For the full list of built-in configuration values, see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||
|
||||
project = 'xo alloc documentation'
|
||||
copyright = '2025, Roland Conybeare'
|
||||
author = 'Roland Conybeare'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
||||
#extensions = []
|
||||
extensions = [ "breathe",
|
||||
"sphinx.ext.mathjax", # inline math
|
||||
"sphinx.ext.autodoc", # generate info from docstrings
|
||||
"sphinxcontrib.ditaa", # diagrams-through-ascii-art
|
||||
"sphinxcontrib.plantuml" # text -> uml diagrams
|
||||
]
|
||||
|
||||
# note: breathe requires doxygen xml output -> must have GENERATE_XML = YES in Doxyfile.in
|
||||
# match project name in Doxyfile.in
|
||||
breathe_default_project = "xodoxxml"
|
||||
|
||||
templates_path = ['_templates']
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||
|
||||
#html_theme = 'alabaster'
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_static_path = ['_static']
|
||||
html_favicon = '_static/img/favicon.ico'
|
||||
202
docs/implementation.rst
Normal file
202
docs/implementation.rst
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
.. _implementation:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Library
|
||||
=======
|
||||
|
||||
Library dependency tower for *xo-alloc*:
|
||||
|
||||
.. ditaa::
|
||||
|
||||
+------------------------------------------+
|
||||
| xo_alloc |
|
||||
+------------------------------------------+
|
||||
| xo_indentlog |
|
||||
+------------------------------------------+
|
||||
|
||||
Install instructions :doc:`here<install>`
|
||||
|
||||
Components
|
||||
==========
|
||||
|
||||
Abstraction tower for *xo-alloc* components:
|
||||
|
||||
.. ditaa::
|
||||
:--scale: 0.85
|
||||
|
||||
+----------------+-------------+
|
||||
| IAlloc | Object |
|
||||
+----------------+-------------+
|
||||
|
||||
+-------------+ +-------------+
|
||||
| GC | | Forwarding1 |
|
||||
+-------------+ +-------------+
|
||||
| ListAlloc |
|
||||
+-------------+
|
||||
| ArenaAlloc |
|
||||
+-------------+
|
||||
|
||||
* *IAlloc*
|
||||
Allocator interface.
|
||||
|
||||
* *Object*
|
||||
Root Object Interface for types participating in garbage collection
|
||||
|
||||
* *GC*
|
||||
Incremental compacting garbage collector.
|
||||
|
||||
* *ListAlloc*
|
||||
Auto-expanding allocator. Contains a collection of ArenaAllocs
|
||||
|
||||
* *ArenaAlloc*
|
||||
Arena allocator (a.k.a bump allocator).
|
||||
|
||||
* *Object*
|
||||
Interface for types that participate in garbage collection
|
||||
|
||||
* *Forwarding1*
|
||||
Forwarding pointer. Supports the Object interface;
|
||||
used internally by GC during evacuation.
|
||||
|
||||
Key Points
|
||||
----------
|
||||
|
||||
* Allocators can be reset, but do not support freeing of individual allocs.
|
||||
* GC works with types that implement auxiliary GC-support methods.
|
||||
Such types must inherit Object.
|
||||
* A region may uses multiple arenas, but because of allocation activity
|
||||
since the last GC. If necessary, GC will allocate a new to-space with a
|
||||
single arena that's large enough to accomodate all objects that might survive
|
||||
from a from-space that has acquired multiple arenas.
|
||||
Intent is to scale up to find application's working set size, then stabilize
|
||||
|
||||
Components
|
||||
==========
|
||||
|
||||
Allocators
|
||||
----------
|
||||
|
||||
Inheritance
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. uml::
|
||||
:caption: allocators
|
||||
:scale: 99%
|
||||
:align: center
|
||||
|
||||
class IAlloc {
|
||||
+ alloc()
|
||||
+ alloc_gc_copy()
|
||||
+ checkpoint()
|
||||
+ clear()
|
||||
}
|
||||
|
||||
class ArenaAlloc {
|
||||
+ free_ptr()
|
||||
- lo_ : byte*
|
||||
- checkpoint_ : byte*
|
||||
- limit_ : byte*
|
||||
}
|
||||
|
||||
IAlloc <|-- ArenaAlloc
|
||||
|
||||
class ListAlloc {
|
||||
+ expand()
|
||||
+ free_ptr()
|
||||
- start_z_
|
||||
- hd_
|
||||
- full_l_
|
||||
}
|
||||
|
||||
IAlloc <|-- ListAlloc
|
||||
|
||||
class GC {
|
||||
+ add_gc_root()
|
||||
+ request_gc()
|
||||
+ gc_statistics()
|
||||
- gc_root_v_[] : Object**
|
||||
- nursery_[2] : ListAlloc*
|
||||
- tenured_[2] : ListAlloc*
|
||||
}
|
||||
|
||||
IAlloc <|-- GC
|
||||
|
||||
|
||||
Composition
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. uml::
|
||||
:caption: allocator composition
|
||||
:scale: 99%
|
||||
:align: center
|
||||
|
||||
object gc<<GC>>
|
||||
gc : nursery[from] = n0
|
||||
gc : nursery[to] = n1
|
||||
gc : tenured[from] = t0
|
||||
gc : tenured[to] = t1
|
||||
|
||||
object n0<<ListAlloc>>
|
||||
|
||||
object n1<<ListAlloc>>
|
||||
|
||||
object t0<<ListAlloc>>
|
||||
|
||||
object t1<<ListAlloc>>
|
||||
|
||||
gc o-- n0
|
||||
gc o-- n1
|
||||
gc o-- t0
|
||||
gc o-- t1
|
||||
|
||||
|
||||
Each ListAlloc composes like this:
|
||||
|
||||
.. uml::
|
||||
:caption: ListAlloc composition
|
||||
:scale: 99%
|
||||
:align: center
|
||||
|
||||
object x<<ListAlloc>>
|
||||
x : hd_ = a0
|
||||
x : full_l = {a1, a2}
|
||||
|
||||
object a0<<ArenaAlloc>>
|
||||
a0 : lo_ = 0
|
||||
a0 : free_ = 12345
|
||||
a0 : hi_ = 1000000
|
||||
|
||||
object a1<<ArenaAlloc>>
|
||||
|
||||
object a2<<ArenaAlloc>>
|
||||
|
||||
x o-- a0
|
||||
x o-- a1
|
||||
x o-- a2
|
||||
|
||||
Here *a1* and *a2* are full, while *a0* can still allocate memory.
|
||||
|
||||
Objects
|
||||
|
||||
.. uml::
|
||||
:caption: objects
|
||||
:scale: 99%
|
||||
:align: center
|
||||
|
||||
class Object {
|
||||
+ _is_forwarded()
|
||||
+ _offset_destination()
|
||||
+ _forward_to()
|
||||
+ _destination()
|
||||
+ _shallow_size()
|
||||
+ _shallow_copy()
|
||||
+ _forward_children()
|
||||
}
|
||||
|
||||
class Forwarding1 {
|
||||
- dest_ : Object*
|
||||
}
|
||||
|
||||
Object <|-- Forwarding1
|
||||
14
docs/index.rst
Normal file
14
docs/index.rst
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# xo-alloc documentation master file
|
||||
|
||||
xo-alloc documentation
|
||||
======================
|
||||
|
||||
xo-alloc provides arena allocators and a generation garbage collector
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: xo-alloc contents
|
||||
|
||||
install
|
||||
introduction
|
||||
implementation
|
||||
120
docs/install.rst
Normal file
120
docs/install.rst
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
.. _install:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
Source
|
||||
======
|
||||
|
||||
Source code lives on github `here`_
|
||||
|
||||
.. _here: https://github.com/rconybea/xo-alloc
|
||||
|
||||
To clone from git:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/rconybea/xo-alloc
|
||||
|
||||
Tested with gcc 13.3
|
||||
|
||||
Install
|
||||
=======
|
||||
|
||||
One-step Install
|
||||
----------------
|
||||
|
||||
Install along with the reset of *XO* from `xo-umbrella2 source`_
|
||||
|
||||
.. _xo-umbrella2 source: https://github.com/rconybea/xo-umbrella2
|
||||
|
||||
Minimal Install
|
||||
---------------
|
||||
|
||||
To build+install just required dependencies:
|
||||
``xo-alloc`` uses several supporting libraries from the *XO* project:
|
||||
|
||||
- `xo-indentlog source`_ (structured logging)
|
||||
- `xo-cmake source`_ (shared cmake macros)
|
||||
|
||||
.. _xo-indentlog source: https://github.com/rconybea/indentlog
|
||||
.. _xo-cmake source: https://github.com/rconybea/xo-cmake
|
||||
|
||||
Building from source
|
||||
--------------------
|
||||
|
||||
Install scripts for XO libraries depend on helper scripts installed from `xo-cmake`.
|
||||
|
||||
Preamble:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir -p ~/proj/xo
|
||||
cd ~/proj/xo
|
||||
|
||||
git clone https://github.com/rconybea/xo-cmake
|
||||
|
||||
PREFIX=/usr/local # ..or desired installation prefix
|
||||
|
||||
# want PREFIX/bin in PATH to use xo-cmake helpers
|
||||
PATH=$PREFIX/bin:$PATH
|
||||
|
||||
Install `xo-cmake`:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake -B xo-cmake/.build -S xo-cmake
|
||||
cmake --install xo-cmake/.build
|
||||
|
||||
Install remaining dependencie(s) in topological order:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
xo-build --clone --configure --build --install xo-indentlog
|
||||
xo-build --clone --configure --build --install xo-alloc
|
||||
|
||||
Directories under ``PREFIX`` will then contain:
|
||||
|
||||
.. code-block::
|
||||
|
||||
PREFIX
|
||||
+- bin
|
||||
| +- xo-build
|
||||
| +- xo-cmake-config
|
||||
| \- xo-cmake-lcov-harness
|
||||
+- include
|
||||
| \- xo
|
||||
| +- alloc/
|
||||
| \- indentlog/
|
||||
+- lib
|
||||
| +- cmake
|
||||
| | +- xo_alloc/
|
||||
| | \- indentlog/
|
||||
| +- lib*.so
|
||||
+- share
|
||||
+- cmake
|
||||
| \- xo_macros
|
||||
| +- code-coverage.cmake
|
||||
| +- xo-project-macros.cmake
|
||||
| \- xo_cxx.cmake
|
||||
+- etc
|
||||
| \- xo
|
||||
| \- subsystem-list
|
||||
\- xo-macros
|
||||
+- Doxyfile.in
|
||||
+- gen-ccov.in
|
||||
\- xo-bootstrap-macros.cmake
|
||||
|
||||
CMake Support
|
||||
-------------
|
||||
|
||||
To use built-in cmake support, when using ``xo-alloc`` from another project:
|
||||
|
||||
Make sure ``PREFIX/lib/cmake`` is searched by cmake (for example include it in ``CMAKE_PREFIX_PATH``)
|
||||
|
||||
Add to your ``CMakeLists.txt``:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
FindPackage(xo_alloc CONFIG REQUIRED)
|
||||
target_link_libraries(mytarget INTERFACE xo_alloc)
|
||||
268
docs/introduction.rst
Normal file
268
docs/introduction.rst
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
.. _introduction:
|
||||
|
||||
.. toctree
|
||||
:maxdepth: 2
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The ``xo-alloc`` library provides a in incremental, generational collector for c++ code.
|
||||
|
||||
Features:
|
||||
|
||||
* *incremental* - can reasonably expect short pause times.
|
||||
* *generational* - focuses effort on collecting young objects,
|
||||
on the basis that they're more likely to be garbage.
|
||||
* *compacting* - each garbage collection cycle evacuates survivors to contiguous memory,
|
||||
so effect is to defragment.
|
||||
* *collects cycles* - collection algorithm naturally collects cyclic references
|
||||
|
||||
Tradeoffs:
|
||||
|
||||
* Application is responsible for spilling register values and protecting hardware stack,
|
||||
since garbage collector cannot indepndently distinguish collectable object pointers from
|
||||
non-pointer values.
|
||||
|
||||
* GC will not spontaneously run without permission. Instead will set a pending bit, with GC
|
||||
occurring only when application releases it (e.g. when stack+registers are known to be empty of values
|
||||
subject to GC).
|
||||
|
||||
* GC implementation is single-threaded. It cannot run in parallel with the mutator (i.e. application code)
|
||||
In return this allows GC to be only lightly coupled with application.
|
||||
|
||||
* GC divides each generation into separate from- and to- spaces. A collection cycle copies surviving
|
||||
objects out of from-space. Once complete, the entire from-space is treated as empty, and available to
|
||||
become to-space on a future cycle. This means that at any time only half of allocated memory is available
|
||||
to the application; the rest is waiting to receive survivors from the next GC cycle.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
Garbage Collector
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The garbage collector supports two generations, labelled *nursery* and *tenured*.
|
||||
Nursery objects that survive two collection cycles are promoted to tenured space.
|
||||
Nursery and tenured objects are kept in separate memory areas, instead of being interspersed.
|
||||
|
||||
Collection cycles come in two flavors:
|
||||
|
||||
1. *incremental* collections - these collect only the nursery space.
|
||||
|
||||
2. *full* collections - these collect both nursery and tenured spaces.
|
||||
Full collection may incur noticeable GC pauses.
|
||||
|
||||
Application Interaction
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Application code that interacts with GC has several responsibilities.
|
||||
|
||||
1. application must explicitly invoke GC, when convenient. Since in general any GC-eligible object
|
||||
may get moved by the collector: once a collection cycle completes,
|
||||
it's up to the application to re-load pointers from memory addresses
|
||||
(GC roots) that have been shared with the collector.
|
||||
|
||||
2. application must identify a set of GC roots. GC preserves everything reachable from any GC root
|
||||
|
||||
3. The collector needs to know how to traverse GC-managed objects.
|
||||
We teach it this by requiring that such objects inherit the ``xo::Object`` interface,
|
||||
and implement auxiliary function detailed below.
|
||||
|
||||
4. GC also needs to know when a mutation alters a pointer from one GC-managed object to another.
|
||||
In particular, GC needs to track pointers from tenured space into nursery space,
|
||||
and update them when an incremental collection moves nursery objects.
|
||||
We do this by requiring application code use a GC-provided assignment primitive
|
||||
on GC-eligible pointers.
|
||||
|
||||
|
||||
Example GC Use
|
||||
--------------
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
#include "xo/object/List.hpp" // polymorphic List with GC support
|
||||
#include "xo/object/String.hpp" // string type with GC support
|
||||
#include "xo/alloc/GC.hpp"
|
||||
|
||||
int main() {
|
||||
using xo::gc::Config;
|
||||
using xo::obj::String;
|
||||
using xo::obj::List;
|
||||
using xo::gp;
|
||||
|
||||
Config config = { .initial_nursery_z_ = 50*1000,
|
||||
.initial_tenured_z_ = 10*1000*1000,
|
||||
.debug_flag_ = false };
|
||||
|
||||
up<GC> gc = GC::make(config);
|
||||
|
||||
Object::mm = gc; // use GC for allocation of Object (+ derived classes)
|
||||
|
||||
gc->disable_gc(); // gc forbidden
|
||||
|
||||
// tiny example data structure
|
||||
gp<String> s1 = String::copy("hello");
|
||||
gp<String> s2 = String::copy(", ");
|
||||
gp<String> s3 = String::copy("world!");
|
||||
gp<List> list = List::cons(s1, List::cons(s2, List::cons(s3, List::nil)));
|
||||
|
||||
// tell GC what to preserve
|
||||
gc->add_gc_root(reinterpret_cast<Object **>(list.ptr_address());
|
||||
|
||||
gc->enable_gc(); // triggers immediate gc
|
||||
|
||||
// s1, s2, s3 invalid.
|
||||
// list at new address
|
||||
|
||||
std::cout << "list.size=" << list->size << std::endl;
|
||||
}
|
||||
|
||||
GC-Eligible Types
|
||||
-----------------
|
||||
|
||||
Or, how to inherit ``xo::Object`` and provide GC support
|
||||
|
||||
A type Foo that inherits ``xo::Object`` needs to provide overrides for Object methods ``_shallow_size()``,
|
||||
``_shallow_copy()`` and ``_forward_children()``:
|
||||
|
||||
Typical Pattern
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
GC support methods look something like this:
|
||||
|
||||
* class definition
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
#include "xo/alloc/Object.hpp"
|
||||
|
||||
namespace xo {
|
||||
class Foo : public xo::Object {
|
||||
public:
|
||||
...
|
||||
virtual std::size_t _shallow_size() const override;
|
||||
virtual Object * _shallow_copy() const override;
|
||||
virtual std::size_t _forward_children() override;
|
||||
};
|
||||
}
|
||||
|
||||
* use overloaded ``operator new``
|
||||
|
||||
A GC-eligible class will allocate instances using the ``MMPtr`` overload.
|
||||
This allocates memory in GC-owned space
|
||||
|
||||
.. code-block::cpp
|
||||
:linenos:
|
||||
|
||||
gp<Foo> Foo::make(...) {
|
||||
...
|
||||
return new MMPtr(mm) Foo(...);
|
||||
}
|
||||
|
||||
* ``_shallow_size()`` returns the amount of memory used by the subject:
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
std::size_t Foo::_shallow_size() const { return sizeof(Foo); }
|
||||
|
||||
* ``_shallow_copy()`` is invoked during GC to create a copy of the subject
|
||||
|
||||
It should use the ``xo::Cpof`` argument to ``operator new``.
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
Object *
|
||||
Foo::_shallow_copy() const;
|
||||
|
||||
* ``_forward_children()`` is invoked during GC to vist child ``xo::Object`` pointers
|
||||
to make sure they survive
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
std::size_t
|
||||
Foo::_forward_children();
|
||||
|
||||
Atomic Types Without Object Pointers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Plain-old-data classes without embedded pointers
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
Object *
|
||||
Foo::_shallow_copy() const {
|
||||
return new (Cpof(this)) Foo(*this);
|
||||
}
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
std::size_t
|
||||
Foo::_forward_children() { return Foo::_shallow_size(); }
|
||||
|
||||
For example see ``xo::obj::String`` in ``xo-object``
|
||||
|
||||
Non-GC Objects
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
A class *Foo* that inherits ``xo::Object`` can opt-out of garbage collection by
|
||||
omitting the ``MMptr(mm)`` overload.
|
||||
|
||||
In that case `Foo::_shallow_size()`, `Foo::_shallow_copy()` and `Foo::_forward_children()`
|
||||
will not be called:
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
std::size_t Foo::_shallow_size() const { return sizeof(Foo); }
|
||||
Object * Foo::_shallow_copy() const { assert(false); return nullptr; }
|
||||
std::size_t Foo::_forward_children() { assert(false); return 0; }
|
||||
|
||||
For example see ``xo::obj::Boolean`` in ``xo-object``
|
||||
|
||||
Structs Containing Object Pointers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A class with object pointers needs to tell GC how to traverse them
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
#include "xo/alloc/Object.hpp"
|
||||
|
||||
namespace xo {
|
||||
class Foo : public xo::Object {
|
||||
public:
|
||||
...
|
||||
virtual std::size_t _shallow_size() const override;
|
||||
virtual Object * _shallow_copy() const override;
|
||||
virtual std::size_t _forward_children() override;
|
||||
|
||||
private:
|
||||
gp<Object> bar_;
|
||||
gp<Object> quux_;
|
||||
};
|
||||
}
|
||||
|
||||
* ``_forward_children()`` is invoked during GC to fixup child pointers
|
||||
that refer to forwarding objects:
|
||||
|
||||
.. code-block:: cpp
|
||||
:linenos:
|
||||
|
||||
std::size_t
|
||||
Foo::_forward_children()
|
||||
{
|
||||
Object::_forward_inplace(bar_);
|
||||
Object::_forward_inplace(quux_);
|
||||
|
||||
return Foo::_shallow_size();
|
||||
}
|
||||
|
||||
For example see ``xo::obj::List`` in ``xo-object``
|
||||
Loading…
Add table
Add a link
Reference in a new issue