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.

92 lines
2.4 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using static System.Collections.Specialized.BitVector32;
  4. namespace Apewer.Internals
  5. {
  6. /// <summary>整数锁。</summary>
  7. internal sealed class Int32Locker : Locker<int>
  8. {
  9. /// <summary>获取整数的哈希值。</summary>
  10. protected override int GetHash(int target) => target;
  11. }
  12. /// <summary>整数锁。</summary>
  13. internal sealed class Int64Locker : Locker<long>
  14. {
  15. /// <summary>获取整数的哈希值。</summary>
  16. protected override int GetHash(long target) => target.GetHashCode();
  17. }
  18. /// <summary>文本锁。</summary>
  19. internal sealed class TextLocker : Locker<string>
  20. {
  21. /// <summary>获取文本的哈希值。</summary>
  22. protected override int GetHash(string target) => target == null ? 0 : target.GetHashCode();
  23. }
  24. /// <summary>锁。</summary>
  25. internal abstract class Locker<TTarget>
  26. {
  27. Dictionary<int, Class<object>> _pool = new Dictionary<int, Class<object>>();
  28. /// <summary>获取目标的哈希值。</summary>
  29. protected abstract int GetHash(TTarget key);
  30. /// <summary>清除所有缓存的锁。</summary>
  31. public void Clear()
  32. {
  33. lock (_pool)
  34. {
  35. _pool.Clear();
  36. }
  37. }
  38. Class<object> GetLocker(TTarget target)
  39. {
  40. var key = GetHash(target);
  41. lock (_pool)
  42. {
  43. if (_pool.TryGetValue(key, out var locker))
  44. {
  45. return locker;
  46. }
  47. else
  48. {
  49. locker = new Class<object>(new object());
  50. _pool.Add(key, locker);
  51. return locker;
  52. }
  53. }
  54. }
  55. /// <summary>锁定目标,执行 Action。</summary>
  56. public void InLock(TTarget target, Action action)
  57. {
  58. if (action == null) return;
  59. var locker = GetLocker(target);
  60. lock (locker.Value) action.Invoke();
  61. }
  62. /// <summary>锁定目标,执行 Func。</summary>
  63. public TResult InLock<TResult>(TTarget target, Func<TResult> func)
  64. {
  65. if (func == null) return default;
  66. var locker = GetLocker(target);
  67. lock (locker.Value) return func.Invoke();
  68. }
  69. }
  70. }