JD2022-TU1/main/tools/framework/JD.Collections/Lockless/NodeManager.cs

120 lines
No EOL
4.1 KiB
C#

// Copyright (c) 2006-2007 by Jeffrey Richter and Wintellect
// NOTE: I have not done extensive testing on my lock-free collections and
// I do not feel comfortable recommending their use at this time. This is
// why the classes are all 'internal'. As I personally have no need for these
// classes, I have suspended work on them. If people express more interest in
// them, then I may pursue working on them more in the future.
using System.Diagnostics.CodeAnalysis;
namespace JD.Collections.Lockless
{
internal class NodeManager<T>
{
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes",
Justification = "This is by design since this is a factory")]
public static NodeManager<T> Default = new NodeManager<T>();
public LocklessNode<T> Allocate() { return Allocate(default(T)); }
public virtual LocklessNode<T> Allocate(T item)
{
return new LocklessNode<T>(item);
}
public virtual void Free(LocklessNode<T> node)
{
node.Item = default(T); // Allow early GC
}
}
}
#region TestCode
#if false
namespace Ubi.Tools.Oasis.Shared.PowerThreading.Collections {
public static class Test {
public static void Test() {
PerfTest();
//StackTest();
//QueueTest();
}
static void PerfTest() {
const int iterations = 10000;
const int opsPerIteration = 1000;
Stack<int> s1 = new Stack<int>();
s1.Push(0); s1.Pop(); // JIT
using (new OperationTimer("s1, no locking")) {
for (int times = 0; times < iterations; times++) {
for (int x = 0; x < opsPerIteration; x++) { s1.Push(x); }
for (int x = 0; x < opsPerIteration; x++) { int z = s1.Pop(); }
}
}
using (new OperationTimer("s1, with locking")) {
for (int times = 0; times < iterations; times++) {
for (int x = 0; x < opsPerIteration; x++) { lock (s1) { s1.Push(x); } }
for (int x = 0; x < opsPerIteration; x++) { lock (s1) { int z = s1.Pop(); } }
}
}
LockFreeStack<int> lfs = new LockFreeStack<int>();
lfs.Push(0); lfs.Pop(); // JIT
using (new OperationTimer("lfs, no node pooling")) {
for (int times = 0; times < iterations; times++) {
for (int x = 0; x < opsPerIteration; x++) { lfs.Push(x); }
for (int x = 0; x < opsPerIteration; x++) { int z = lfs.Pop(); }
}
}
LockFreeStack<int> lfs2 = new LockFreeStack<int>(new NodePool<int>());
lfs2.Push(0); lfs2.Pop(); // JIT
using (new OperationTimer("lfs, with node pooling")) {
for (int times = 0; times < iterations; times++) {
for (int x = 0; x < opsPerIteration; x++) { lfs2.Push(x); }
for (int x = 0; x < opsPerIteration; x++) { int z = lfs2.Pop(); }
}
}
}
static void QueueTest() {
LockFreeQueue<Int32> q = new LockFreeQueue<int>(new NodePool<Int32>());
#if true
ThreadPool.QueueUserWorkItem(delegate(Object o) {
while (true) {
Int32 d;
if (q.TryDequeue(out d)) Console.WriteLine(d);
};
});
#endif
Int32 z;
while (q.TryDequeue(out z)) Console.WriteLine(z);
for (int x = 0; x < 100; x += 2) {
q.Enqueue(x);
Thread.Sleep(0);
}
while (q.TryDequeue(out z)) Console.WriteLine(z);
Console.ReadLine();
}
static void StackTest() {
LockFreeStack<Int32> s = new LockFreeStack<int>(new NodePool<Int32>());
ThreadPool.QueueUserWorkItem(delegate(Object o) {
while (true) {
Int32 d;
if (s.TryPop(out d)) Console.WriteLine(d);
};
});
Int32 z;
while (s.TryPop(out z)) Console.WriteLine(z);
for (int x = 0; x < 100; x += 2) {
s.Push(x);
Thread.Sleep(0);
}
//while (s.TryPop(out z)) Console.WriteLine(z);
Console.ReadLine();
}
}
}
#endif
#endregion