PyDecisionGraph 0.3.1.post2__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- decision_graph/__init__.py +26 -0
- decision_graph/decision_tree/__init__.py +85 -0
- decision_graph/decision_tree/bake/__infra__.pxd +502 -0
- decision_graph/decision_tree/bake/__init__.pxd +502 -0
- decision_graph/decision_tree/bake/__init__.py +29 -0
- decision_graph/decision_tree/bake/c_action.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_action.h +324 -0
- decision_graph/decision_tree/bake/c_action.pxd +54 -0
- decision_graph/decision_tree/bake/c_action.pyi +126 -0
- decision_graph/decision_tree/bake/c_action.pyx +65 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pxd +24 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pyi +61 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pyx +109 -0
- decision_graph/decision_tree/bake/c_bake.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_bake.h +629 -0
- decision_graph/decision_tree/bake/c_bake.pxd +52 -0
- decision_graph/decision_tree/bake/c_bake.pyi +151 -0
- decision_graph/decision_tree/bake/c_bake.pyx +142 -0
- decision_graph/decision_tree/bake/c_collections.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_collections.h +692 -0
- decision_graph/decision_tree/bake/c_collections.pxd +52 -0
- decision_graph/decision_tree/bake/c_collections.pyi +193 -0
- decision_graph/decision_tree/bake/c_collections.pyx +161 -0
- decision_graph/decision_tree/bake/c_const.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_const.h +395 -0
- decision_graph/decision_tree/bake/c_const.pxd +56 -0
- decision_graph/decision_tree/bake/c_const.pyi +305 -0
- decision_graph/decision_tree/bake/c_const.pyx +278 -0
- decision_graph/decision_tree/bake/c_edge.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_edge.h +511 -0
- decision_graph/decision_tree/bake/c_edge.pxd +117 -0
- decision_graph/decision_tree/bake/c_edge.pyi +192 -0
- decision_graph/decision_tree/bake/c_edge.pyx +270 -0
- decision_graph/decision_tree/bake/c_eval.h +848 -0
- decision_graph/decision_tree/bake/c_eval.pxd +40 -0
- decision_graph/decision_tree/bake/c_expr.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_expr.h +1900 -0
- decision_graph/decision_tree/bake/c_expr.pxd +129 -0
- decision_graph/decision_tree/bake/c_expr.pyi +280 -0
- decision_graph/decision_tree/bake/c_expr.pyx +272 -0
- decision_graph/decision_tree/bake/c_hierarchy.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
- decision_graph/decision_tree/bake/c_hierarchy.pxd +71 -0
- decision_graph/decision_tree/bake/c_hierarchy.pyi +409 -0
- decision_graph/decision_tree/bake/c_hierarchy.pyx +277 -0
- decision_graph/decision_tree/bake/c_logic_group.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
- decision_graph/decision_tree/bake/c_logic_group.pxd +162 -0
- decision_graph/decision_tree/bake/c_logic_group.pyi +264 -0
- decision_graph/decision_tree/bake/c_logic_group.pyx +308 -0
- decision_graph/decision_tree/bake/c_node.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_node.h +2660 -0
- decision_graph/decision_tree/bake/c_node.pxd +381 -0
- decision_graph/decision_tree/bake/c_node.pyi +438 -0
- decision_graph/decision_tree/bake/c_node.pyx +639 -0
- decision_graph/decision_tree/bake/c_reconstruct.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_reconstruct.pxd +63 -0
- decision_graph/decision_tree/bake/c_reconstruct.pyi +60 -0
- decision_graph/decision_tree/bake/c_reconstruct.pyx +252 -0
- decision_graph/decision_tree/bake/c_var.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_var.h +2054 -0
- decision_graph/decision_tree/bake/c_var.pxd +205 -0
- decision_graph/decision_tree/bake/c_var.pyi +271 -0
- decision_graph/decision_tree/bake/c_var.pyx +228 -0
- decision_graph/decision_tree/capi/__init__.pxd +33 -0
- decision_graph/decision_tree/capi/__init__.py +57 -0
- decision_graph/decision_tree/capi/c_abc.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_abc.pxd +246 -0
- decision_graph/decision_tree/capi/c_abc.pyi +770 -0
- decision_graph/decision_tree/capi/c_abc.pyx +1529 -0
- decision_graph/decision_tree/capi/c_collection.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_collection.pxd +22 -0
- decision_graph/decision_tree/capi/c_collection.pyi +245 -0
- decision_graph/decision_tree/capi/c_collection.pyx +138 -0
- decision_graph/decision_tree/capi/c_node.cp313-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_node.pxd +95 -0
- decision_graph/decision_tree/capi/c_node.pyi +492 -0
- decision_graph/decision_tree/capi/c_node.pyx +551 -0
- decision_graph/decision_tree/exc.py +189 -0
- decision_graph/decision_tree/native/__init__.py +57 -0
- decision_graph/decision_tree/native/abc.py +1164 -0
- decision_graph/decision_tree/native/collection.py +134 -0
- decision_graph/decision_tree/native/node.py +521 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_action.c +16320 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_action.h +324 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_allocator_protocol.c +12473 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_bake.c +16485 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_bake.h +629 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_collections.c +17381 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_collections.h +692 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_const.c +20815 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_const.h +395 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_edge.c +20696 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_edge.h +511 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_eval.h +848 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_expr.c +22065 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_expr.h +1900 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.c +23267 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.c +22434 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_node.c +28385 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_node.h +2660 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_reconstruct.c +15955 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_var.c +16881 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_var.h +2054 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_abc.c +59143 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_collection.c +19967 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_node.c +39220 -0
- decision_graph/logic_group/__init__.py +25 -0
- decision_graph/logic_group/base.py +100 -0
- decision_graph/logic_group/pending_request.py +384 -0
- decision_graph/webui/__init__.py +24 -0
- decision_graph/webui/bake/__init__.py +65 -0
- decision_graph/webui/bake/app.py +488 -0
- decision_graph/webui/bake/static/d3.v7.min.js +2 -0
- decision_graph/webui/bake/static/script.js +1440 -0
- decision_graph/webui/bake/static/style.css +920 -0
- decision_graph/webui/bake/templates/index.html +183 -0
- decision_graph/webui/bake/templates/offline.html +184 -0
- decision_graph/webui/capi/__init__.py +54 -0
- decision_graph/webui/capi/app.py +366 -0
- decision_graph/webui/capi/main.py +53 -0
- decision_graph/webui/capi/static/d3.v7.min.js +2 -0
- decision_graph/webui/capi/static/script.js +1026 -0
- decision_graph/webui/capi/static/style.css +656 -0
- decision_graph/webui/capi/templates/index.html +93 -0
- decision_graph/webui/capi/templates/offline.html +94 -0
- decision_graph/webui/native/__init__.py +54 -0
- decision_graph/webui/native/app.py +366 -0
- decision_graph/webui/native/main.py +53 -0
- decision_graph/webui/native/static/d3.v7.min.js +2 -0
- decision_graph/webui/native/static/script.js +1026 -0
- decision_graph/webui/native/static/style.css +656 -0
- decision_graph/webui/native/templates/index.html +93 -0
- decision_graph/webui/native/templates/offline.html +94 -0
- pydecisiongraph-0.3.1.post2.dist-info/METADATA +130 -0
- pydecisiongraph-0.3.1.post2.dist-info/RECORD +144 -0
- pydecisiongraph-0.3.1.post2.dist-info/WHEEL +5 -0
- pydecisiongraph-0.3.1.post2.dist-info/licenses/LICENSE +373 -0
- pydecisiongraph-0.3.1.post2.dist-info/top_level.txt +2 -0
- tests/bake_c_evaluator.cp313-win_amd64.pyd +0 -0
- tests/bake_eval_probe.cp313-win_amd64.pyd +0 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
#ifndef C_DCG_BAKE_ACTION_H
|
|
2
|
+
#define C_DCG_BAKE_ACTION_H
|
|
3
|
+
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
#include <stddef.h>
|
|
6
|
+
#include <stdint.h>
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
|
|
9
|
+
#include <cbase/allocator_protocol/c_allocator_protocol.h>
|
|
10
|
+
|
|
11
|
+
#include <decision_graph/decision_tree/bake/c_node.h>
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* The action family: the leaves that say what the graph decides (NOACTION /
|
|
15
|
+
* LONGACTION / SHORTACTION / CANCELACTION / CLEARACTION).
|
|
16
|
+
*
|
|
17
|
+
* Every one of them is the same struct - the base node and the two fields the
|
|
18
|
+
* builder needs to place it: whether it should be connected to the active node
|
|
19
|
+
* as it is built, and whatever data the caller hangs off it. The family's _free
|
|
20
|
+
* is the base free today, because nothing it carries goes beyond the block; it
|
|
21
|
+
* stays a function of its own - and the dispatcher in c_hierarchy.h routes the
|
|
22
|
+
* whole family through it - because the action types are the ones the capi keeps
|
|
23
|
+
* growing (a trade's signal, the payload a caller hangs off it), and their
|
|
24
|
+
* teardown is where that growth will land. The graph's own types - the root and
|
|
25
|
+
* the breakpoint - live in c_hierarchy.h too.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
// ========== Constants ==========
|
|
29
|
+
|
|
30
|
+
/* DCG_DEF_REPR_NOACTION is defined in c_node.h - see the note there. */
|
|
31
|
+
/* DCG_DEF_REPR_PLACEHOLDER is defined in c_node.h too: the placeholder is a
|
|
32
|
+
* plain node rather than an action, and its constructor sits there. */
|
|
33
|
+
|
|
34
|
+
// ========== Structs ==========
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @brief An action node: the base node plus what the builder needs to place it.
|
|
38
|
+
*
|
|
39
|
+
* `auto_connect` records how the node was built, not what it is: the plain
|
|
40
|
+
* constructors leave it false and the connect ones set it to what they were
|
|
41
|
+
* asked for - "join the active node" is what the capi does with it. Nothing
|
|
42
|
+
* acts on the field afterwards; it is there for whoever reads the node back.
|
|
43
|
+
* `action_data` is the caller's opaque pointer and is NOT owned: it is carried
|
|
44
|
+
* to whoever evaluates the action, and stays the caller's to release.
|
|
45
|
+
*
|
|
46
|
+
* `sig` is the signal the action stands for, and it is what the capi's action
|
|
47
|
+
* classes carry in the same field name: +1 for a long, -1 for a short, 0 for
|
|
48
|
+
* everything that decides nothing. The type is the authority the signal follows;
|
|
49
|
+
* the variant constructors, whose types all decide nothing, pass 0.
|
|
50
|
+
*
|
|
51
|
+
* The base node must stay the FIRST member: a dcg_action_node* is therefore a
|
|
52
|
+
* valid dcg_node*.
|
|
53
|
+
*/
|
|
54
|
+
typedef struct dcg_action_node {
|
|
55
|
+
dcg_node base; // The common node header. Must stay first.
|
|
56
|
+
bool auto_connect; // Whether the builder should connect it as it is made.
|
|
57
|
+
ssize_t sig; // The action's signal: +1 long, -1 short, 0 for the rest.
|
|
58
|
+
void* action_data; // NOT owned - the caller's own payload.
|
|
59
|
+
} dcg_action_node;
|
|
60
|
+
|
|
61
|
+
// ========== Forward Declarations ==========
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* The manager a connect constructor joins through. Only the pointer is named
|
|
65
|
+
* here: connecting needs the manager's stacks, which c_logic_group.h defines,
|
|
66
|
+
* and that header includes this one - so the bodies live there and this header
|
|
67
|
+
* carries the family's shape.
|
|
68
|
+
*/
|
|
69
|
+
typedef struct dcg_logic_group_manager dcg_logic_group_manager;
|
|
70
|
+
|
|
71
|
+
// Lifecycle - the action family (a type, its repr, and its two fields)
|
|
72
|
+
static inline dcg_action_node* c_dcg_node_new_action(dcg_node_type action_type, const char* repr, ssize_t sig, void* action_data, allocator_protocol* allocator);
|
|
73
|
+
static inline void c_dcg_node_free_action(dcg_action_node* node);
|
|
74
|
+
|
|
75
|
+
static inline dcg_action_node* c_dcg_node_new_action_trade(dcg_node_type action_type, allocator_protocol* allocator);
|
|
76
|
+
static inline dcg_action_node* c_dcg_node_new_action_clear(allocator_protocol* allocator);
|
|
77
|
+
|
|
78
|
+
static inline int c_dcg_node_auto_fill(dcg_node* node);
|
|
79
|
+
|
|
80
|
+
// ========== Lifecycle Methods ==========
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @brief Allocate an action leaf of an explicit type - standalone.
|
|
84
|
+
*
|
|
85
|
+
* The node joins no graph here: connecting means taking the arm the active
|
|
86
|
+
* node reserved, and that needs a manager to say which node is active. These
|
|
87
|
+
* constructors build a node nobody owns yet; the connect variants below take
|
|
88
|
+
* the manager and do the joining.
|
|
89
|
+
*
|
|
90
|
+
* @param action_type An action type.
|
|
91
|
+
* @param repr Display text to copy (may be NULL: naming the type is the
|
|
92
|
+
* caller's, which is what the variants below do).
|
|
93
|
+
* @param sig The signal to carry (+1 long, -1 short, 0 for the rest).
|
|
94
|
+
* @param action_data The caller's payload (not owned; may be NULL).
|
|
95
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
96
|
+
* @return The node, or NULL on OOM / invalid type.
|
|
97
|
+
*/
|
|
98
|
+
static inline dcg_action_node* c_dcg_node_new_action(dcg_node_type action_type, const char* repr, ssize_t sig, void* action_data, allocator_protocol* allocator) {
|
|
99
|
+
if (!c_dcg_node_type_is_action(action_type)) return NULL;
|
|
100
|
+
|
|
101
|
+
dcg_action_node* node = (dcg_action_node*) c_ap_alloc(sizeof(dcg_action_node), allocator);
|
|
102
|
+
if (!node) return NULL;
|
|
103
|
+
|
|
104
|
+
if (c_dcg_node_init(&node->base, action_type, repr) != DCG_OK) {
|
|
105
|
+
c_ap_free_owned(node);
|
|
106
|
+
return NULL;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
node->auto_connect = false; /* nothing was connected: the callers that do say so */
|
|
110
|
+
node->sig = sig;
|
|
111
|
+
node->action_data = action_data;
|
|
112
|
+
|
|
113
|
+
/* An action's value is the node itself, and it is written HERE rather than
|
|
114
|
+
* produced by an evaluation: nothing about running an action changes what it
|
|
115
|
+
* stands for, so there is nothing for an evaluation to do - and a node whose
|
|
116
|
+
* slot is the node needs no rule and no dispatch (see c_dcg_node_eval_default).
|
|
117
|
+
* The slot is NODE-shaped rather than an opaque pointer, which is what lets it
|
|
118
|
+
* unpack as the wrapper again (see c_dcg_var_pyunpack). */
|
|
119
|
+
if (c_dcg_var_init_node(&node->base.out, &node->base) != DCG_OK) {
|
|
120
|
+
c_ap_free_owned(node);
|
|
121
|
+
return NULL;
|
|
122
|
+
}
|
|
123
|
+
return node;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @brief Tear down an action and free its buf.
|
|
128
|
+
*
|
|
129
|
+
* The base free is the whole of it: `auto_connect` and `sig` are plain fields
|
|
130
|
+
* inside the block, and `action_data` is the caller's own pointer, not owned.
|
|
131
|
+
* It is a function of its own anyway - and the dispatcher in c_hierarchy.h
|
|
132
|
+
* routes the whole family through it - because the action types are the ones
|
|
133
|
+
* the capi keeps growing, and this is where the release of whatever they grow
|
|
134
|
+
* will live.
|
|
135
|
+
*
|
|
136
|
+
* @param node Node to free (NULL-safe).
|
|
137
|
+
*/
|
|
138
|
+
static inline void c_dcg_node_free_action(dcg_action_node* node) {
|
|
139
|
+
if (!node) return;
|
|
140
|
+
c_dcg_node_free(&node->base);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ========== Public APIs - Variant Constructors ==========
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @brief Allocate a trade action of an explicit type.
|
|
147
|
+
*
|
|
148
|
+
* Only the types that trade are accepted - a long, a short and a cancel - and
|
|
149
|
+
* each brings the signal it stands for with it: +1, -1 and 0, the values the
|
|
150
|
+
* capi's action classes default to. The repr is the type's name, so the caller
|
|
151
|
+
* states the decision and nothing else; anything the type does not already say
|
|
152
|
+
* the generic constructor can carry.
|
|
153
|
+
*
|
|
154
|
+
* @param action_type DCG_NODE_LONGACTION, DCG_NODE_SHORTACTION or DCG_NODE_CANCELACTION.
|
|
155
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
156
|
+
* @return The node, or NULL on OOM / a type that does not trade.
|
|
157
|
+
*/
|
|
158
|
+
static inline dcg_action_node* c_dcg_node_new_action_trade(dcg_node_type action_type, allocator_protocol* allocator) {
|
|
159
|
+
ssize_t sig = 0;
|
|
160
|
+
|
|
161
|
+
switch (action_type) {
|
|
162
|
+
case DCG_NODE_LONGACTION:
|
|
163
|
+
sig = 1;
|
|
164
|
+
break;
|
|
165
|
+
case DCG_NODE_SHORTACTION:
|
|
166
|
+
sig = -1;
|
|
167
|
+
break;
|
|
168
|
+
case DCG_NODE_CANCELACTION:
|
|
169
|
+
break; /* neither direction: a cancel closes what is open */
|
|
170
|
+
default:
|
|
171
|
+
return NULL; /* a clear, a no-op and a placeholder are not trades */
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return c_dcg_node_new_action(action_type, c_dcg_node_type_name(action_type), sig, NULL, allocator);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @brief Allocate an action leaf that flattens the position.
|
|
179
|
+
*
|
|
180
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
181
|
+
* @return The node, or NULL on OOM.
|
|
182
|
+
*/
|
|
183
|
+
static inline dcg_action_node* c_dcg_node_new_action_clear(allocator_protocol* allocator) {
|
|
184
|
+
return c_dcg_node_new_action(DCG_NODE_CLEARACTION, c_dcg_node_type_name(DCG_NODE_CLEARACTION), 0, NULL, allocator);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ========== Public APIs - Closing a Branch ==========
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @brief Close a node's branches: fill the arm it never got, add the fallback.
|
|
191
|
+
*
|
|
192
|
+
* The step a build closes a node with, and the second half of the placeholder
|
|
193
|
+
* discipline - a node is entered with its arms reserved (c_dcg_node_get_placeholder),
|
|
194
|
+
* a build fills the arms it means to, and this supplies the ones it did not.
|
|
195
|
+
* It runs on exit, before the placeholders are consolidated.
|
|
196
|
+
*
|
|
197
|
+
* Every arm it fills is filled with an auto-generated no-action, so a later
|
|
198
|
+
* consolidation can tell it from an action the caller wrote. The rules read the
|
|
199
|
+
* node's EXISTING branches, in the capi's order:
|
|
200
|
+
*
|
|
201
|
+
* - no branch at all -> an auto no-action on the unconditioned edge;
|
|
202
|
+
* - one branch -> its opposite when it is a binary, nothing when it is
|
|
203
|
+
* unconditioned, and the TRUE arm an ELSE-only node
|
|
204
|
+
* was waiting for (inserted in front, so the fallback
|
|
205
|
+
* stays last) - a value-keyed arm stands alone;
|
|
206
|
+
* - two branches -> two binaries stand, an ELSE stands as the fallback,
|
|
207
|
+
* two value-keyed arms gain a protective ELSE, and any
|
|
208
|
+
* other pairing is contradictory (DCG_ERR_EDGE);
|
|
209
|
+
* - three or more -> binaries and unconditioned edges are illegal among
|
|
210
|
+
* them (DCG_ERR_TYPE or DCG_ERR_EDGE), and a set with
|
|
211
|
+
* no fallback gains a trailing ELSE.
|
|
212
|
+
*
|
|
213
|
+
* Nothing is added when the node already says all it can: the call is
|
|
214
|
+
* idempotent, and a failure changes nothing - the auto no-action is released
|
|
215
|
+
* rather than left half-linked.
|
|
216
|
+
*
|
|
217
|
+
* @param node Node to close (NULL-safe).
|
|
218
|
+
* @return DCG_OK, or a DCG_ERR_* code: DCG_ERR_INVALID_ARG (NULL), DCG_ERR_EDGE
|
|
219
|
+
* (contradictory branches), DCG_ERR_TYPE (too many, or a binary among
|
|
220
|
+
* three) and DCG_ERR_OOM.
|
|
221
|
+
*/
|
|
222
|
+
static inline int c_dcg_node_auto_fill(dcg_node* node) {
|
|
223
|
+
if (!node) return DCG_ERR_INVALID_ARG;
|
|
224
|
+
|
|
225
|
+
size_t count = c_dcg_node_child_count(node);
|
|
226
|
+
dcg_node* last = c_dcg_node_last_child(node);
|
|
227
|
+
|
|
228
|
+
/* The arm every branch below is filled with, built on demand and released
|
|
229
|
+
* again if the link it was built for is refused. */
|
|
230
|
+
dcg_action_node* no_action = NULL;
|
|
231
|
+
int ret = DCG_OK;
|
|
232
|
+
|
|
233
|
+
if (count == 0) {
|
|
234
|
+
no_action = c_dcg_node_new_action(DCG_NODE_NOACTION, DCG_DEF_REPR_NOACTION, 0, NULL, c_ap_protocol_from_ptr(node));
|
|
235
|
+
if (!no_action) return DCG_ERR_OOM;
|
|
236
|
+
no_action->base.autogen = true;
|
|
237
|
+
|
|
238
|
+
ret = c_dcg_node_append(node, &no_action->base, DCG_NO_CONDITION);
|
|
239
|
+
if (ret != DCG_OK) c_dcg_node_free_action(no_action);
|
|
240
|
+
return ret;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const dcg_node_edge_condition* condition = last->condition_to_parent;
|
|
244
|
+
|
|
245
|
+
if (count == 1) {
|
|
246
|
+
const dcg_node_edge_condition* fill = NULL;
|
|
247
|
+
bool head = false; /* an ELSE waits for its TRUE arm, which goes in front */
|
|
248
|
+
|
|
249
|
+
if (c_dcg_condition_is_none(condition)) return DCG_OK;
|
|
250
|
+
else if (c_dcg_condition_is_binary(condition)) fill = c_dcg_condition_is_true(condition) ? DCG_FALSE_CONDITION : DCG_TRUE_CONDITION;
|
|
251
|
+
else if (c_dcg_condition_is_else(condition)) {
|
|
252
|
+
fill = DCG_TRUE_CONDITION;
|
|
253
|
+
head = true;
|
|
254
|
+
}
|
|
255
|
+
else return DCG_OK; /* a value-keyed arm stands alone */
|
|
256
|
+
|
|
257
|
+
no_action = c_dcg_node_new_action(DCG_NODE_NOACTION, DCG_DEF_REPR_NOACTION, 0, NULL, c_ap_protocol_from_ptr(node));
|
|
258
|
+
if (!no_action) return DCG_ERR_OOM;
|
|
259
|
+
no_action->base.autogen = true;
|
|
260
|
+
|
|
261
|
+
ret = head ? c_dcg_node_append_at(node, &no_action->base, fill, 0) : c_dcg_node_append(node, &no_action->base, fill);
|
|
262
|
+
if (ret != DCG_OK) c_dcg_node_free_action(no_action);
|
|
263
|
+
return ret;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (count == 2) {
|
|
267
|
+
const dcg_node_edge_condition* second_condition = last->prev_sibling->condition_to_parent;
|
|
268
|
+
|
|
269
|
+
if (c_dcg_condition_is_none(condition) || c_dcg_condition_is_none(second_condition)) return DCG_ERR_EDGE; /* an unconditioned arm cannot share a node */
|
|
270
|
+
if (c_dcg_condition_is_else(condition) || c_dcg_condition_is_else(second_condition)) return DCG_OK;
|
|
271
|
+
if (c_dcg_condition_is_binary(condition) && c_dcg_condition_is_binary(second_condition)) return DCG_OK;
|
|
272
|
+
if (c_dcg_condition_is_binary(condition) || c_dcg_condition_is_binary(second_condition)) return DCG_ERR_EDGE; /* a binary beside a value-keyed arm */
|
|
273
|
+
/* Two value-keyed arms: the fallback is what makes the node total. */
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
/* Three or more: only value-keyed arms may share a node. */
|
|
277
|
+
for (dcg_node* child = node->children; child; child = child->next_sibling) {
|
|
278
|
+
const dcg_node_edge_condition* child_condition = child->condition_to_parent;
|
|
279
|
+
|
|
280
|
+
if (c_dcg_condition_is_none(child_condition)) return DCG_ERR_EDGE;
|
|
281
|
+
if (c_dcg_condition_is_binary(child_condition)) return DCG_ERR_TYPE;
|
|
282
|
+
if (c_dcg_condition_is_else(child_condition)) return DCG_OK; /* the fallback is there already, and it is last */
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
no_action = c_dcg_node_new_action(DCG_NODE_NOACTION, DCG_DEF_REPR_NOACTION, 0, NULL, c_ap_protocol_from_ptr(node));
|
|
287
|
+
if (!no_action) return DCG_ERR_OOM;
|
|
288
|
+
no_action->base.autogen = true;
|
|
289
|
+
|
|
290
|
+
ret = c_dcg_node_append(node, &no_action->base, DCG_ELSE_CONDITION);
|
|
291
|
+
if (ret != DCG_OK) c_dcg_node_free_action(no_action);
|
|
292
|
+
return ret;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @brief Leave a node: fill the branch it never got, then retire the stand-ins.
|
|
297
|
+
*
|
|
298
|
+
* The order is the capi's, and it is the same for every type. `auto_fill`
|
|
299
|
+
* supplies the branches a build did not build, so a node entered and left
|
|
300
|
+
* without one still says something; the consolidation that follows turns
|
|
301
|
+
* whatever is STILL a placeholder into a no-action, so a graph that has closed
|
|
302
|
+
* never contains a stand-in.
|
|
303
|
+
*
|
|
304
|
+
* This is the exit half of every type's context ops - which is why the manager
|
|
305
|
+
* installs it as a node arrives rather than each constructor arming it: the body
|
|
306
|
+
* needs the action family's constructors, and those are above the header that
|
|
307
|
+
* declares the ops.
|
|
308
|
+
*
|
|
309
|
+
* @param node Node being left.
|
|
310
|
+
* @param mgr Manager holding the build (unused: closing is the node's own).
|
|
311
|
+
* @return DCG_OK, or a DCG_ERR_* code.
|
|
312
|
+
*/
|
|
313
|
+
static inline int c_dcg_node_ctx_exit_closed(dcg_node* node, dcg_logic_group_manager* mgr) {
|
|
314
|
+
(void) mgr;
|
|
315
|
+
if (!node) return DCG_ERR_INVALID_ARG;
|
|
316
|
+
|
|
317
|
+
int ret = c_dcg_node_auto_fill(node);
|
|
318
|
+
if (ret != DCG_OK) return ret;
|
|
319
|
+
|
|
320
|
+
c_dcg_node_consolidate_placeholder(node);
|
|
321
|
+
return DCG_OK;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
#endif // C_DCG_BAKE_ACTION_H
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from libcpp cimport bool as c_bool
|
|
2
|
+
|
|
3
|
+
from cbase.allocator_protocol cimport allocator_protocol
|
|
4
|
+
|
|
5
|
+
from .c_node cimport LogicNode, dcg_node, dcg_node_type
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
cdef extern from "decision_graph/decision_tree/bake/c_action.h":
|
|
9
|
+
ctypedef struct dcg_action_node:
|
|
10
|
+
dcg_node base
|
|
11
|
+
c_bool auto_connect
|
|
12
|
+
ssize_t sig
|
|
13
|
+
void* action_data
|
|
14
|
+
|
|
15
|
+
dcg_action_node* c_dcg_node_new_action(dcg_node_type action_type, const char* repr, ssize_t sig, void* action_data, allocator_protocol* allocator) noexcept nogil
|
|
16
|
+
void c_dcg_node_free_action(dcg_action_node* node) noexcept nogil
|
|
17
|
+
|
|
18
|
+
dcg_action_node* c_dcg_node_new_action_trade(dcg_node_type action_type, allocator_protocol* allocator) noexcept nogil
|
|
19
|
+
dcg_action_node* c_dcg_node_new_action_clear(allocator_protocol* allocator) noexcept nogil
|
|
20
|
+
|
|
21
|
+
int c_dcg_node_auto_fill(dcg_node* node) noexcept nogil
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
cdef extern from "decision_graph/decision_tree/bake/c_logic_group.h":
|
|
25
|
+
ctypedef struct dcg_logic_group_manager:
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
dcg_action_node* c_dcg_node_connect_new_action(dcg_node_type action_type, const char* repr, c_bool auto_connect, ssize_t sig, void* action_data, dcg_logic_group_manager* mgr, allocator_protocol* allocator) noexcept nogil
|
|
29
|
+
dcg_action_node* c_dcg_node_connect_new_action_trade(dcg_node_type action_type, c_bool auto_connect, dcg_logic_group_manager* mgr, allocator_protocol* allocator) noexcept nogil
|
|
30
|
+
dcg_action_node* c_dcg_node_connect_new_action_clear(c_bool auto_connect, dcg_logic_group_manager* mgr, allocator_protocol* allocator) noexcept nogil
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
cdef class ActionNode(LogicNode):
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
cdef class NoAction(ActionNode):
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
cdef class LongAction(ActionNode):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
cdef class ShortAction(ActionNode):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
cdef class CancelAction(ActionNode):
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
cdef class ClearAction(ActionNode):
|
|
54
|
+
pass
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""The action layer: the leaves a graph decides with.
|
|
2
|
+
|
|
3
|
+
An action is where a graph stops and answers. It carries a signal - long, short,
|
|
4
|
+
flat - and is a typed node of its own, so a render, an evaluation and a rebuild
|
|
5
|
+
can all tell the leaves apart.
|
|
6
|
+
|
|
7
|
+
A leaf that is built inside a build joins the node being built, unless the caller
|
|
8
|
+
says otherwise; the action that joins nothing stands on its own.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from .c_node import LogicNode
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ActionNode(LogicNode):
|
|
17
|
+
"""An action leaf: a typed terminal node carrying a signal.
|
|
18
|
+
|
|
19
|
+
The class itself is the family's own; a caller builds the named leaves below
|
|
20
|
+
it, which differ only in the type and the signal they pass.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, node_type: int, *, repr: str | None = None, sig: int = 0, auto_connect: bool = True, **kwargs: Any) -> None:
|
|
24
|
+
"""Build an action of an explicit node type.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
node_type: The C node type this action is.
|
|
28
|
+
repr: Display text to copy; the type's own text when not given.
|
|
29
|
+
sig: The signal it carries: +1 long, -1 short, 0 for the rest.
|
|
30
|
+
auto_connect: Whether it joins the node being built.
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
MemoryError: When the block cannot be allocated.
|
|
34
|
+
"""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class NoAction(ActionNode):
|
|
39
|
+
"""The leaf that decides nothing: what an unfilled arm closes as."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, *, sig: int = 0, repr: str = 'NoAction', auto_connect: bool = True, autogen: bool = False, **kwargs: Any) -> None:
|
|
42
|
+
"""Build a no-action leaf.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
sig: The signal it carries, 0 by default.
|
|
46
|
+
repr: Display text to copy.
|
|
47
|
+
auto_connect: Whether it joins the node being built.
|
|
48
|
+
autogen: Whether the builder generated it rather than a caller.
|
|
49
|
+
"""
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
def __int__(self) -> int:
|
|
53
|
+
"""The signal the leaf carries."""
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class LongAction(ActionNode):
|
|
58
|
+
"""The leaf that signals long."""
|
|
59
|
+
|
|
60
|
+
def __init__(self, *, sig: int = 1, repr: str = 'LongAction', auto_connect: bool = True, **kwargs: Any) -> None:
|
|
61
|
+
"""Build a long-action leaf.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
sig: The signal it carries, +1 by default.
|
|
65
|
+
repr: Display text to copy.
|
|
66
|
+
auto_connect: Whether it joins the node being built.
|
|
67
|
+
"""
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
def __int__(self) -> int:
|
|
71
|
+
"""The signal the leaf carries."""
|
|
72
|
+
...
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ShortAction(ActionNode):
|
|
76
|
+
"""The leaf that signals short."""
|
|
77
|
+
|
|
78
|
+
def __init__(self, *, sig: int = -1, repr: str = 'ShortAction', auto_connect: bool = True, **kwargs: Any) -> None:
|
|
79
|
+
"""Build a short-action leaf.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
sig: The signal it carries, -1 by default.
|
|
83
|
+
repr: Display text to copy.
|
|
84
|
+
auto_connect: Whether it joins the node being built.
|
|
85
|
+
"""
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
def __int__(self) -> int:
|
|
89
|
+
"""The signal the leaf carries."""
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class CancelAction(ActionNode):
|
|
94
|
+
"""The leaf that cancels an outstanding signal."""
|
|
95
|
+
|
|
96
|
+
def __init__(self, *, sig: int = 0, repr: str = 'CancelAction', auto_connect: bool = True, **kwargs: Any) -> None:
|
|
97
|
+
"""Build a cancel-action leaf.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
sig: The signal it carries, 0 by default.
|
|
101
|
+
repr: Display text to copy.
|
|
102
|
+
auto_connect: Whether it joins the node being built.
|
|
103
|
+
"""
|
|
104
|
+
...
|
|
105
|
+
|
|
106
|
+
def __int__(self) -> int:
|
|
107
|
+
"""The signal the leaf carries."""
|
|
108
|
+
...
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class ClearAction(ActionNode):
|
|
112
|
+
"""The leaf that flattens: it clears whatever position is held."""
|
|
113
|
+
|
|
114
|
+
def __init__(self, *, sig: int = 0, repr: str = 'ClearAction', auto_connect: bool = True, **kwargs: Any) -> None:
|
|
115
|
+
"""Build a clear-action leaf.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
sig: The signal it carries, 0 by default.
|
|
119
|
+
repr: Display text to copy.
|
|
120
|
+
auto_connect: Whether it joins the node being built.
|
|
121
|
+
"""
|
|
122
|
+
...
|
|
123
|
+
|
|
124
|
+
def __int__(self) -> int:
|
|
125
|
+
"""The signal the leaf carries."""
|
|
126
|
+
...
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from cpython.unicode cimport PyUnicode_AsUTF8
|
|
2
|
+
|
|
3
|
+
from .c_allocator_protocol cimport DCG_DEFAULT_ALLOCATOR
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
cdef class ActionNode(LogicNode):
|
|
7
|
+
def __init__(self, dcg_node_type node_type, *, str repr=None, ssize_t sig=0, bint auto_connect=True, **kwargs):
|
|
8
|
+
cdef dcg_action_node* node = c_dcg_node_connect_new_action(
|
|
9
|
+
node_type,
|
|
10
|
+
PyUnicode_AsUTF8(repr) if repr is not None else NULL,
|
|
11
|
+
auto_connect,
|
|
12
|
+
sig,
|
|
13
|
+
NULL,
|
|
14
|
+
LogicNode.c_get_manager(),
|
|
15
|
+
DCG_DEFAULT_ALLOCATOR,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if not node:
|
|
19
|
+
raise MemoryError(f'Failed to allocate {self.__class__.__name__}.')
|
|
20
|
+
|
|
21
|
+
self.header = &node.base
|
|
22
|
+
self.owner = True
|
|
23
|
+
|
|
24
|
+
self.c_register_node()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
cdef class NoAction(ActionNode):
|
|
28
|
+
def __init__(self, *, ssize_t sig=0, str repr='NoAction', bint auto_connect=True, bint autogen=False, **kwargs):
|
|
29
|
+
ActionNode.__init__(self, dcg_node_type.DCG_NODE_NOACTION, repr=repr, sig=sig, auto_connect=auto_connect)
|
|
30
|
+
self.header.autogen = autogen
|
|
31
|
+
|
|
32
|
+
def __int__(self):
|
|
33
|
+
return 0
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
cdef class LongAction(ActionNode):
|
|
37
|
+
def __init__(self, *, ssize_t sig=1, str repr='LongAction', bint auto_connect=True, **kwargs):
|
|
38
|
+
ActionNode.__init__(self, dcg_node_type.DCG_NODE_LONGACTION, repr=repr, sig=sig, auto_connect=auto_connect)
|
|
39
|
+
|
|
40
|
+
def __int__(self):
|
|
41
|
+
return 1
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
cdef class ShortAction(ActionNode):
|
|
45
|
+
def __init__(self, *, ssize_t sig=-1, str repr='ShortAction', bint auto_connect=True, **kwargs):
|
|
46
|
+
ActionNode.__init__(self, dcg_node_type.DCG_NODE_SHORTACTION, repr=repr, sig=sig, auto_connect=auto_connect)
|
|
47
|
+
|
|
48
|
+
def __int__(self):
|
|
49
|
+
return -1
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
cdef class CancelAction(ActionNode):
|
|
53
|
+
def __init__(self, *, ssize_t sig=0, str repr='CancelAction', bint auto_connect=True, **kwargs):
|
|
54
|
+
ActionNode.__init__(self, dcg_node_type.DCG_NODE_CANCELACTION, repr=repr, sig=sig, auto_connect=auto_connect)
|
|
55
|
+
|
|
56
|
+
def __int__(self):
|
|
57
|
+
return 0
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
cdef class ClearAction(ActionNode):
|
|
61
|
+
def __init__(self, *, ssize_t sig=0, str repr='ClearAction', bint auto_connect=True, **kwargs):
|
|
62
|
+
ActionNode.__init__(self, dcg_node_type.DCG_NODE_CLEARACTION, repr=repr, sig=sig, auto_connect=auto_connect)
|
|
63
|
+
|
|
64
|
+
def __int__(self):
|
|
65
|
+
return 0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from libcpp cimport bool as c_bool
|
|
2
|
+
|
|
3
|
+
from cbase.allocator_protocol cimport AllocatorConfigContext, allocator_protocol, heap_allocator, shm_allocator_ctx
|
|
4
|
+
|
|
5
|
+
cdef c_bool DCG_CFG_LOCKED
|
|
6
|
+
cdef c_bool DCG_CFG_SHARED
|
|
7
|
+
cdef c_bool DCG_CFG_FREELIST
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
cdef class ConfigContext(AllocatorConfigContext):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
cdef heap_allocator* HEAP_ALLOCATOR
|
|
15
|
+
cdef shm_allocator_ctx* SHM_ALLOCATOR
|
|
16
|
+
|
|
17
|
+
cdef allocator_protocol* DCG_DEFAULT_ALLOCATOR
|
|
18
|
+
cdef allocator_protocol* DCG_SHM_ALLOCATOR
|
|
19
|
+
cdef allocator_protocol* DCG_HEAP_ALLOCATOR
|
|
20
|
+
|
|
21
|
+
cdef ConfigContext DCG_SHARED
|
|
22
|
+
cdef ConfigContext DCG_LOCKED
|
|
23
|
+
cdef ConfigContext DCG_LOCKFREE
|
|
24
|
+
cdef ConfigContext DCG_FREELIST
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""The allocator the bake layer allocates through, and the switches it reads.
|
|
2
|
+
|
|
3
|
+
Every block the layer builds - nodes, groups, slots, strings - comes from the
|
|
4
|
+
allocator protocol, and this module owns the layer's instance of it along with
|
|
5
|
+
the switches that decide how it behaves: locking, shared memory, and the free
|
|
6
|
+
list.
|
|
7
|
+
|
|
8
|
+
A switch is read by the C layer as it allocates, so it is set by entering one of
|
|
9
|
+
the contexts below rather than by assignment, and a block's lifetime is the
|
|
10
|
+
protocol's: a child block dies with its parent.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from cbase.allocator_protocol import AllocatorConfigContext
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ConfigContext(AllocatorConfigContext):
|
|
17
|
+
"""A set of allocator switches, applied on entry and put back on exit.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
overrides: The switches this context sets, keyed by name.
|
|
21
|
+
originals: What those switches were before the context was entered.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, *, locked: bool = ..., shared: bool = ..., freelist: bool = ...) -> None:
|
|
25
|
+
"""Build a context that sets the switches it is given.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
locked: Whether allocations take the protocol's lock.
|
|
29
|
+
shared: Whether blocks come from shared memory.
|
|
30
|
+
freelist: Whether freed blocks are recycled.
|
|
31
|
+
"""
|
|
32
|
+
...
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class _RuntimeAllocatorConfig:
|
|
36
|
+
"""The live switch values, read through properties rather than copied."""
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def DCG_CFG_LOCKED(self) -> bool:
|
|
40
|
+
"""Whether allocations currently take the protocol's lock."""
|
|
41
|
+
...
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def DCG_CFG_SHARED(self) -> bool:
|
|
45
|
+
"""Whether blocks currently come from shared memory."""
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def DCG_CFG_FREELIST(self) -> bool:
|
|
50
|
+
"""Whether freed blocks are currently recycled."""
|
|
51
|
+
...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# The four switch contexts: shared memory, locking, lock-free, free list.
|
|
55
|
+
DCG_SHARED: ConfigContext
|
|
56
|
+
DCG_LOCKED: ConfigContext
|
|
57
|
+
DCG_LOCKFREE: ConfigContext
|
|
58
|
+
DCG_FREELIST: ConfigContext
|
|
59
|
+
|
|
60
|
+
# The switches as they are right now, for a caller that has to ask.
|
|
61
|
+
RUNTIME_ALLOCATOR_CONFIG: _RuntimeAllocatorConfig
|