1
1
#include " firebird.h"
2
2
#include " boost/test/unit_test.hpp"
3
3
#include < atomic>
4
+ #include < chrono>
5
+ #include < functional>
4
6
#include < latch>
5
7
#include < memory>
8
+ #include < memory>
6
9
#include < mutex>
10
+ #include < optional>
7
11
#include < unordered_map>
8
12
#include < thread>
9
13
#include < vector>
@@ -200,22 +204,21 @@ BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
200
204
std::thread::id threadId;
201
205
LockManager* lockManager = nullptr ;
202
206
std::mutex localMutex;
203
- std::unordered_map<SLONG, Lock* > locks;
204
- SLONG ownerHandle;
207
+ std::unordered_map<SLONG, std::unique_ptr< Lock> > locks;
208
+ SLONG ownerHandle = 0 ;
205
209
bool shutdown = false ;
206
210
};
207
211
208
212
struct Lock
209
213
{
210
214
ThreadData* threadData = nullptr ;
211
215
unsigned key = 0 ;
212
- SLONG lockId = 0 ;
213
- bool locked = false ;
216
+ std::optional<SLONG> lockId;
214
217
bool blocking = false ;
215
218
};
216
219
217
220
constexpr unsigned THREAD_COUNT = 8u ;
218
- constexpr unsigned ITERATION_COUNT = 100 '000u ;
221
+ constexpr unsigned ITERATION_COUNT = 10 '000u ;
219
222
220
223
ConfigFile configFile (ConfigFile::USE_TEXT, " \n " );
221
224
Config config (configFile);
@@ -238,25 +241,22 @@ BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
238
241
if (threadData->shutdown )
239
242
return 0 ;
240
243
241
- fb_assert (!lock->locked || lock->lockId );
244
+ fb_assert (!lock->lockId . has_value () || lock->lockId . value () != 0 );
242
245
243
- if (lock->locked )
246
+ if (lock->lockId . has_value () )
244
247
{
245
- if (!threadData->lockManager ->dequeue (lock->lockId ))
248
+ if (!threadData->lockManager ->dequeue (lock->lockId . value () ))
246
249
fb_assert (false );
247
250
248
- const auto num = threadData->locks .erase (lock->lockId );
249
- fb_assert (num == 1 );
250
- delete lock;
251
+ [[maybe_unused]] const auto erasedCount = threadData->locks .erase (lock->lockId .value ());
252
+ fb_assert (erasedCount == 1 );
251
253
}
252
254
else
253
255
lock->blocking = true ;
254
256
255
257
return 0 ;
256
258
};
257
259
258
- // std::mutex globalMutex;
259
-
260
260
for (unsigned threadNum = 0u ; threadNum < THREAD_COUNT; ++threadNum)
261
261
{
262
262
threads.emplace_back ([&, threadNum]() {
@@ -267,67 +267,55 @@ BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
267
267
LockManagerTestCallbacks callbacks (&threadData.localMutex );
268
268
FbLocalStatus statusVector;
269
269
LOCK_OWNER_T ownerId = threadNum + 1 ;
270
- SLONG ownerHandle = 0 ;
271
270
272
- lockManager->initializeOwner (&statusVector, ownerId, LCK_OWNER_attachment, &ownerHandle);
273
- threadData.ownerHandle = ownerHandle;
271
+ lockManager->initializeOwner (&statusVector, ownerId, LCK_OWNER_attachment, &threadData.ownerHandle );
274
272
275
273
latch.arrive_and_wait ();
276
274
277
275
for (unsigned i = 0 ; i < ITERATION_COUNT; ++i)
278
276
{
279
- // std::lock_guard globalMutexGuard(globalMutex);
280
- std::lock_guard localMutexGuard (threadData.localMutex );
281
-
282
- const auto lock = new Lock ();
277
+ auto lock = std::make_unique<Lock>();
283
278
lock->threadData = &threadData;
284
279
lock->key = i;
285
280
286
- lock->lockId = lockManager->enqueue (callbacks, &statusVector, 0 ,
281
+ std::lock_guard localMutexGuard (threadData.localMutex );
282
+
283
+ const auto lockId = lockManager->enqueue (callbacks, &statusVector, 0 ,
287
284
LCK_expression, (const UCHAR*) &lock->key , sizeof (lock->key ), LCK_EX,
288
- ast, lock, 0 , LCK_WAIT, ownerHandle);
285
+ ast, lock. get () , 0 , LCK_WAIT, threadData. ownerHandle );
289
286
290
- if (lock-> lockId )
287
+ if (lockId)
291
288
{
292
289
++lockSuccess;
293
290
294
291
if (lock->blocking )
295
- {
296
- lockManager->dequeue (lock->lockId );
297
- delete lock;
298
- }
292
+ lockManager->dequeue (lockId);
299
293
else
300
294
{
301
- lock->locked = true ;
302
- threadData.locks .insert ({ lock-> lockId , lock });
295
+ lock->lockId = lockId ;
296
+ threadData.locks .insert ({ lockId, std::move ( lock) });
303
297
}
304
298
}
305
299
else
306
300
{
307
301
fb_assert (false );
308
- delete lock;
309
302
++lockFail;
310
303
}
311
304
}
312
305
313
306
{ // scope
314
- // std::lock_guard globalMutexGuard(globalMutex);
315
307
std::lock_guard localMutexGuard (threadData.localMutex );
316
308
317
309
threadData.shutdown = true ;
318
310
319
- for (const auto [lockId, lock] : threadData.locks )
311
+ for (const auto & [lockId, lock] : threadData.locks )
320
312
{
321
313
fb_assert (!lock->blocking );
322
- fb_assert (lock->locked );
323
- fb_assert (lock->lockId );
314
+ fb_assert (lock->lockId .has_value () && lock->lockId .value () == lockId);
324
315
lockManager->dequeue (lockId);
325
316
}
326
317
327
- lockManager->shutdownOwner (callbacks, &ownerHandle);
328
-
329
- for (const auto [lockId, lock] : threadData.locks )
330
- delete lock;
318
+ lockManager->shutdownOwner (callbacks, &threadData.ownerHandle );
331
319
332
320
threadData.locks .clear ();
333
321
}
0 commit comments