You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Zero/ZeroLevel/Services/Collections/ZPriorityQueue.cs

128 lines
3.6 KiB

using System;
namespace ZeroLevel.Services.Collections
{
public interface IPriorityQueue<T>
{
int Count { get; }
void Append(T item, int priority);
T HandleCurrentItem();
}
public struct PriorityQueueObjectHandleResult
{
public bool IsCompleted;
public bool CanBeSkipped;
}
public class ZPriorityQueue<T>
: IPriorityQueue<T>
{
7 months ago
private sealed class PriorityQueueObject<T1>
{
public readonly int Priority;
7 months ago
public readonly T1 Value;
7 months ago
public PriorityQueueObject<T1> Next;
7 months ago
public PriorityQueueObject(T1 val, int priority)
{
Value = val;
Priority = priority;
}
}
private readonly Func<T, PriorityQueueObjectHandleResult> _handler;
7 months ago
private PriorityQueueObject<T> _head = null!;
private readonly object _rw_lock = new object();
private int _counter = 0;
public int Count => _counter;
public ZPriorityQueue(Func<T, PriorityQueueObjectHandleResult> handler)
{
7 months ago
if (handler == null!)
throw new ArgumentNullException(nameof(handler));
_handler = handler;
}
public void Append(T item, int priority)
{
var insert = new PriorityQueueObject<T>(item, priority);
lock (_rw_lock)
{
if (null == _head)
{
_head = insert;
}
else
{
var cursor = _head;
7 months ago
PriorityQueueObject<T> prev = null!;
do
{
if (cursor.Priority > insert.Priority)
{
insert.Next = cursor;
if (null == prev) // insert to head
{
_head = insert;
}
else
{
prev.Next = insert;
}
break;
}
prev = cursor;
cursor = cursor.Next;
7 months ago
if (cursor == null!)
{
prev.Next = insert;
}
7 months ago
} while (cursor != null!);
}
_counter++;
}
return;
}
public T HandleCurrentItem()
{
7 months ago
T v = default(T)!;
lock (_rw_lock)
{
var item = _head;
7 months ago
PriorityQueueObject<T> prev = null!;
while (item != null!)
{
var result = this._handler.Invoke(item.Value);
if (result.IsCompleted)
{
7 months ago
if (prev != null!)
{
prev.Next = item.Next;
}
else
{
_head = _head.Next;
}
v = item.Value;
break;
}
if (result.CanBeSkipped == false)
{
break;
}
prev = item;
item = item.Next;
}
}
return v;
}
}
}

Powered by TurnKey Linux.