From 6cc7bc4cbf68048c5d28f331ad08c1d26559fb2a Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Thu, 13 Jun 2019 20:40:16 +0800 Subject: [PATCH] add some tools --- .../HandyControlDemo_Net_GE45.csproj | 3 - .../Data/Args/KeyboardHookEventArgs.cs | 2 +- .../HandyControl_Shared.projitems | 4 + .../Tools/Hook/KeyboardHook.cs | 2 +- .../HandyControl_Shared/Tools/Pool/IPool!1.cs | 9 + .../Tools/Pool/SimplePool!1.cs | 64 ++++ .../Tools/Pool/SynchronizedPool!1.cs | 27 ++ .../Tools/Queue/Deque!1.cs | 345 ++++++++++++++++++ 8 files changed, 451 insertions(+), 5 deletions(-) create mode 100644 src/Shared/HandyControl_Shared/Tools/Pool/IPool!1.cs create mode 100644 src/Shared/HandyControl_Shared/Tools/Pool/SimplePool!1.cs create mode 100644 src/Shared/HandyControl_Shared/Tools/Pool/SynchronizedPool!1.cs create mode 100644 src/Shared/HandyControl_Shared/Tools/Queue/Deque!1.cs diff --git a/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj b/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj index e5a45bc4..57947a1f 100644 --- a/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj +++ b/src/Net_GE45/HandyControlDemo_Net_GE45/HandyControlDemo_Net_GE45.csproj @@ -457,9 +457,6 @@ TextTemplatingFileGenerator MessageToken.cs - - Resources\Img\LeftMainContent\PaneLayout_16x.png - Resources\Img\LeftMainContent\brackets_Square_16xLG.png diff --git a/src/Shared/HandyControl_Shared/Data/Args/KeyboardHookEventArgs.cs b/src/Shared/HandyControl_Shared/Data/Args/KeyboardHookEventArgs.cs index 717c6384..4f50f3e1 100644 --- a/src/Shared/HandyControl_Shared/Data/Args/KeyboardHookEventArgs.cs +++ b/src/Shared/HandyControl_Shared/Data/Args/KeyboardHookEventArgs.cs @@ -3,7 +3,7 @@ using System.Windows.Input; namespace HandyControl.Data { - internal class KeyboardHookEventArgs : EventArgs + public class KeyboardHookEventArgs : EventArgs { public bool IsSystemKey { get; } diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index 2253c400..32e07fa8 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -271,6 +271,10 @@ + + + + diff --git a/src/Shared/HandyControl_Shared/Tools/Hook/KeyboardHook.cs b/src/Shared/HandyControl_Shared/Tools/Hook/KeyboardHook.cs index 32bb8dcf..07ce92b6 100644 --- a/src/Shared/HandyControl_Shared/Tools/Hook/KeyboardHook.cs +++ b/src/Shared/HandyControl_Shared/Tools/Hook/KeyboardHook.cs @@ -6,7 +6,7 @@ using HandyControl.Tools.Interop; namespace HandyControl.Tools { - internal class KeyboardHook + public class KeyboardHook { public static event EventHandler KeyDown; diff --git a/src/Shared/HandyControl_Shared/Tools/Pool/IPool!1.cs b/src/Shared/HandyControl_Shared/Tools/Pool/IPool!1.cs new file mode 100644 index 00000000..5eeeac75 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Tools/Pool/IPool!1.cs @@ -0,0 +1,9 @@ +namespace HandyControl.Tools +{ + public interface IPool + { + T Acquire(); + + bool Release(T instance); + } +} diff --git a/src/Shared/HandyControl_Shared/Tools/Pool/SimplePool!1.cs b/src/Shared/HandyControl_Shared/Tools/Pool/SimplePool!1.cs new file mode 100644 index 00000000..53731a46 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Tools/Pool/SimplePool!1.cs @@ -0,0 +1,64 @@ +//adapted from https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/Pools.java + +using System; + +namespace HandyControl.Tools +{ + public class SimplePool : IPool + { + private readonly object[] _pool; + + private int _poolSize; + + public SimplePool(int maxPoolSize) + { + if (maxPoolSize <= 0) + { + throw new ArgumentException("The max pool size must be > 0"); + } + _pool = new object[maxPoolSize]; + } + + public virtual T Acquire() + { + if (_poolSize > 0) + { + var lastPooledIndex = _poolSize - 1; + var instance = (T)_pool[lastPooledIndex]; + _pool[lastPooledIndex] = null; + _poolSize--; + return instance; + } + return default; + } + + public virtual bool Release(T instance) + { + if (IsInPool(instance)) + { + throw new Exception("Already in the pool!"); + } + + if (_poolSize < _pool.Length) + { + _pool[_poolSize] = instance; + _poolSize++; + return true; + } + + return false; + } + + private bool IsInPool(T instance) + { + for (var i = 0; i < _poolSize; i++) + { + if (Equals(_pool[i], instance)) + { + return true; + } + } + return false; + } + } +} diff --git a/src/Shared/HandyControl_Shared/Tools/Pool/SynchronizedPool!1.cs b/src/Shared/HandyControl_Shared/Tools/Pool/SynchronizedPool!1.cs new file mode 100644 index 00000000..0a430778 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Tools/Pool/SynchronizedPool!1.cs @@ -0,0 +1,27 @@ +namespace HandyControl.Tools +{ + public class SynchronizedPool : SimplePool + { + private readonly object _lockObj = new object(); + + public SynchronizedPool(int maxPoolSize) : base(maxPoolSize) + { + + } + + public override T Acquire() + { + lock (_lockObj) + { + return base.Acquire(); + } + } + + public override bool Release(T element) + { + lock (_lockObj) { + return base.Release(element); + } + } + } +} diff --git a/src/Shared/HandyControl_Shared/Tools/Queue/Deque!1.cs b/src/Shared/HandyControl_Shared/Tools/Queue/Deque!1.cs new file mode 100644 index 00000000..d15c992c --- /dev/null +++ b/src/Shared/HandyControl_Shared/Tools/Queue/Deque!1.cs @@ -0,0 +1,345 @@ +// adapted from https://www.c-sharpcorner.com/uploadfile/b942f9/implementing-a-double-ended-queue-or-deque-in-c-sharp/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; + +namespace HandyControl.Tools +{ + [Serializable] + public class Deque : IEnumerable, ICollection + { + [NonSerialized] + private object _syncRoot; + + private List _front; + + private List _back; + + private int _frontDeleted; + + private int _backDeleted; + + public int Capacity => _front.Capacity + _back.Capacity; + + public int Count => _front.Count + _back.Count - _frontDeleted - _backDeleted; + + public bool IsEmpty => Count == 0; + + public IEnumerable Reversed + { + get + { + if (_back.Count - _backDeleted > 0) + { + for (var i = _back.Count - 1; i >= _backDeleted; i--) yield return _back[i]; + } + + if (_front.Count - _frontDeleted > 0) + { + for (var i = _frontDeleted; i < _front.Count; i++) yield return _front[i]; + } + } + } + + public Deque() + { + _front = new List(); + _back = new List(); + } + + public Deque(int capacity) + { + if (capacity < 0) throw new ArgumentException("Capacity cannot be negative"); + var temp = capacity / 2; + var temp2 = capacity - temp; + _front = new List(temp); + _back = new List(temp2); + } + + public Deque(IEnumerable backCollection) : this(backCollection, null) + { + + } + + public Deque(IEnumerable backCollection, IEnumerable frontCollection) + { + if (backCollection == null && frontCollection == null) throw new ArgumentException("Collections cannot both be null"); + _front = new List(); + _back = new List(); + + if (backCollection != null) + { + foreach (var item in backCollection) _back.Add(item); + } + + if (frontCollection != null) + { + foreach (var item in frontCollection) _front.Add(item); + } + } + + public void AddFirst(T item) + { + if (_frontDeleted > 0 && _front.Count == _front.Capacity) + { + _front.RemoveRange(0, _frontDeleted); + _frontDeleted = 0; + } + + _front.Add(item); + } + + public void AddLast(T item) + { + if (_backDeleted > 0 && _back.Count == _back.Capacity) + { + _back.RemoveRange(0, _backDeleted); + _backDeleted = 0; + } + + _back.Add(item); + } + + public void AddRangeFirst(IEnumerable range) + { + if (range == null) return; + + foreach (var item in range) AddFirst(item); + } + + public void AddRangeLast(IEnumerable range) + { + if (range == null) return; + + foreach (var item in range) AddLast(item); + } + + public void Clear() + { + _front.Clear(); + _back.Clear(); + _frontDeleted = 0; + _backDeleted = 0; + } + + public bool Contains(T item) + { + for (var i = _frontDeleted; i < _front.Count; i++) + { + if (Equals(_front[i], item)) return true; + } + + for (var i = _backDeleted; i < _back.Count; i++) + { + if (Equals(_back[i], item)) return true; + } + + return false; + } + + public void CopyTo(T[] array, int index) + { + if (array == null) throw new ArgumentNullException("Array cannot be null"); + if (index < 0) throw new ArgumentOutOfRangeException("Index cannot be negative"); + if (array.Length < index + Count) throw new ArgumentException("Index is invalid"); + var i = index; + + foreach (var item in this) + { + array[i++] = item; + } + } + + public IEnumerator GetEnumerator() + { + if (_front.Count - _frontDeleted > 0) + { + for (var i = _front.Count - 1; i >= _frontDeleted; i--) yield return _front[i]; + } + + if (_back.Count - _backDeleted > 0) + { + for (var i = _backDeleted; i < _back.Count; i++) yield return _back[i]; + } + } + + public T PeekFirst() + { + if (_front.Count > _frontDeleted) + { + return _front[_front.Count - 1]; + } + + if (_back.Count > _backDeleted) + { + return _back[_backDeleted]; + } + + throw new InvalidOperationException("Can't peek at empty Deque"); + } + + public T PeekLast() + { + if (_back.Count > _backDeleted) + { + return _back[_back.Count - 1]; + } + + if (_front.Count > _frontDeleted) + { + return _front[_frontDeleted]; + } + + throw new InvalidOperationException("Can't peek at empty Deque"); + } + + public T PopFirst() + { + T result; + + if (_front.Count > _frontDeleted) + { + result = _front[_front.Count - 1]; + _front.RemoveAt(_front.Count - 1); + } + else if (_back.Count > _backDeleted) + { + result = _back[_backDeleted]; + _backDeleted++; + } + else + { + throw new InvalidOperationException("Can't pop empty Deque"); + } + + return result; + } + + + public T PopLast() + { + T result; + + if (_back.Count > _backDeleted) + { + result = _back[_back.Count - 1]; + _back.RemoveAt(_back.Count - 1); + } + else if (_front.Count > _frontDeleted) + { + result = _front[_frontDeleted]; + _frontDeleted++; + } + else + { + throw new InvalidOperationException("Can't pop empty Deque"); + } + + return result; + } + + public void Reverse() + { + var temp = _front; + _front = _back; + _back = temp; + var temp2 = _frontDeleted; + _frontDeleted = _backDeleted; + _backDeleted = temp2; + } + + public T[] ToArray() + { + if (Count == 0) return new T[0]; + var result = new T[Count]; + CopyTo(result, 0); + return result; + } + + public void TrimExcess() + { + if (_frontDeleted > 0) + { + _front.RemoveRange(0, _frontDeleted); + _frontDeleted = 0; + } + + if (_backDeleted > 0) + { + _back.RemoveRange(0, _backDeleted); + _backDeleted = 0; + } + + _front.TrimExcess(); + _back.TrimExcess(); + } + + public bool TryPeekFirst(out T item) + { + if (!IsEmpty) + { + item = PeekFirst(); + return true; + } + + item = default; + return false; + } + + public bool TryPeekLast(out T item) + { + if (!IsEmpty) + { + item = PeekLast(); + return true; + } + + item = default; + return false; + } + + public bool TryPopFirst(out T item) + { + if (!IsEmpty) + { + item = PopFirst(); + return true; + } + + item = default; + return false; + } + + public bool TryPopLast(out T item) + { + if (!IsEmpty) + { + item = PopLast(); + return true; + } + + item = default; + return false; + } + + bool ICollection.IsSynchronized => false; + + object ICollection.SyncRoot + { + get + { + if (_syncRoot == null) + { + Interlocked.CompareExchange(ref _syncRoot, new object(), null); + } + return _syncRoot; + } + } + + void ICollection.CopyTo(Array array, int index) => CopyTo((T[])array, index); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +}