1//
2// RWLockTest.cpp
3//
4// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "RWLockTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/RWLock.h"
15#include "Poco/Thread.h"
16#include "Poco/Runnable.h"
17
18
19using Poco::RWLock;
20using Poco::Thread;
21using Poco::Runnable;
22
23
24class RWLockRunnable: public Runnable
25{
26public:
27 RWLockRunnable(RWLock& lock, volatile int& counter): _lock(lock), _counter(counter), _ok(true)
28 {
29 }
30
31 void run()
32 {
33 int lastCount = 0;
34 for (int i = 0; i < 10000; ++i)
35 {
36 _lock.readLock();
37 lastCount = _counter;
38 for (int k = 0; k < 100; ++k)
39 {
40 if (_counter != lastCount) _ok = false;
41 Thread::yield();
42 }
43 _lock.unlock();
44 _lock.writeLock();
45 for (int k = 0; k < 100; ++k)
46 {
47 --_counter;
48 Thread::yield();
49 }
50 for (int k = 0; k < 100; ++k)
51 {
52 ++_counter;
53 Thread::yield();
54 }
55 ++_counter;
56 if (_counter <= lastCount) _ok = false;
57 _lock.unlock();
58 }
59 }
60
61 bool ok() const
62 {
63 return _ok;
64 }
65
66private:
67 RWLock& _lock;
68 volatile int& _counter;
69 bool _ok;
70};
71
72
73class RWTryLockRunnable: public Runnable
74{
75public:
76 RWTryLockRunnable(RWLock& lock, volatile int& counter): _lock(lock), _counter(counter), _ok(true)
77 {
78 }
79
80 void run()
81 {
82 int lastCount = 0;
83 for (int i = 0; i < 10000; ++i)
84 {
85 while (!_lock.tryReadLock()) Thread::yield();
86 lastCount = _counter;
87 for (int k = 0; k < 100; ++k)
88 {
89 if (_counter != lastCount) _ok = false;
90 Thread::yield();
91 }
92 _lock.unlock();
93 while (!_lock.tryWriteLock()) Thread::yield();
94 for (int k = 0; k < 100; ++k)
95 {
96 --_counter;
97 Thread::yield();
98 }
99 for (int k = 0; k < 100; ++k)
100 {
101 ++_counter;
102 Thread::yield();
103 }
104 ++_counter;
105 if (_counter <= lastCount) _ok = false;
106 _lock.unlock();
107 }
108 }
109
110 bool ok() const
111 {
112 return _ok;
113 }
114
115private:
116 RWLock& _lock;
117 volatile int& _counter;
118 bool _ok;
119};
120
121
122RWLockTest::RWLockTest(const std::string& rName): CppUnit::TestCase(rName)
123{
124}
125
126
127RWLockTest::~RWLockTest()
128{
129}
130
131
132void RWLockTest::testLock()
133{
134#if defined(ENABLE_LONG_RUNNING_TESTS)
135 RWLock lock;
136 int counter = 0;
137 RWLockRunnable r1(lock, counter);
138 RWLockRunnable r2(lock, counter);
139 RWLockRunnable r3(lock, counter);
140 RWLockRunnable r4(lock, counter);
141 RWLockRunnable r5(lock, counter);
142 Thread t1;
143 Thread t2;
144 Thread t3;
145 Thread t4;
146 Thread t5;
147 t1.start(r1);
148 t2.start(r2);
149 t3.start(r3);
150 t4.start(r4);
151 t5.start(r5);
152 t1.join();
153 t2.join();
154 t3.join();
155 t4.join();
156 t5.join();
157 assertTrue (counter == 50000);
158 assertTrue (r1.ok());
159 assertTrue (r2.ok());
160 assertTrue (r3.ok());
161 assertTrue (r4.ok());
162 assertTrue (r5.ok());
163#endif // defined(ENABLE_LONG_RUNNING_TESTS)
164}
165
166
167void RWLockTest::testTryLock()
168{
169#if defined(ENABLE_LONG_RUNNING_TESTS)
170 RWLock lock;
171 int counter = 0;
172 RWTryLockRunnable r1(lock, counter);
173 RWTryLockRunnable r2(lock, counter);
174 RWTryLockRunnable r3(lock, counter);
175 RWTryLockRunnable r4(lock, counter);
176 RWTryLockRunnable r5(lock, counter);
177 Thread t1;
178 Thread t2;
179 Thread t3;
180 Thread t4;
181 Thread t5;
182 t1.start(r1);
183 t2.start(r2);
184 t3.start(r3);
185 t4.start(r4);
186 t5.start(r5);
187 t1.join();
188 t2.join();
189 t3.join();
190 t4.join();
191 t5.join();
192 assertTrue (counter == 50000);
193 assertTrue (r1.ok());
194 assertTrue (r2.ok());
195 assertTrue (r3.ok());
196 assertTrue (r4.ok());
197 assertTrue (r5.ok());
198#endif // defined(ENABLE_LONG_RUNNING_TESTS)
199}
200
201
202void RWLockTest::setUp()
203{
204}
205
206
207void RWLockTest::tearDown()
208{
209}
210
211
212CppUnit::Test* RWLockTest::suite()
213{
214 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("RWLockTest");
215
216 CppUnit_addTest(pSuite, RWLockTest, testLock);
217 CppUnit_addTest(pSuite, RWLockTest, testTryLock);
218
219 return pSuite;
220}
221