nk 1.0.0
C++ Numerical Computing Runtime
Loading...
Searching...
No Matches
heap_object.hpp
1// include/heap_object.hpp
2#pragma once
3
4#include <nk/value/data_buffer.hpp>
5#include <nk/value/dims.hpp>
6#include <nk/value/value_type.hpp>
7
8#include <atomic>
9#include <map>
10#include <memory>
11#include <memory_resource>
12#include <string>
13#include <vector>
14
15namespace nk {
16
17class Value; // forward decl
18struct ObjectState; // OBJECT instance state (see object.hpp); held by shared_ptr
19
20// ============================================================
21// HeapObject — ref-counted storage for non-scalar values
22//
23// Holds arrays, cells, structs, func handles.
24// Shared via COW (copy-on-write) through refCount.
25// ============================================================
26struct HeapObject
27{
28 std::atomic<int> refCount{1};
29 ValueType type = ValueType::EMPTY;
30 Dims dims;
31 std::pmr::memory_resource *mr = nullptr; // not owned; outlives the heap
32
33 // Array data (DOUBLE, INT*, UINT*, LOGICAL, CHAR, COMPLEX)
34 DataBuffer *buffer = nullptr;
35
36 // Extended data — allocated only for CELL, STRUCT, FUNC_HANDLE.
37 // The wrapper objects themselves (vector / map headers) are
38 // bookkeeping (~24-48 bytes) on the global heap; their internal
39 // buffers (which hold the actual user data — Value slots and map
40 // nodes) flow through `mr`. funcName is always a short identifier
41 // that fits in std::string's SBO; not user data, kept simple.
42 //
43 // STRUCT layout: array of structs (AoS). `structArray` always
44 // holds `numel()` per-element field maps; a "single struct" is
45 // simply `structArray->size() == 1`. The accessors `field()` /
46 // `structFields()` forward to `(*structArray)[0]` in that case so
47 // the user-facing single-struct semantics are preserved.
48 std::pmr::vector<Value> *cellData = nullptr;
49 std::pmr::vector<std::pmr::map<std::string, Value>> *structArray = nullptr;
50 // Insertion-order tracker for struct fields (BUG #15 fix).
51 // MATLAB's fieldnames() returns fields in the order they were first
52 // added; std::map iterates alphabetically so we maintain a parallel
53 // vector. Shared across all elements of a struct array (the field
54 // set is uniform per MATLAB semantics — see structFields() doc).
55 // nullptr until first STRUCT allocation; ownership matches structArray.
56 std::pmr::vector<std::string> *fieldOrder = nullptr;
57 std::string *funcName = nullptr;
58 // For anonymous-function handles only: the reconstructed source text
59 // (e.g. "@(x)x+1") that func2str returns. nullptr for named handles
60 // (which return their bare name) and all non-handle values.
61 std::string *funcSource = nullptr;
62
63 // ── OBJECT (class instance / array) — object.hpp / object_model.md ──
64 // objClass: registry key (class name). objStates: per-element instance
65 // state, length == numel() (a scalar object is a 1-element vector; the
66 // shape lives in `dims`). objIsHandle: cached from the class — drives
67 // clone() per element (share the shared_ptr for handle classes,
68 // deep-copy the ObjectState for value classes).
69 std::string *objClass = nullptr;
70 std::vector<std::shared_ptr<ObjectState>> objStates;
71 bool objIsHandle = false;
72
73 // Capacity for appendScalar amortization
74 size_t appendCapacity = 0;
75
76 HeapObject() = default;
77 ~HeapObject();
78
79 HeapObject(const HeapObject &) = delete;
80 HeapObject &operator=(const HeapObject &) = delete;
81
82 void addRef() { refCount.fetch_add(1, std::memory_order_relaxed); }
83 bool release() { return refCount.fetch_sub(1, std::memory_order_acq_rel) == 1; }
84
85 // Deep clone for COW
86 HeapObject *clone() const;
87};
88
89} // namespace nk
Core MATLAB-compatible multidimensional array and scalar value type.
Definition value.hpp:61