From c04dcc2e7d834218ef2d4194331e383402495ae1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 20:07:22 +0200 Subject: Adding upstream version 2:20.4+dfsg. Signed-off-by: Daniel Baumann --- xbmc/threads/test/TestSharedSection.cpp | 215 ++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 xbmc/threads/test/TestSharedSection.cpp (limited to 'xbmc/threads/test/TestSharedSection.cpp') diff --git a/xbmc/threads/test/TestSharedSection.cpp b/xbmc/threads/test/TestSharedSection.cpp new file mode 100644 index 0000000..fc2ca08 --- /dev/null +++ b/xbmc/threads/test/TestSharedSection.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "threads/Event.h" +#include "threads/IRunnable.h" +#include "threads/SharedSection.h" +#include "threads/test/TestHelpers.h" + +#include +#include +#include + +using namespace std::chrono_literals; + +//============================================================================= +// Helper classes +//============================================================================= + +template +class locker : public IRunnable +{ + CSharedSection& sec; + CEvent* wait; + + std::atomic* mutex; +public: + volatile bool haslock; + volatile bool obtainedlock; + + inline locker(CSharedSection& o, std::atomic* mutex_ = NULL, CEvent* wait_ = NULL) : + sec(o), wait(wait_), mutex(mutex_), haslock(false), obtainedlock(false) {} + + inline locker(CSharedSection& o, CEvent* wait_ = NULL) : + sec(o), wait(wait_), mutex(NULL), haslock(false), obtainedlock(false) {} + + void Run() override + { + AtomicGuard g(mutex); + L lock(sec); + haslock = true; + obtainedlock = true; + if (wait) + wait->Wait(); + haslock = false; + } +}; + +TEST(TestCritSection, General) +{ + CCriticalSection sec; + + std::unique_lock l1(sec); + std::unique_lock l2(sec); +} + +TEST(TestSharedSection, General) +{ + CSharedSection sec; + + std::shared_lock l1(sec); + std::shared_lock l2(sec); +} + +TEST(TestSharedSection, GetSharedLockWhileTryingExclusiveLock) +{ + std::atomic mutex(0L); + CEvent event; + + CSharedSection sec; + + std::shared_lock l1(sec); // get a shared lock + + locker> l2(sec, &mutex); + thread waitThread1(l2); // try to get an exclusive lock + + EXPECT_TRUE(waitForThread(mutex, 1, 10000ms)); + std::this_thread::sleep_for(10ms); // still need to give it a chance to move ahead + + EXPECT_TRUE(!l2.haslock); // this thread is waiting ... + EXPECT_TRUE(!l2.obtainedlock); // this thread is waiting ... + + // now try and get a SharedLock + locker> l3(sec, &mutex, &event); + thread waitThread3(l3); // try to get a shared lock + EXPECT_TRUE(waitForThread(mutex, 2, 10000ms)); + std::this_thread::sleep_for(10ms); + EXPECT_TRUE(l3.haslock); + + event.Set(); + EXPECT_TRUE(waitThread3.timed_join(10000ms)); + + // l3 should have released. + EXPECT_TRUE(!l3.haslock); + + // but the exclusive lock should still not have happened + EXPECT_TRUE(!l2.haslock); // this thread is waiting ... + EXPECT_TRUE(!l2.obtainedlock); // this thread is waiting ... + + // let it go + l1.unlock(); // the last shared lock leaves. + + EXPECT_TRUE(waitThread1.timed_join(10000ms)); + + EXPECT_TRUE(l2.obtainedlock); // the exclusive lock was captured + EXPECT_TRUE(!l2.haslock); // ... but it doesn't have it anymore +} + +TEST(TestSharedSection, TwoCase) +{ + CSharedSection sec; + + CEvent event; + std::atomic mutex(0L); + + locker> l1(sec, &mutex, &event); + + { + std::shared_lock lock(sec); + thread waitThread1(l1); + + EXPECT_TRUE(waitForWaiters(event, 1, 10000ms)); + EXPECT_TRUE(l1.haslock); + + event.Set(); + + EXPECT_TRUE(waitThread1.timed_join(10000ms)); + } + + locker> l2(sec, &mutex, &event); + { + std::unique_lock lock(sec); // get exclusive lock + thread waitThread2(l2); // thread should block + + EXPECT_TRUE(waitForThread(mutex, 1, 10000ms)); + std::this_thread::sleep_for(10ms); + + EXPECT_TRUE(!l2.haslock); + + lock.unlock(); + + EXPECT_TRUE(waitForWaiters(event, 1, 10000ms)); + std::this_thread::sleep_for(10ms); + EXPECT_TRUE(l2.haslock); + + event.Set(); + + EXPECT_TRUE(waitThread2.timed_join(10000ms)); + } +} + +TEST(TestMultipleSharedSection, General) +{ + CSharedSection sec; + + CEvent event; + std::atomic mutex(0L); + + locker> l1(sec, &mutex, &event); + + { + std::shared_lock lock(sec); + thread waitThread1(l1); + + EXPECT_TRUE(waitForThread(mutex, 1, 10000ms)); + std::this_thread::sleep_for(10ms); + + EXPECT_TRUE(l1.haslock); + + event.Set(); + + EXPECT_TRUE(waitThread1.timed_join(10000ms)); + } + + locker> l2(sec, &mutex, &event); + locker> l3(sec, &mutex, &event); + locker> l4(sec, &mutex, &event); + locker> l5(sec, &mutex, &event); + { + std::unique_lock lock(sec); + thread waitThread1(l2); + thread waitThread2(l3); + thread waitThread3(l4); + thread waitThread4(l5); + + EXPECT_TRUE(waitForThread(mutex, 4, 10000ms)); + std::this_thread::sleep_for(10ms); + + EXPECT_TRUE(!l2.haslock); + EXPECT_TRUE(!l3.haslock); + EXPECT_TRUE(!l4.haslock); + EXPECT_TRUE(!l5.haslock); + + lock.unlock(); + + EXPECT_TRUE(waitForWaiters(event, 4, 10000ms)); + + EXPECT_TRUE(l2.haslock); + EXPECT_TRUE(l3.haslock); + EXPECT_TRUE(l4.haslock); + EXPECT_TRUE(l5.haslock); + + event.Set(); + + EXPECT_TRUE(waitThread1.timed_join(10000ms)); + EXPECT_TRUE(waitThread2.timed_join(10000ms)); + EXPECT_TRUE(waitThread3.timed_join(10000ms)); + EXPECT_TRUE(waitThread4.timed_join(10000ms)); + } +} + -- cgit v1.2.3