Mutex.h 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, kleines Filmröllchen <malu.bertsch@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Assertions.h>
  9. #include <AK/Noncopyable.h>
  10. #include <AK/Types.h>
  11. #include <pthread.h>
  12. namespace Threading {
  13. class Mutex {
  14. AK_MAKE_NONCOPYABLE(Mutex);
  15. AK_MAKE_NONMOVABLE(Mutex);
  16. friend class ConditionVariable;
  17. public:
  18. Mutex()
  19. : m_lock_count(0)
  20. {
  21. #ifndef AK_OS_SERENITY
  22. pthread_mutexattr_t attr;
  23. pthread_mutexattr_init(&attr);
  24. pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  25. pthread_mutex_init(&m_mutex, &attr);
  26. #endif
  27. }
  28. ~Mutex()
  29. {
  30. VERIFY(m_lock_count == 0);
  31. // FIXME: pthread_mutex_destroy() is not implemented.
  32. }
  33. void lock();
  34. void unlock();
  35. private:
  36. #ifdef AK_OS_SERENITY
  37. pthread_mutex_t m_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
  38. #else
  39. pthread_mutex_t m_mutex;
  40. #endif
  41. unsigned m_lock_count { 0 };
  42. };
  43. class MutexLocker {
  44. AK_MAKE_NONCOPYABLE(MutexLocker);
  45. AK_MAKE_NONMOVABLE(MutexLocker);
  46. public:
  47. ALWAYS_INLINE explicit MutexLocker(Mutex& mutex)
  48. : m_mutex(mutex)
  49. {
  50. lock();
  51. }
  52. ALWAYS_INLINE ~MutexLocker()
  53. {
  54. unlock();
  55. }
  56. ALWAYS_INLINE void unlock() { m_mutex.unlock(); }
  57. ALWAYS_INLINE void lock() { m_mutex.lock(); }
  58. private:
  59. Mutex& m_mutex;
  60. };
  61. ALWAYS_INLINE void Mutex::lock()
  62. {
  63. pthread_mutex_lock(&m_mutex);
  64. m_lock_count++;
  65. }
  66. ALWAYS_INLINE void Mutex::unlock()
  67. {
  68. VERIFY(m_lock_count > 0);
  69. // FIXME: We need to protect the lock count with the mutex itself.
  70. // This may be bad because we're not *technically* unlocked yet,
  71. // but we're not handling any errors from pthread_mutex_unlock anyways.
  72. m_lock_count--;
  73. pthread_mutex_unlock(&m_mutex);
  74. }
  75. }