Açıklama Yok
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.

Lock.h 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. #pragma once
  2. #include "../C/Baselib_Lock.h"
  3. #include "Internal/ScopedAcquireMixin.h"
  4. #include "Time.h"
  5. namespace baselib
  6. {
  7. BASELIB_CPP_INTERFACE
  8. {
  9. // In computer science, a lock or mutex (from mutual exclusion) is a synchronization mechanism for enforcing limits on access to a resource in an environment
  10. // where there are many threads of execution. A lock is designed to enforce a mutual exclusion concurrency control policy.
  11. //
  12. // "Lock (computer science)", Wikipedia: The Free Encyclopedia
  13. // https://en.wikipedia.org/w/index.php?title=Lock_(computer_science)&oldid=875674239
  14. class Lock : public detail::ScopedAcquireMixin<Lock>
  15. {
  16. public:
  17. // non-copyable
  18. Lock(const Lock& other) = delete;
  19. Lock& operator=(const Lock& other) = delete;
  20. // non-movable (strictly speaking not needed but listed to signal intent)
  21. Lock(Lock&& other) = delete;
  22. Lock& operator=(Lock&& other) = delete;
  23. // Creates a lock synchronization primitive.
  24. // If there are not enough system resources to create a lock, process abort is triggered.
  25. Lock()
  26. {
  27. Baselib_Lock_CreateInplace(&m_LockData);
  28. }
  29. // Reclaim resources and memory held by lock.
  30. // If threads are waiting on the lock, calling free may trigger an assert and may cause process abort.
  31. ~Lock()
  32. {
  33. Baselib_Lock_FreeInplace(&m_LockData);
  34. }
  35. // Acquire lock.
  36. //
  37. // If lock is held, either by this or another thread, then the function wait for lock to be released.
  38. //
  39. // This function is guaranteed to emit an acquire barrier.
  40. //
  41. // \param maxSpinCount Max number of times to spin in user space before falling back to the kernel. The actual number
  42. // may differ depending on the underlying implementation but will never exceed the maxSpinCount
  43. // value.
  44. inline void Acquire(const uint32_t maxSpinCount = 0)
  45. {
  46. if (maxSpinCount && Baselib_Lock_TrySpinAcquire(&m_LockData, maxSpinCount))
  47. return;
  48. return Baselib_Lock_Acquire(&m_LockData);
  49. }
  50. // Try to acquire locks.
  51. //
  52. // If lock is held, either by this or another thread, then lock is not acquired and function return false.
  53. //
  54. // When a lock is acquired this function is guaranteed to emit an acquire barrier.
  55. //
  56. // \param maxSpinCount Max number of times to spin in user space before falling back to the kernel. The actual number
  57. // may differ depending on the underlying implementation but will never exceed the maxSpinCount
  58. // value.
  59. // \returns true if lock was acquired.
  60. COMPILER_WARN_UNUSED_RESULT
  61. FORCE_INLINE bool TryAcquire(const uint32_t maxSpinCount = 0)
  62. {
  63. return Baselib_Lock_TrySpinAcquire(&m_LockData, maxSpinCount);
  64. }
  65. // Try to acquire lock.
  66. // If lock is held, either by this or another thread, then the function wait for timeoutInMilliseconds for lock to be released.
  67. //
  68. // When a lock is acquired this function is guaranteed to emit an acquire barrier.
  69. //
  70. // TryAcquire with a zero timeout differs from TryAcquire() in that TryAcquire() is guaranteed to be a user space operation
  71. // while TryAcquire with zero timeout may enter the kernel and cause a context switch.
  72. //
  73. // Timeout passed to this function may be subject to system clock resolution.
  74. // If the system clock has a resolution of e.g. 16ms that means this function may exit with a timeout error 16ms earlier than originally scheduled.
  75. //
  76. // \param maxSpinCount Max number of times to spin in user space before falling back to the kernel. The actual number
  77. // may differ depending on the underlying implementation but will never exceed the maxSpinCount
  78. // value.
  79. // \returns true if lock was acquired.
  80. COMPILER_WARN_UNUSED_RESULT
  81. FORCE_INLINE bool TryTimedAcquire(const timeout_ms timeoutInMilliseconds, const uint32_t maxSpinCount = 0)
  82. {
  83. if (maxSpinCount && Baselib_Lock_TrySpinAcquire(&m_LockData, maxSpinCount))
  84. return true;
  85. return Baselib_Lock_TryTimedAcquire(&m_LockData, timeoutInMilliseconds.count());
  86. }
  87. // Release lock and make it available to other threads.
  88. //
  89. // This function can be called from any thread, not only the thread that acquired the lock.
  90. // If no lock was previously held calling this function result in a no-op.
  91. //
  92. // When the lock is released this function is guaranteed to emit a release barrier.
  93. FORCE_INLINE void Release()
  94. {
  95. return Baselib_Lock_Release(&m_LockData);
  96. }
  97. private:
  98. Baselib_Lock m_LockData;
  99. };
  100. }
  101. }