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.

77 lines
1.6KB

  1. #pragma once
  2. #include <common.hpp>
  3. #include <pthread.h>
  4. namespace rack {
  5. /** Allows multiple "reader" threads to obtain a lock simultaneously, but only one "writer" thread.
  6. This implementation is currently just a wrapper for pthreads, which works on Linux/Mac/.
  7. This is available in C++17 as std::shared_mutex, but unfortunately we're using C++11.
  8. */
  9. struct ReadWriteMutex {
  10. pthread_rwlock_t rwlock;
  11. ReadWriteMutex() {
  12. if (pthread_rwlock_init(&rwlock, NULL))
  13. throw Exception("pthread_rwlock_init failed");
  14. }
  15. ~ReadWriteMutex() {
  16. pthread_rwlock_destroy(&rwlock);
  17. }
  18. void lockReader() {
  19. if (pthread_rwlock_rdlock(&rwlock))
  20. throw Exception("pthread_rwlock_rdlock failed");
  21. }
  22. /** Returns whether the lock was acquired. */
  23. bool tryLockReader() {
  24. return pthread_rwlock_tryrdlock(&rwlock) == 0;
  25. }
  26. void unlockReader() {
  27. if (pthread_rwlock_unlock(&rwlock))
  28. throw Exception("pthread_rwlock_unlock failed");
  29. }
  30. void lockWriter() {
  31. if (pthread_rwlock_wrlock(&rwlock))
  32. throw Exception("pthread_rwlock_wrlock failed");
  33. }
  34. /** Returns whether the lock was acquired. */
  35. bool tryLockWriter() {
  36. return pthread_rwlock_trywrlock(&rwlock) == 0;
  37. }
  38. void unlockWriter() {
  39. if (pthread_rwlock_unlock(&rwlock))
  40. throw Exception("pthread_rwlock_unlock failed");
  41. }
  42. };
  43. struct ReadLock {
  44. ReadWriteMutex& m;
  45. ReadLock(ReadWriteMutex& m) : m(m) {
  46. m.lockReader();
  47. }
  48. ~ReadLock() {
  49. m.unlockReader();
  50. }
  51. };
  52. struct WriteLock {
  53. ReadWriteMutex& m;
  54. WriteLock(ReadWriteMutex& m) : m(m) {
  55. m.lockWriter();
  56. }
  57. ~WriteLock() {
  58. m.unlockWriter();
  59. }
  60. };
  61. } // namespace rack