From 6acf07f48760007fdb670d82b7fe1c440e8b4d13 Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Thu, 13 Aug 2026 17:51:33 +0200 Subject: [PATCH] reset stimulus during output getter --- Runtime/Scripts/Core/Cluster.cs | 2 + Runtime/Scripts/Core/Neuron.cs | 70 +++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/Runtime/Scripts/Core/Cluster.cs b/Runtime/Scripts/Core/Cluster.cs index 1e3a25b..a9ea309 100644 --- a/Runtime/Scripts/Core/Cluster.cs +++ b/Runtime/Scripts/Core/Cluster.cs @@ -80,6 +80,8 @@ namespace NanoBrain { [HideInInspector] public List nuclei = new(); + public readonly List<(long timestamp, string neuronName, Action action)> functions = new(); + #region Init public Cluster() { diff --git a/Runtime/Scripts/Core/Neuron.cs b/Runtime/Scripts/Core/Neuron.cs index 06d630e..e87d749 100644 --- a/Runtime/Scripts/Core/Neuron.cs +++ b/Runtime/Scripts/Core/Neuron.cs @@ -174,8 +174,6 @@ namespace NanoBrain { #if UNITY_MATHEMATICS - private readonly List fs = new(); - /// /// The output value of the neuron /// @@ -185,11 +183,20 @@ namespace NanoBrain { /// The output value of the neuron /// public virtual float3 outputValue { - get { - foreach (var f in fs) - f(); + get { + long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + List<(long timestamp, string, Action)> q = this.parent.functions; + // if (q.Count > 0) { + // Debug.Log($"Q size is {q.Count} {q[0].timestamp} {q[0].timestamp - now}"); + // } + while (q.Count > 0 && q[0].timestamp <= now) { + // Debug.Log($"Function call at {now}"); + (long timestamp, string neuron, Action action) = q[0]; + q.RemoveAt(0); + action(); + } return _outputValue; - } + } set { _outputValue = value; if (this.isFiring) @@ -804,26 +811,47 @@ namespace NanoBrain { this.parent?.UpdateFromNucleus(this); if (autoResetDelay > 0) { - _cts?.Cancel(); - _cts?.Dispose(); - _cts = new CancellationTokenSource(); - _ = CallResetAfterDelayAsync(_cts.Token, autoResetDelay); + long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + long resetTime = now + (long)(autoResetDelay * 1000.0f); + var q = this.parent.functions; + int ix = q.FindIndex(f => f.neuronName == this.name); + if (ix >= 0) { + // Debug.Log($"Update resetter at {resetTime}"); + // update the reset time of the existing function call + q[ix] = (resetTime, this.name, ResetStimulus); + } + else { + // Add the function call in a sorted manner + ix = q.FindIndex(f => f.timestamp > resetTime); + if (ix < 0) { + // Debug.Log($"Add resetter at {resetTime}"); + q.Add((resetTime, this.name, ResetStimulus)); + } + else { + Debug.Log($"Insert resetter at {resetTime}"); + q.Insert(ix, (resetTime, this.name, ResetStimulus)); + } + } + // _cts?.Cancel(); + // _cts?.Dispose(); + // _cts = new CancellationTokenSource(); + // _ = CallResetAfterDelayAsync(_cts.Token, autoResetDelay); } } - private async Task CallResetAfterDelayAsync(CancellationToken token, float autoResetDelay) { - try { - await Task.Delay(TimeSpan.FromSeconds(autoResetDelay), token); - if (!token.IsCancellationRequested) - ResetStimulus(); - } - catch (TaskCanceledException) { - // Expected when Stimulus is called again; do nothing - } - } + // private async Task CallResetAfterDelayAsync(CancellationToken token, float autoResetDelay) { + // try { + // await Task.Delay(TimeSpan.FromSeconds(autoResetDelay), token); + // if (!token.IsCancellationRequested) + // ResetStimulus(); + // } + // catch (TaskCanceledException) { + // // Expected when Stimulus is called again; do nothing + // } + // } protected void ResetStimulus() { - //Debug.Log("reset stimulus"); + Debug.Log("reset stimulus"); this.bias = Vector3.zero; this.parent?.UpdateFromNucleus(this); }