@@ -27,8 +27,12 @@ namespace hgraph {
2727 void BaseTimeSeriesOutput::reset_parent_or_node () { _parent_ts_or_node.reset (); }
2828
2929 // Implement re_parent methods
30- void BaseTimeSeriesOutput::re_parent (const node_ptr &parent) { _parent_ts_or_node = parent; }
31- void BaseTimeSeriesOutput::re_parent (const TimeSeriesType::ptr &parent) { _parent_ts_or_node = parent; }
30+ void BaseTimeSeriesOutput::re_parent (const node_ptr &parent) {
31+ _parent_ts_or_node = parent;
32+ }
33+ void BaseTimeSeriesOutput::re_parent (const TimeSeriesType::ptr &parent) {
34+ _parent_ts_or_node = parent;
35+ }
3236
3337 // TimeSeriesType helper methods
3438 TimeSeriesType::ptr &BaseTimeSeriesOutput::_parent_time_series () const {
@@ -119,9 +123,10 @@ namespace hgraph {
119123 }
120124
121125 bool BaseTimeSeriesOutput::modified () const {
122- auto g = owning_graph ();
123- if (!g) { return false ; }
124- return g->evaluation_clock ()->evaluation_time () == _last_modified_time;
126+ auto n = owning_node ();
127+ if (n.get () == nullptr ) { return false ; }
128+ // Use cached evaluation time pointer from node for performance
129+ return *n->cached_evaluation_time_ptr () == _last_modified_time;
125130 }
126131
127132 bool BaseTimeSeriesOutput::valid () const { return _last_modified_time > MIN_DT; }
@@ -135,24 +140,26 @@ namespace hgraph {
135140 void BaseTimeSeriesOutput::mark_invalid () {
136141 if (_last_modified_time > MIN_DT) {
137142 _last_modified_time = MIN_DT;
138- auto g = owning_graph ();
139- if (g) {
140- _notify (g->evaluation_clock ()->evaluation_time ());
143+ auto n = owning_node ();
144+ if (n.get () != nullptr ) {
145+ // Use cached evaluation time pointer from node for performance
146+ _notify (*n->cached_evaluation_time_ptr ());
141147 } else {
142- // Owning graph not yet attached; skip notify to avoid dereferencing null during start/recover
148+ // Owning node not yet attached; skip notify to avoid dereferencing null during start/recover
143149 }
144150 }
145151 }
146152
147153 void BaseTimeSeriesOutput::mark_modified () {
148154 if (has_parent_or_node ()) {
149- auto g = owning_graph ();
150- if (g != nullptr ) {
151- mark_modified (g->evaluation_clock ()->evaluation_time ());
155+ auto n = owning_node ();
156+ if (n.get () != nullptr ) {
157+ // Use cached evaluation time pointer from node for performance
158+ mark_modified (*n->cached_evaluation_time_ptr ());
152159 } else {
153- // Graph not yet attached; mark with a maximal time to preserve monotonicity without dereferencing
160+ // Owning node not yet attached; mark with a maximal time to preserve monotonicity without dereferencing
154161 // This is a bad situation, I would probably prefer to find out why,
155- // TODO: find the root cause of why this could be called without a bound graph .
162+ // TODO: find the root cause of why this could be called without a bound node .
156163 }
157164 } else {
158165 mark_modified (MAX_ET);
@@ -203,8 +210,12 @@ namespace hgraph {
203210 void BaseTimeSeriesInput::reset_parent_or_node () { _parent_ts_or_node.reset (); }
204211
205212 // Implement re_parent methods
206- void BaseTimeSeriesInput::re_parent (const node_ptr &parent) { _parent_ts_or_node = parent; }
207- void BaseTimeSeriesInput::re_parent (const TimeSeriesType::ptr &parent) { _parent_ts_or_node = parent; }
213+ void BaseTimeSeriesInput::re_parent (const node_ptr &parent) {
214+ _parent_ts_or_node = parent;
215+ }
216+ void BaseTimeSeriesInput::re_parent (const TimeSeriesType::ptr &parent) {
217+ _parent_ts_or_node = parent;
218+ }
208219
209220 // TimeSeriesType helper methods
210221 TimeSeriesType::ptr &BaseTimeSeriesInput::_parent_time_series () const {
@@ -301,9 +312,10 @@ namespace hgraph {
301312 // - The input was previously bound (rebinding case), OR
302313 // - The new output is valid
303314 // This matches the Python implementation: (was_bound or self._output.valid)
304- if ((owning_node ()->is_started () || owning_node ()->is_starting ()) && _output.get () && (was_bound || _output->
305- valid ())) {
306- _sample_time = owning_graph ()->evaluation_clock ()->evaluation_time ();
315+ auto n = owning_node ();
316+ if ((n->is_started () || n->is_starting ()) && _output.get () && (was_bound || _output->valid ())) {
317+ // Use cached evaluation time pointer from node for performance
318+ _sample_time = *n->cached_evaluation_time_ptr ();
307319 if (active ()) {
308320 notify (_sample_time);
309321 // TODO: This might belong to make_active, or not? There is a race with setting sample_time too.
@@ -325,11 +337,13 @@ namespace hgraph {
325337 if (bound ()) {
326338 do_un_bind_output (unbind_refs);
327339
328- if (owning_node ()->is_started () && was_valid) {
329- _sample_time = owning_graph ()->evaluation_clock ()->evaluation_time ();
340+ auto n = owning_node ();
341+ if (n->is_started () && was_valid) {
342+ // Use cached evaluation time pointer from node for performance
343+ _sample_time = *n->cached_evaluation_time_ptr ();
330344 if (active ()) {
331345 // Notify as the state of the node has changed from bound to un_bound
332- owning_node () ->notify (_sample_time);
346+ n ->notify (_sample_time);
333347 }
334348 }
335349 }
@@ -433,7 +447,10 @@ namespace hgraph {
433447 engine_time_t BaseTimeSeriesInput::sample_time () const { return _sample_time; }
434448
435449 bool BaseTimeSeriesInput::sampled () const {
436- return _sample_time != MIN_DT && _sample_time == owning_graph ()->evaluation_clock ()->evaluation_time ();
450+ auto n = owning_node ();
451+ if (n.get () == nullptr ) { return false ; }
452+ // Use cached evaluation time pointer from node for performance
453+ return _sample_time != MIN_DT && _sample_time == *n->cached_evaluation_time_ptr ();
437454 }
438455
439456 time_series_reference_output_ptr BaseTimeSeriesInput::reference_output () const { return _reference_output; }
0 commit comments