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 | |
19 | using Poco::RWLock; |
20 | using Poco::Thread; |
21 | using Poco::Runnable; |
22 | |
23 | |
24 | class RWLockRunnable: public Runnable |
25 | { |
26 | public: |
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 | |
66 | private: |
67 | RWLock& _lock; |
68 | volatile int& _counter; |
69 | bool _ok; |
70 | }; |
71 | |
72 | |
73 | class RWTryLockRunnable: public Runnable |
74 | { |
75 | public: |
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 | |
115 | private: |
116 | RWLock& _lock; |
117 | volatile int& _counter; |
118 | bool _ok; |
119 | }; |
120 | |
121 | |
122 | RWLockTest::RWLockTest(const std::string& rName): CppUnit::TestCase(rName) |
123 | { |
124 | } |
125 | |
126 | |
127 | RWLockTest::~RWLockTest() |
128 | { |
129 | } |
130 | |
131 | |
132 | void 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 | |
167 | void 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 | |
202 | void RWLockTest::setUp() |
203 | { |
204 | } |
205 | |
206 | |
207 | void RWLockTest::tearDown() |
208 | { |
209 | } |
210 | |
211 | |
212 | CppUnit::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 | |