fix(abcip): serialize Read/GetStatus/Decode + Encode/Write/GetStatus per runtime (05/STAB-4)
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
{
|
||||
"id": "B2.3",
|
||||
"subject": "B2: wrap ReadSingleAsync/ReadGroupAsync/WriteAsync critical sections in the per-runtime lock; AbCip suite green",
|
||||
"status": "pending",
|
||||
"status": "completed",
|
||||
"blockedBy": [
|
||||
"B2.2"
|
||||
]
|
||||
|
||||
@@ -542,6 +542,13 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
try
|
||||
{
|
||||
var runtime = await EnsureTagRuntimeAsync(device, def, ct).ConfigureAwait(false);
|
||||
|
||||
// Serialise Read → GetStatus → Decode against the shared runtime — the cached libplctag
|
||||
// Tag handle is not concurrency-safe and GetStatus returns the LAST op's status (05/STAB-4).
|
||||
var opLock = device.GetRuntimeLock(def.Name);
|
||||
await opLock.WaitAsync(ct).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await runtime.ReadAsync(ct).ConfigureAwait(false);
|
||||
|
||||
var status = runtime.GetStatus();
|
||||
@@ -574,6 +581,11 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
results[fb.OriginalIndex] = new DataValueSnapshot(value, AbCipStatusMapper.Good, now, now);
|
||||
_health = new DriverHealth(DriverState.Healthy, now, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
opLock.Release();
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
throw;
|
||||
@@ -612,6 +624,13 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
try
|
||||
{
|
||||
var runtime = await EnsureTagRuntimeAsync(device, parent, ct).ConfigureAwait(false);
|
||||
|
||||
// Serialise the whole-UDT Read → GetStatus → per-member DecodeValueAt against the shared
|
||||
// parent runtime — the members decode from that one handle's buffer (05/STAB-4).
|
||||
var opLock = device.GetRuntimeLock(parent.Name);
|
||||
await opLock.WaitAsync(ct).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await runtime.ReadAsync(ct).ConfigureAwait(false);
|
||||
|
||||
var status = runtime.GetStatus();
|
||||
@@ -636,6 +655,11 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
}
|
||||
_health = new DriverHealth(DriverState.Healthy, now, null);
|
||||
}
|
||||
finally
|
||||
{
|
||||
opLock.Release();
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
throw;
|
||||
@@ -706,10 +730,23 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
}
|
||||
|
||||
var runtime = await EnsureTagRuntimeAsync(device, def, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Serialise Encode → Write → GetStatus against the shared runtime — the same cached
|
||||
// Tag handle may be in use by a concurrent ReadAsync or poll loop (05/STAB-4).
|
||||
var opLock = device.GetRuntimeLock(def.Name);
|
||||
await opLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
int status;
|
||||
try
|
||||
{
|
||||
runtime.EncodeValue(def.DataType, parsedPath?.BitIndex, w.Value);
|
||||
await runtime.WriteAsync(cancellationToken).ConfigureAwait(false);
|
||||
status = runtime.GetStatus();
|
||||
}
|
||||
finally
|
||||
{
|
||||
opLock.Release();
|
||||
}
|
||||
|
||||
var status = runtime.GetStatus();
|
||||
if (status != 0)
|
||||
{
|
||||
EvictRuntime(device, def.Name);
|
||||
|
||||
Reference in New Issue
Block a user