Skip to content

Commit 3f87952

Browse files
Merge pull request #102 from SergeyGulik/buffer_races
Buffer race condition fix
2 parents 5a41b61 + b52e282 commit 3f87952

1 file changed

Lines changed: 39 additions & 56 deletions

File tree

libraries/MTConnect.NET-Common/Buffers/MTConnectObservationBuffer.cs

Lines changed: 39 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,15 @@ public IDictionary<int, BufferObservation> CurrentObservations
7474
{
7575
get
7676
{
77-
lock (_lock) return _currentObservations;
77+
lock (_lock) return new Dictionary<int, BufferObservation>(_currentObservations);
7878
}
7979
}
8080

8181
public IDictionary<int, IEnumerable<BufferObservation>> CurrentConditions
8282
{
8383
get
8484
{
85-
lock (_lock) return _currentConditions;
85+
lock (_lock) return new Dictionary<int, IEnumerable<BufferObservation>>(_currentConditions);
8686
}
8787
}
8888

@@ -127,10 +127,7 @@ protected virtual void OnBufferObservationAdd(ref BufferObservation observation)
127127
/// </summary>
128128
protected void SetSequence(ulong sequence)
129129
{
130-
lock (_lock)
131-
{
132-
_sequence = sequence;
133-
}
130+
_sequence = sequence;
134131
}
135132

136133
/// <summary>
@@ -163,28 +160,17 @@ public void IncrementSequence(uint count)
163160

164161
protected IEnumerable<BufferObservation> GetCurrentObservations()
165162
{
166-
var x = new List<BufferObservation>();
167-
168-
lock (_lock)
169-
{
170-
var observations = _currentObservations.Values;
171-
if (!observations.IsNullOrEmpty()) x.AddRange(observations);
172-
}
173-
174-
return x;
163+
return new List<BufferObservation>(_currentObservations.Values);
175164
}
176165

177166
protected IEnumerable<BufferObservation> GetCurrentConditions()
178167
{
179168
var x = new List<BufferObservation>();
180169

181-
lock (_lock)
170+
var conditions = _currentConditions.Values;
171+
if (!conditions.IsNullOrEmpty())
182172
{
183-
var conditions = _currentConditions.Values;
184-
if (!conditions.IsNullOrEmpty())
185-
{
186-
foreach (var condition in conditions) x.AddRange(condition);
187-
}
173+
foreach (var condition in conditions) x.AddRange(condition);
188174
}
189175

190176
return x;
@@ -584,13 +570,9 @@ protected void AddCurrentObservation(BufferObservation observation)
584570
// Check for UNAVAILABLE
585571
var isUnavailable = observation.GetValue(ValueKeys.Result) == Observation.Unavailable;
586572

587-
BufferObservation existingObservation;
588-
lock (_lock)
589-
{
590-
_currentObservations.TryGetValue(observation._key, out existingObservation);
591-
_currentObservations.Remove(observation._key);
592-
}
593-
573+
_currentObservations.TryGetValue(observation._key, out var existingObservation);
574+
_currentObservations.Remove(observation._key);
575+
594576
if (existingObservation.IsValid && !isUnavailable)
595577
{
596578
if (resetTriggered == ResetTriggered.NOT_SPECIFIED)
@@ -622,7 +604,7 @@ protected void AddCurrentObservation(BufferObservation observation)
622604
}
623605
}
624606

625-
lock (_lock) _currentObservations.Add(observation._key, observation);
607+
_currentObservations.Add(observation._key, observation);
626608

627609
// Call Overridable Methods
628610
OnCurrentObservationAdd(ref observation);
@@ -641,12 +623,8 @@ protected void AddCurrentCondition(BufferObservation observation)
641623
{
642624
var bufferObservations = new List<BufferObservation>();
643625

644-
IEnumerable<BufferObservation> existingObservations;
645-
lock (_lock)
646-
{
647-
_currentConditions.TryGetValue(observation._key, out existingObservations);
648-
_currentConditions.Remove(observation._key);
649-
}
626+
_currentConditions.TryGetValue(observation._key, out var existingObservations);
627+
_currentConditions.Remove(observation._key);
650628

651629
if (!existingObservations.IsNullOrEmpty())
652630
{
@@ -661,7 +639,7 @@ protected void AddCurrentCondition(BufferObservation observation)
661639
var existingLevel = existingObservation.GetValue(ValueKeys.Level);
662640
var existingNativeCode = existingObservation.GetValue(ValueKeys.NativeCode);
663641

664-
if (existingNativeCode != nativeCode &&
642+
if (existingNativeCode != nativeCode &&
665643
existingLevel != ConditionLevel.UNAVAILABLE.ToString() &&
666644
existingObservation.Sequence != observation.Sequence)
667645
{
@@ -676,15 +654,18 @@ protected void AddCurrentCondition(BufferObservation observation)
676654

677655
// If any WARNING or FAULT states present, then remove any NORMAL states
678656
// Current should only show the active states
679-
if (bufferObservations.Any(o => o.GetValue(ValueKeys.Level) == ConditionLevel.WARNING.ToString() || o.GetValue(ValueKeys.Level) == ConditionLevel.FAULT.ToString()))
657+
if (bufferObservations.Any(o =>
658+
o.GetValue(ValueKeys.Level) == ConditionLevel.WARNING.ToString() ||
659+
o.GetValue(ValueKeys.Level) == ConditionLevel.FAULT.ToString()))
680660
{
681-
bufferObservations.RemoveAll(o => o.GetValue(ValueKeys.Level) == ConditionLevel.NORMAL.ToString());
661+
bufferObservations.RemoveAll(o =>
662+
o.GetValue(ValueKeys.Level) == ConditionLevel.NORMAL.ToString());
682663
}
683664

684665
IEnumerable<BufferObservation> iBufferObservations = bufferObservations;
685666

686667
// Add to stored List
687-
lock (_lock) _currentConditions.Add(observation._key, iBufferObservations);
668+
_currentConditions.Add(observation._key, iBufferObservations);
688669

689670
// Call Overridable Method
690671
OnCurrentConditionChange(GetCurrentConditions());
@@ -841,27 +822,29 @@ public virtual ulong AddObservation(ref BufferObservation observation)
841822
{
842823
if (observation._key >= 0 && !observation._values.IsNullOrEmpty() && observation._timestamp > 0)
843824
{
844-
// Get the Sequence to Add Observation at
845-
ulong sequence;
846-
lock (_lock) sequence = _sequence++;
825+
lock (_lock)
826+
{
827+
// Get the Sequence to Add Observation at
828+
ulong sequence = _sequence++;
847829

848-
observation._sequence = sequence;
830+
observation._sequence = sequence;
849831

850-
if (observation.Category == DataItemCategory.CONDITION)
851-
{
852-
// Add to Current Conditions
853-
AddCurrentCondition(observation);
854-
}
855-
else
856-
{
857-
// Add to Current Observations
858-
AddCurrentObservation(observation);
859-
}
832+
if (observation.Category == DataItemCategory.CONDITION)
833+
{
834+
// Add to Current Conditions
835+
AddCurrentCondition(observation);
836+
}
837+
else
838+
{
839+
// Add to Current Observations
840+
AddCurrentObservation(observation);
841+
}
860842

861-
// Add to Buffer
862-
AddBufferObservation(ref observation);
843+
// Add to Buffer
844+
AddBufferObservation(ref observation);
863845

864-
return sequence;
846+
return sequence;
847+
}
865848
}
866849

867850
return 0;

0 commit comments

Comments
 (0)