11#include " firebird.h"
22#include " boost/test/unit_test.hpp"
33#include < atomic>
4+ #include < chrono>
5+ #include < functional>
46#include < latch>
57#include < memory>
8+ #include < memory>
69#include < mutex>
10+ #include < optional>
711#include < unordered_map>
812#include < thread>
913#include < vector>
@@ -200,22 +204,21 @@ BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
200204 std::thread::id threadId;
201205 LockManager* lockManager = nullptr ;
202206 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 ;
205209 bool shutdown = false ;
206210 };
207211
208212 struct Lock
209213 {
210214 ThreadData* threadData = nullptr ;
211215 unsigned key = 0 ;
212- SLONG lockId = 0 ;
213- bool locked = false ;
216+ std::optional<SLONG> lockId;
214217 bool blocking = false ;
215218 };
216219
217220 constexpr unsigned THREAD_COUNT = 8u ;
218- constexpr unsigned ITERATION_COUNT = 100 '000u ;
221+ constexpr unsigned ITERATION_COUNT = 10 '000u ;
219222
220223 ConfigFile configFile (ConfigFile::USE_TEXT, " \n " );
221224 Config config (configFile);
@@ -238,25 +241,22 @@ BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
238241 if (threadData->shutdown )
239242 return 0 ;
240243
241- fb_assert (!lock->locked || lock->lockId );
244+ fb_assert (!lock->lockId . has_value () || lock->lockId . value () != 0 );
242245
243- if (lock->locked )
246+ if (lock->lockId . has_value () )
244247 {
245- if (!threadData->lockManager ->dequeue (lock->lockId ))
248+ if (!threadData->lockManager ->dequeue (lock->lockId . value () ))
246249 fb_assert (false );
247250
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 );
251253 }
252254 else
253255 lock->blocking = true ;
254256
255257 return 0 ;
256258 };
257259
258- // std::mutex globalMutex;
259-
260260 for (unsigned threadNum = 0u ; threadNum < THREAD_COUNT; ++threadNum)
261261 {
262262 threads.emplace_back ([&, threadNum]() {
@@ -267,67 +267,55 @@ BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
267267 LockManagerTestCallbacks callbacks (&threadData.localMutex );
268268 FbLocalStatus statusVector;
269269 LOCK_OWNER_T ownerId = threadNum + 1 ;
270- SLONG ownerHandle = 0 ;
271270
272- lockManager->initializeOwner (&statusVector, ownerId, LCK_OWNER_attachment, &ownerHandle);
273- threadData.ownerHandle = ownerHandle;
271+ lockManager->initializeOwner (&statusVector, ownerId, LCK_OWNER_attachment, &threadData.ownerHandle );
274272
275273 latch.arrive_and_wait ();
276274
277275 for (unsigned i = 0 ; i < ITERATION_COUNT; ++i)
278276 {
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>();
283278 lock->threadData = &threadData;
284279 lock->key = i;
285280
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 ,
287284 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 );
289286
290- if (lock-> lockId )
287+ if (lockId)
291288 {
292289 ++lockSuccess;
293290
294291 if (lock->blocking )
295- {
296- lockManager->dequeue (lock->lockId );
297- delete lock;
298- }
292+ lockManager->dequeue (lockId);
299293 else
300294 {
301- lock->locked = true ;
302- threadData.locks .insert ({ lock-> lockId , lock });
295+ lock->lockId = lockId ;
296+ threadData.locks .insert ({ lockId, std::move ( lock) });
303297 }
304298 }
305299 else
306300 {
307301 fb_assert (false );
308- delete lock;
309302 ++lockFail;
310303 }
311304 }
312305
313306 { // scope
314- // std::lock_guard globalMutexGuard(globalMutex);
315307 std::lock_guard localMutexGuard (threadData.localMutex );
316308
317309 threadData.shutdown = true ;
318310
319- for (const auto [lockId, lock] : threadData.locks )
311+ for (const auto & [lockId, lock] : threadData.locks )
320312 {
321313 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);
324315 lockManager->dequeue (lockId);
325316 }
326317
327- lockManager->shutdownOwner (callbacks, &ownerHandle);
328-
329- for (const auto [lockId, lock] : threadData.locks )
330- delete lock;
318+ lockManager->shutdownOwner (callbacks, &threadData.ownerHandle );
331319
332320 threadData.locks .clear ();
333321 }
0 commit comments