Warning: session_start(): open(/var/lib/php/sessions/sess_2l5g9af2mb1ov0qh9gu1hm5hm6, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
transient srecord noeq G22NetworkInstance(G22Network network) {
new Map valuesByIdentifier;
new Map valuesByBlueprint;
event dirtyStatesChanged;
sclass Value {
settable O object; // the actual value calculated by the node
settable Timestamp calculatedWhen; // when the value was calculated
settable volatile bool dirty; // does this node need recalculation?
settable volatile bool calculating; // are we recalculating right now?
settable volatile bool hasError; // error during calculation?
O get() { ret object; }
toString { ret classNameWithIdentity(this) + ": " + object; }
}
void calculateNode(G22Utils g22utils, G22NetworkElement e) {
if (e == null) ret;
Value value = valueForBlueprint(e);
value.calculating(true);
try {
dirtyStatesChanged();
O instance = e.makeInstance(g22utils, this);
print("Calculated: " + instance);
value.hasError(false);
setObject(e, value, instance);
} catch print exception {
value.hasError(true);
value.dirty(false);
} finally {
value.calculating(false);
dirtyStatesChanged();
}
}
void setObject(G22NetworkElement e, Value value, O instance) {
value.object(instance).calculatedWhen(tsNow());
if (value.dirty()) {
value.dirty(false);
dirtyStatesChanged();
}
invalidateDependentNodes(e);
}
void init(G22Utils g22utils) {
// make empty Value object for each node
for (e : network.elements) {
new Value value;
value.dirty(true);
dirtyStatesChanged();
valuesByBlueprint.put(e, value);
//print("Put value in map: " + e + " => " + value);
mapPut(valuesByIdentifier, e.identifier(), value);
}
}
O getObjectForBlueprint(G22NetworkElement element) {
var value = valueForBlueprint(element);
O object = value!;
printVars("getObjectForBlueprint", +element, +value, +object);
ret object;
}
void invalidateDependentNodes(G22NetworkElement element) {
if (element == null) ret;
print("invalidateDependentNodes", element);
for (e : element.downstreamNodes())
invalidateNode(e);
}
// a node is calculable if its upstream nodes (the inputs
// it needs) are clean
bool isCalculable(G22NetworkElement element) {
ret all(element.upstreamNodes(), e -> !isDirty(e));
}
Value valueForBlueprint(G22NetworkElement element) {
ret syncGetOrCreate(valuesByBlueprint, element, -> new Value);
}
bool isDirty(G22NetworkElement element) {
ret valueForBlueprint(element).dirty();
}
void invalidateNode(G22NetworkElement element) {
print("invalidateNode", element);
var value = valueForBlueprint(element);
if (value.dirty()) ret; // Node already dirty
value.dirty(true);
dirtyStatesChanged();
invalidateDependentNodes(element);
}
// select any calculable node and calculate it
G22NetworkElement calculateOneNode(G22Utils g22utils) {
var calculableElements = filter(
e -> isDirty(e) && isCalculable(e),
keys(valuesByBlueprint));
var e = random(calculableElements);
calculateNode(g22utils, e);
ret e;
}
}