Skip to content

Commit 0f5778f

Browse files
committed
LockManager AST test
1 parent 661f7d9 commit 0f5778f

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

src/lock/tests/LockManagerTest.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <atomic>
44
#include <latch>
55
#include <memory>
6+
#include <mutex>
7+
#include <unordered_map>
68
#include <thread>
79
#include <vector>
810
#include "../common/status.h"
@@ -173,6 +175,127 @@ BOOST_AUTO_TEST_CASE(LockUnlockNoWaitTest)
173175
}
174176

175177

178+
BOOST_AUTO_TEST_CASE(LockUnlockAstTest)
179+
{
180+
struct Lock;
181+
182+
struct ThreadData
183+
{
184+
LockManager* lockManager = nullptr;
185+
std::mutex* globalMutex = nullptr;
186+
std::mutex localMutex;
187+
std::unordered_map<SLONG, Lock*> locks;
188+
};
189+
190+
struct Lock
191+
{
192+
ThreadData* threadData = nullptr;
193+
unsigned key = 0;
194+
SLONG lockId = 0;
195+
};
196+
197+
constexpr unsigned THREAD_COUNT = 8u;
198+
constexpr unsigned ITERATION_COUNT = 10'000u;
199+
200+
ConfigFile configFile(ConfigFile::USE_TEXT, "\n");
201+
Config config(configFile);
202+
203+
LockManagerTestCallbacks callbacks;
204+
const string lockManagerId(getUniqueId().c_str());
205+
auto lockManager = std::make_unique<LockManager>(lockManagerId, &config);
206+
207+
std::atomic_uint lockSuccess = 0u;
208+
std::atomic_uint lockFail = 0u;
209+
210+
std::vector<std::thread> threads;
211+
std::latch latch(THREAD_COUNT);
212+
213+
static const auto ast = [](void* astArg) -> int {
214+
const auto lock = static_cast<Lock*>(astArg);
215+
const auto threadData = lock->threadData;
216+
217+
std::lock_guard localMutexGuard(threadData->localMutex);
218+
219+
fb_assert(lock->lockId);
220+
221+
if (!threadData->lockManager->dequeue(lock->lockId))
222+
fb_assert(false);
223+
224+
threadData->locks.erase(lock->lockId);
225+
delete lock;
226+
227+
return 0;
228+
};
229+
230+
std::mutex globalMutex;
231+
232+
for (unsigned threadNum = 0u; threadNum < THREAD_COUNT; ++threadNum)
233+
{
234+
threads.emplace_back([&, threadNum]() {
235+
ThreadData threadData;
236+
threadData.lockManager = lockManager.get();
237+
threadData.globalMutex = &globalMutex;
238+
239+
FbLocalStatus statusVector;
240+
LOCK_OWNER_T ownerId = threadNum + 1;
241+
SLONG ownerHandle = 0;
242+
243+
lockManager->initializeOwner(&statusVector, ownerId, LCK_OWNER_attachment, &ownerHandle);
244+
245+
latch.arrive_and_wait();
246+
247+
for (unsigned i = 0; i < ITERATION_COUNT; ++i)
248+
{
249+
std::lock_guard globalMutexGuard(globalMutex);
250+
std::lock_guard localMutexGuard(threadData.localMutex);
251+
252+
const auto lock = new Lock();
253+
lock->threadData = &threadData;
254+
lock->key = i;
255+
lock->lockId = lockManager->enqueue(callbacks, &statusVector, 0,
256+
LCK_expression, (const UCHAR*) &lock->key, sizeof(lock->key), LCK_EX,
257+
ast, lock, 0, LCK_WAIT, ownerHandle);
258+
259+
if (lock->lockId)
260+
{
261+
threadData.locks.insert({ lock->lockId, lock });
262+
++lockSuccess;
263+
}
264+
else
265+
{
266+
fb_assert(false);
267+
delete lock;
268+
++lockFail;
269+
}
270+
}
271+
272+
{ // scope
273+
std::lock_guard globalMutexGuard(globalMutex);
274+
std::lock_guard localMutexGuard(threadData.localMutex);
275+
276+
for (const auto [lockId, lock] : threadData.locks)
277+
{
278+
lockManager->dequeue(lockId);
279+
delete lock;
280+
}
281+
282+
threadData.locks.clear();
283+
}
284+
285+
lockManager->shutdownOwner(callbacks, &ownerHandle);
286+
});
287+
}
288+
289+
for (auto& thread : threads)
290+
thread.join();
291+
292+
BOOST_CHECK_EQUAL(lockFail.load(), 0u);
293+
BOOST_CHECK_EQUAL(lockSuccess.load(), THREAD_COUNT * ITERATION_COUNT);
294+
295+
lockManager.reset();
296+
}
297+
298+
176299
BOOST_AUTO_TEST_SUITE_END() // LockManagerTests
177300
BOOST_AUTO_TEST_SUITE_END() // LockManagerSuite
178301
BOOST_AUTO_TEST_SUITE_END() // EngineSuite

0 commit comments

Comments
 (0)