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.

83 lines
2.1 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 TextLocker : Locker<string>
  14. {
  15. /// <summary>获取文本的哈希值。</summary>
  16. protected override int GetHash(string target) => target == null ? 0 : target.GetHashCode();
  17. }
  18. /// <summary>锁。</summary>
  19. internal abstract class Locker<TTarget>
  20. {
  21. Dictionary<int, Class<object>> _pool = new Dictionary<int, Class<object>>();
  22. /// <summary>获取目标的哈希值。</summary>
  23. protected abstract int GetHash(TTarget key);
  24. /// <summary>清除所有缓存的锁。</summary>
  25. public void Clear()
  26. {
  27. lock (_pool)
  28. {
  29. _pool.Clear();
  30. }
  31. }
  32. Class<object> GetLocker(TTarget target)
  33. {
  34. var key = GetHash(target);
  35. lock (_pool)
  36. {
  37. if (_pool.TryGetValue(key, out var locker))
  38. {
  39. return locker;
  40. }
  41. else
  42. {
  43. locker = new Class<object>(new object());
  44. _pool.Add(key, locker);
  45. return locker;
  46. }
  47. }
  48. }
  49. /// <summary>锁定目标,执行 Action。</summary>
  50. public void InLock(TTarget target, Action action)
  51. {
  52. if (action == null) return;
  53. var locker = GetLocker(target);
  54. lock (locker.Value) action.Invoke();
  55. }
  56. /// <summary>锁定目标,执行 Func。</summary>
  57. public TResult InLock<TResult>(TTarget target, Func<TResult> func)
  58. {
  59. if (func == null) return default;
  60. var locker = GetLocker(target);
  61. lock (locker.Value) return func.Invoke();
  62. }
  63. }
  64. }