Fix race condition for the shared evaluator when any active input handler is threaded.
This commit is contained in:
@@ -18,7 +18,7 @@ namespace Cryville.Crtr {
|
|||||||
_vecsrcs[i] = vecsrc;
|
_vecsrcs[i] = vecsrc;
|
||||||
_vecops[i] = new InputVectorOp(vecsrc);
|
_vecops[i] = new InputVectorOp(vecsrc);
|
||||||
}
|
}
|
||||||
_etor = ChartPlayer.etor;
|
_etor = judge != null ? judge._etor : ChartPlayer.etor;
|
||||||
_ruleset = ruleset;
|
_ruleset = ruleset;
|
||||||
_judge = judge;
|
_judge = judge;
|
||||||
foreach (var i in ruleset.inputs) {
|
foreach (var i in ruleset.inputs) {
|
||||||
@@ -172,7 +172,6 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly object _lock = new object();
|
|
||||||
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
|
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
|
||||||
const int MAX_DEPTH = 15;
|
const int MAX_DEPTH = 15;
|
||||||
const int MAX_DIMENSION = 3;
|
const int MAX_DIMENSION = 3;
|
||||||
@@ -228,7 +227,7 @@ namespace Cryville.Crtr {
|
|||||||
readonly Dictionary<ProxiedInputIdentifier, PropSrc> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc>();
|
readonly Dictionary<ProxiedInputIdentifier, PropSrc> _vecs = new Dictionary<ProxiedInputIdentifier, PropSrc>();
|
||||||
double? _lockTime = null;
|
double? _lockTime = null;
|
||||||
unsafe void OnInput(InputIdentifier id, InputVector vec) {
|
unsafe void OnInput(InputIdentifier id, InputVector vec) {
|
||||||
lock (_lock) {
|
lock (_etor) {
|
||||||
InputProxyEntry proxy;
|
InputProxyEntry proxy;
|
||||||
if (_sproxies.TryGetValue(id.Source, out proxy)) {
|
if (_sproxies.TryGetValue(id.Source, out proxy)) {
|
||||||
_etor.ContextCascadeInsert();
|
_etor.ContextCascadeInsert();
|
||||||
@@ -258,10 +257,10 @@ namespace Cryville.Crtr {
|
|||||||
_etor.ContextCascadeInsert();
|
_etor.ContextCascadeInsert();
|
||||||
bool newNullFlag = nullflag;
|
bool newNullFlag = nullflag;
|
||||||
if (!newNullFlag) {
|
if (!newNullFlag) {
|
||||||
ChartPlayer.etor.Evaluate(_vecops[depth + 1], p.Value);
|
_etor.Evaluate(_vecops[depth + 1], p.Value);
|
||||||
newNullFlag = _vecsrcs[depth + 1].IsNull;
|
newNullFlag = _vecsrcs[depth + 1].IsNull;
|
||||||
if (newNullFlag) ChartPlayer.etor.ContextCascadeUpdate(_var_value, PropSrc.Null);
|
if (newNullFlag) _etor.ContextCascadeUpdate(_var_value, PropSrc.Null);
|
||||||
else ChartPlayer.etor.ContextCascadeUpdate(_var_value, _vecsrcs[depth + 1]);
|
else _etor.ContextCascadeUpdate(_var_value, _vecsrcs[depth + 1]);
|
||||||
}
|
}
|
||||||
OnInput(id, p.Key, ft, tt, newNullFlag, depth + 1);
|
OnInput(id, p.Key, ft, tt, newNullFlag, depth + 1);
|
||||||
_etor.ContextCascadeDiscard();
|
_etor.ContextCascadeDiscard();
|
||||||
|
@@ -13,7 +13,7 @@ namespace Cryville.Crtr {
|
|||||||
public class Judge {
|
public class Judge {
|
||||||
#region Data
|
#region Data
|
||||||
readonly ChartPlayer _sys;
|
readonly ChartPlayer _sys;
|
||||||
readonly PdtEvaluator _etor;
|
internal readonly PdtEvaluator _etor;
|
||||||
readonly PdtRuleset _rs;
|
readonly PdtRuleset _rs;
|
||||||
readonly Dictionary<Identifier, List<JudgeEvent>> evs
|
readonly Dictionary<Identifier, List<JudgeEvent>> evs
|
||||||
= new Dictionary<Identifier, List<JudgeEvent>>();
|
= new Dictionary<Identifier, List<JudgeEvent>>();
|
||||||
@@ -38,7 +38,8 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
public Judge(ChartPlayer sys, PdtRuleset rs) {
|
public Judge(ChartPlayer sys, PdtRuleset rs) {
|
||||||
_sys = sys;
|
_sys = sys;
|
||||||
_etor = ChartPlayer.etor;
|
_etor = new PdtEvaluator();
|
||||||
|
_etor.ContextJudge = this;
|
||||||
_rs = rs;
|
_rs = rs;
|
||||||
_numsrc1 = new PropSrc.Float(() => _numbuf1);
|
_numsrc1 = new PropSrc.Float(() => _numbuf1);
|
||||||
_numsrc2 = new PropSrc.Float(() => _numbuf2);
|
_numsrc2 = new PropSrc.Float(() => _numbuf2);
|
||||||
@@ -67,8 +68,8 @@ namespace Cryville.Crtr {
|
|||||||
Identifier input = default(Identifier);
|
Identifier input = default(Identifier);
|
||||||
Clip clip = default(Clip);
|
Clip clip = default(Clip);
|
||||||
var def = _rs.judges[tev.Id];
|
var def = _rs.judges[tev.Id];
|
||||||
ChartPlayer.etor.Evaluate(new PropOp.Identifier(v => input = new Identifier(v)), def.input);
|
_etor.Evaluate(new PropOp.Identifier(v => input = new Identifier(v)), def.input);
|
||||||
ChartPlayer.etor.Evaluate(new PropOp.Clip(v => clip = v), def.clip);
|
_etor.Evaluate(new PropOp.Clip(v => clip = v), def.clip);
|
||||||
double st = sev.Time, et = st + sev.Duration;
|
double st = sev.Time, et = st + sev.Duration;
|
||||||
var list = evs[input];
|
var list = evs[input];
|
||||||
var ev = new JudgeEvent {
|
var ev = new JudgeEvent {
|
||||||
@@ -181,6 +182,7 @@ namespace Cryville.Crtr {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
public void Cleanup(Identifier target, float tt) {
|
public void Cleanup(Identifier target, float tt) {
|
||||||
|
lock (_etor) {
|
||||||
Forward(target, tt);
|
Forward(target, tt);
|
||||||
var actlist = activeEvs[target];
|
var actlist = activeEvs[target];
|
||||||
for (int i = actlist.Count - 1; i >= 0; i--) {
|
for (int i = actlist.Count - 1; i >= 0; i--) {
|
||||||
@@ -191,6 +193,7 @@ namespace Cryville.Crtr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void Forward(Identifier target, float tt) {
|
void Forward(Identifier target, float tt) {
|
||||||
var list = evs[target];
|
var list = evs[target];
|
||||||
var actlist = activeEvs[target];
|
var actlist = activeEvs[target];
|
||||||
@@ -254,6 +257,7 @@ namespace Cryville.Crtr {
|
|||||||
return scoreSrcs.TryGetValue(key, out value);
|
return scoreSrcs.TryGetValue(key, out value);
|
||||||
}
|
}
|
||||||
public TargetString GetFullFormattedScoreString() {
|
public TargetString GetFullFormattedScoreString() {
|
||||||
|
lock (_etor) {
|
||||||
bool flag = false;
|
bool flag = false;
|
||||||
scoreFullBuf.Clear();
|
scoreFullBuf.Clear();
|
||||||
foreach (var s in scores) {
|
foreach (var s in scores) {
|
||||||
@@ -267,6 +271,7 @@ namespace Cryville.Crtr {
|
|||||||
scoreFullBuf.CopyTo(0, arr, 0, scoreFullBuf.Count);
|
scoreFullBuf.CopyTo(0, arr, 0, scoreFullBuf.Count);
|
||||||
return scoreFullStr;
|
return scoreFullStr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class ScoreStringSrc : PropSrc {
|
class ScoreStringSrc : PropSrc {
|
||||||
readonly Func<float> _cb;
|
readonly Func<float> _cb;
|
||||||
readonly string _format;
|
readonly string _format;
|
||||||
|
@@ -103,11 +103,11 @@ namespace Cryville.Crtr {
|
|||||||
if (ev == null) { }
|
if (ev == null) { }
|
||||||
else if (ev.Unstamped == null) { }
|
else if (ev.Unstamped == null) { }
|
||||||
else if (ev.Unstamped is Chart.Judge) {
|
else if (ev.Unstamped is Chart.Judge) {
|
||||||
ChartPlayer.etor.ContextEvent = ev.Unstamped;
|
judge._etor.ContextEvent = ev.Unstamped;
|
||||||
ChartPlayer.etor.ContextState = s;
|
judge._etor.ContextState = s;
|
||||||
judge.Prepare(ev, this);
|
judge.Prepare(ev, this);
|
||||||
ChartPlayer.etor.ContextState = null;
|
judge._etor.ContextState = null;
|
||||||
ChartPlayer.etor.ContextEvent = null;
|
judge._etor.ContextEvent = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s.CloneType == 2 && ev != null && ev.Unstamped is Chart.Judge) {
|
if (s.CloneType == 2 && ev != null && ev.Unstamped is Chart.Judge) {
|
||||||
|
@@ -10,7 +10,7 @@ using UnityEngine;
|
|||||||
|
|
||||||
namespace Cryville.Crtr {
|
namespace Cryville.Crtr {
|
||||||
public class PdtEvaluator : PdtEvaluatorBase {
|
public class PdtEvaluator : PdtEvaluatorBase {
|
||||||
static readonly Dictionary<PdtOperatorSignature, PdtOperator> _shortops = new Dictionary<PdtOperatorSignature, PdtOperator>();
|
readonly Dictionary<PdtOperatorSignature, PdtOperator> _shortops = new Dictionary<PdtOperatorSignature, PdtOperator>();
|
||||||
readonly IntKeyedDictionary<PdtOperator> _ctxops = new IntKeyedDictionary<PdtOperator>();
|
readonly IntKeyedDictionary<PdtOperator> _ctxops = new IntKeyedDictionary<PdtOperator>();
|
||||||
|
|
||||||
static readonly byte[] _nullbuf = new byte[0];
|
static readonly byte[] _nullbuf = new byte[0];
|
||||||
@@ -151,27 +151,6 @@ namespace Cryville.Crtr {
|
|||||||
for (int i = 0; i < ContextCascade.Length; i++) ContextCascade[i] = new IntKeyedDictionary<PropSrc>();
|
for (int i = 0; i < ContextCascade.Length; i++) ContextCascade[i] = new IntKeyedDictionary<PropSrc>();
|
||||||
_vecsrc = new VectorSrc(() => _vec);
|
_vecsrc = new VectorSrc(() => _vec);
|
||||||
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("screen_edge"), new func_screen_edge(() => ContextTransform));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("int"), new func_int(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("clamp"), new func_clamp(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("anim"), new func_anim(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("cubic_bezier"), new func_cubic_bezier(() => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease"), new func_cubic_bezier_fixed(0.25f, 0.1f, 0.25f, 1f, () => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in"), new func_cubic_bezier_fixed(0.42f, 0f, 1f, 1f, () => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_out"), new func_cubic_bezier_fixed(0f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in_out"), new func_cubic_bezier_fixed(0.42f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
|
||||||
|
|
||||||
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("attack_timing"), new func_attack_timing(cccb));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("enter_timing"), new func_enter_timing(cccb));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("release_timing"), new func_release_timing(cccb));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("leave_timing"), new func_leave_timing(cccb));
|
|
||||||
_ctxops.Add(IdentifierManager.SharedInstance.Request("contact_timing"), new func_contact_timing(cccb));
|
|
||||||
}
|
|
||||||
static PdtEvaluator() {
|
|
||||||
_shortops.Add(new PdtOperatorSignature("@", 2), new op_at_2());
|
_shortops.Add(new PdtOperatorSignature("@", 2), new op_at_2());
|
||||||
|
|
||||||
_shortops.Add(new PdtOperatorSignature("*", 2), new op_mul_2());
|
_shortops.Add(new PdtOperatorSignature("*", 2), new op_mul_2());
|
||||||
@@ -193,6 +172,26 @@ namespace Cryville.Crtr {
|
|||||||
_shortops.Add(new PdtOperatorSignature("in_area", 1), new func_in_area());
|
_shortops.Add(new PdtOperatorSignature("in_area", 1), new func_in_area());
|
||||||
_shortops.Add(new PdtOperatorSignature("interval", 3), new func_interval());
|
_shortops.Add(new PdtOperatorSignature("interval", 3), new func_interval());
|
||||||
_shortops.Add(new PdtOperatorSignature("is", 2), new func_is());
|
_shortops.Add(new PdtOperatorSignature("is", 2), new func_is());
|
||||||
|
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("screen_edge"), new func_screen_edge(() => ContextTransform));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("int"), new func_int(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("clamp"), new func_clamp(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("abs"), new func_abs(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("anim"), new func_anim(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("cubic_bezier"), new func_cubic_bezier(() => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease"), new func_cubic_bezier_fixed(0.25f, 0.1f, 0.25f, 1f, () => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in"), new func_cubic_bezier_fixed(0.42f, 0f, 1f, 1f, () => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_out"), new func_cubic_bezier_fixed(0f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("ease_in_out"), new func_cubic_bezier_fixed(0.42f, 0f, 0.58f, 1f, () => ContextSelfValue));
|
||||||
|
|
||||||
|
Func<int, PropSrc> cccb = k => ContextCascadeLookup(k);
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("attack_timing"), new func_attack_timing(cccb));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("enter_timing"), new func_enter_timing(cccb));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("release_timing"), new func_release_timing(cccb));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("leave_timing"), new func_leave_timing(cccb));
|
||||||
|
_ctxops.Add(IdentifierManager.SharedInstance.Request("contact_timing"), new func_contact_timing(cccb));
|
||||||
}
|
}
|
||||||
#region Operators
|
#region Operators
|
||||||
#pragma warning disable IDE1006
|
#pragma warning disable IDE1006
|
||||||
|
Reference in New Issue
Block a user