rwlock_ut.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include "rwlock.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/thread/pool.h>
  4. #include <util/random/random.h>
  5. #include <atomic>
  6. class TRWMutexTest: public TTestBase {
  7. UNIT_TEST_SUITE(TRWMutexTest);
  8. UNIT_TEST(TestReaders)
  9. UNIT_TEST(TestReadersWriters)
  10. UNIT_TEST_SUITE_END();
  11. struct TSharedData {
  12. std::atomic<size_t> writersIn = 0;
  13. std::atomic<size_t> readersIn = 0;
  14. bool failed = false;
  15. TRWMutex mutex;
  16. };
  17. class TThreadTask: public IObjectInQueue {
  18. public:
  19. using PFunc = void (TThreadTask::*)(void);
  20. TThreadTask(PFunc func, TSharedData& data, size_t id, size_t total)
  21. : Func_(func)
  22. , Data_(data)
  23. , Id_(id)
  24. , Total_(total)
  25. {
  26. }
  27. void Process(void*) override {
  28. THolder<TThreadTask> This(this);
  29. (this->*Func_)();
  30. }
  31. #define FAIL_ASSERT(cond) \
  32. if (!(cond)) { \
  33. Data_.failed = true; \
  34. }
  35. void RunReaders() {
  36. Data_.mutex.AcquireRead();
  37. ++Data_.readersIn;
  38. usleep(100);
  39. FAIL_ASSERT(Data_.readersIn.load() == Total_);
  40. usleep(100);
  41. --Data_.readersIn;
  42. Data_.mutex.ReleaseRead();
  43. }
  44. void RunReadersWriters() {
  45. if (Id_ % 2 == 0) {
  46. for (size_t i = 0; i < 10; ++i) {
  47. Data_.mutex.AcquireRead();
  48. ++Data_.readersIn;
  49. FAIL_ASSERT(Data_.writersIn.load() == 0);
  50. usleep(RandomNumber<ui32>() % 5);
  51. --Data_.readersIn;
  52. Data_.mutex.ReleaseRead();
  53. }
  54. } else {
  55. for (size_t i = 0; i < 10; ++i) {
  56. Data_.mutex.AcquireWrite();
  57. ++Data_.writersIn;
  58. FAIL_ASSERT(Data_.readersIn.load() == 0 && Data_.writersIn.load() == 1);
  59. usleep(RandomNumber<ui32>() % 5);
  60. --Data_.writersIn;
  61. Data_.mutex.ReleaseWrite();
  62. }
  63. }
  64. }
  65. #undef FAIL_ASSERT
  66. private:
  67. PFunc Func_;
  68. TSharedData& Data_;
  69. size_t Id_;
  70. size_t Total_;
  71. };
  72. private:
  73. #define RUN_CYCLE(what, count) \
  74. Q_.Start(count); \
  75. for (size_t i = 0; i < count; ++i) { \
  76. UNIT_ASSERT(Q_.Add(new TThreadTask(&TThreadTask::what, Data_, i, count))); \
  77. } \
  78. Q_.Stop(); \
  79. bool b = Data_.failed; \
  80. Data_.failed = false; \
  81. UNIT_ASSERT(!b);
  82. void TestReaders() {
  83. RUN_CYCLE(RunReaders, 1);
  84. }
  85. void TestReadersWriters() {
  86. RUN_CYCLE(RunReadersWriters, 1);
  87. }
  88. #undef RUN_CYCLE
  89. private:
  90. TSharedData Data_;
  91. TThreadPool Q_;
  92. };
  93. UNIT_TEST_SUITE_REGISTRATION(TRWMutexTest)