-
Notifications
You must be signed in to change notification settings - Fork 850
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change node filters to use a concurrent list instead of a dictionary (#…
…698) * Change node filters to use a list instead of a dictionary so insert order can be maintained. * Fix code review issue * Add optimization for enumerator creation. * Better locking around getting the enumerator * Fix GetEnumerator
- Loading branch information
1 parent
54aa8fd
commit a8854dc
Showing
2 changed files
with
124 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace NBitcoin | ||
{ | ||
public class ThreadSafeList<T> : IEnumerable<T> | ||
{ | ||
private List<T> _Behaviors; | ||
private object _lock = new object(); | ||
|
||
private List<T> _EnumeratorList = null; | ||
|
||
public ThreadSafeList() | ||
{ | ||
lock (_lock) | ||
_Behaviors = new List<T>(); | ||
} | ||
|
||
/// <summary> | ||
/// Add an item to the collection | ||
/// </summary> | ||
/// <param name="item"></param> | ||
/// <returns>When disposed, the item is removed</returns> | ||
public IDisposable Add(T item) | ||
{ | ||
if (item == null) | ||
throw new ArgumentNullException(nameof(item)); | ||
OnAdding(item); | ||
lock (_lock) | ||
{ | ||
_Behaviors.Add(item); | ||
_EnumeratorList = null; | ||
} | ||
return new ActionDisposable(() => | ||
{ | ||
}, () => Remove(item)); | ||
} | ||
|
||
protected virtual void OnAdding(T obj) | ||
{ | ||
} | ||
protected virtual void OnRemoved(T obj) | ||
{ | ||
} | ||
|
||
public bool Remove(T item) | ||
{ | ||
bool removed = false; | ||
lock (_lock) | ||
{ | ||
removed = _Behaviors.Remove(item); | ||
_EnumeratorList = null; | ||
} | ||
|
||
if (removed) | ||
OnRemoved(item); | ||
return removed; | ||
} | ||
|
||
public void Clear() | ||
{ | ||
foreach (var behavior in this) | ||
Remove(behavior); | ||
} | ||
|
||
public T FindOrCreate<U>() where U : T, new() | ||
{ | ||
return FindOrCreate<U>(() => new U()); | ||
} | ||
public U FindOrCreate<U>(Func<U> create) where U : T | ||
{ | ||
var result = this.OfType<U>().FirstOrDefault(); | ||
if (result == null) | ||
{ | ||
result = create(); | ||
Add(result); | ||
} | ||
return result; | ||
} | ||
public U Find<U>() where U : T | ||
{ | ||
return this.OfType<U>().FirstOrDefault(); | ||
} | ||
|
||
public void Remove<U>() where U : T | ||
{ | ||
foreach (var b in this.OfType<U>()) | ||
{ | ||
Remove(b); | ||
} | ||
} | ||
|
||
#region IEnumerable<T> Members | ||
|
||
public IEnumerator<T> GetEnumerator() | ||
{ | ||
IEnumerator<T> enumerator = _EnumeratorList?.GetEnumerator(); | ||
if (enumerator == null) | ||
{ | ||
lock (_lock) | ||
{ | ||
var behaviorsList = _Behaviors.ToList(); | ||
_EnumeratorList = behaviorsList; | ||
enumerator = behaviorsList.GetEnumerator(); | ||
} | ||
} | ||
return enumerator; | ||
} | ||
|
||
#endregion | ||
|
||
#region IEnumerable Members | ||
|
||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
#endregion | ||
} | ||
} |