2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "threads/Event.h"
10 #include "threads/IRunnable.h"
11 #include "threads/SharedSection.h"
12 #include "threads/test/TestHelpers.h"
15 #include <shared_mutex>
18 using namespace std::chrono_literals
;
20 //=============================================================================
22 //=============================================================================
25 class locker
: public IRunnable
30 std::atomic
<long>* mutex
;
32 volatile bool haslock
;
33 volatile bool obtainedlock
;
35 inline locker(CSharedSection
& o
, std::atomic
<long>* mutex_
= NULL
, CEvent
* wait_
= NULL
) :
36 sec(o
), wait(wait_
), mutex(mutex_
), haslock(false), obtainedlock(false) {}
38 inline locker(CSharedSection
& o
, CEvent
* wait_
= NULL
) :
39 sec(o
), wait(wait_
), mutex(NULL
), haslock(false), obtainedlock(false) {}
53 TEST(TestCritSection
, General
)
57 std::unique_lock
<CCriticalSection
> l1(sec
);
58 std::unique_lock
<CCriticalSection
> l2(sec
);
61 TEST(TestSharedSection
, General
)
65 std::shared_lock
<CSharedSection
> l1(sec
);
66 std::shared_lock
<CSharedSection
> l2(sec
);
69 TEST(TestSharedSection
, GetSharedLockWhileTryingExclusiveLock
)
71 std::atomic
<long> mutex(0L);
76 std::shared_lock
<CSharedSection
> l1(sec
); // get a shared lock
78 locker
<std::unique_lock
<CSharedSection
>> l2(sec
, &mutex
);
79 thread
waitThread1(l2
); // try to get an exclusive lock
81 EXPECT_TRUE(waitForThread(mutex
, 1, 10000ms
));
82 std::this_thread::sleep_for(10ms
); // still need to give it a chance to move ahead
84 EXPECT_TRUE(!l2
.haslock
); // this thread is waiting ...
85 EXPECT_TRUE(!l2
.obtainedlock
); // this thread is waiting ...
87 // now try and get a SharedLock
88 locker
<std::shared_lock
<CSharedSection
>> l3(sec
, &mutex
, &event
);
89 thread
waitThread3(l3
); // try to get a shared lock
90 EXPECT_TRUE(waitForThread(mutex
, 2, 10000ms
));
91 std::this_thread::sleep_for(10ms
);
92 EXPECT_TRUE(l3
.haslock
);
95 EXPECT_TRUE(waitThread3
.timed_join(10000ms
));
97 // l3 should have released.
98 EXPECT_TRUE(!l3
.haslock
);
100 // but the exclusive lock should still not have happened
101 EXPECT_TRUE(!l2
.haslock
); // this thread is waiting ...
102 EXPECT_TRUE(!l2
.obtainedlock
); // this thread is waiting ...
105 l1
.unlock(); // the last shared lock leaves.
107 EXPECT_TRUE(waitThread1
.timed_join(10000ms
));
109 EXPECT_TRUE(l2
.obtainedlock
); // the exclusive lock was captured
110 EXPECT_TRUE(!l2
.haslock
); // ... but it doesn't have it anymore
113 TEST(TestSharedSection
, TwoCase
)
118 std::atomic
<long> mutex(0L);
120 locker
<std::shared_lock
<CSharedSection
>> l1(sec
, &mutex
, &event
);
123 std::shared_lock
<CSharedSection
> lock(sec
);
124 thread
waitThread1(l1
);
126 EXPECT_TRUE(waitForWaiters(event
, 1, 10000ms
));
127 EXPECT_TRUE(l1
.haslock
);
131 EXPECT_TRUE(waitThread1
.timed_join(10000ms
));
134 locker
<std::shared_lock
<CSharedSection
>> l2(sec
, &mutex
, &event
);
136 std::unique_lock
<CSharedSection
> lock(sec
); // get exclusive lock
137 thread
waitThread2(l2
); // thread should block
139 EXPECT_TRUE(waitForThread(mutex
, 1, 10000ms
));
140 std::this_thread::sleep_for(10ms
);
142 EXPECT_TRUE(!l2
.haslock
);
146 EXPECT_TRUE(waitForWaiters(event
, 1, 10000ms
));
147 std::this_thread::sleep_for(10ms
);
148 EXPECT_TRUE(l2
.haslock
);
152 EXPECT_TRUE(waitThread2
.timed_join(10000ms
));
156 TEST(TestMultipleSharedSection
, General
)
161 std::atomic
<long> mutex(0L);
163 locker
<std::shared_lock
<CSharedSection
>> l1(sec
, &mutex
, &event
);
166 std::shared_lock
<CSharedSection
> lock(sec
);
167 thread
waitThread1(l1
);
169 EXPECT_TRUE(waitForThread(mutex
, 1, 10000ms
));
170 std::this_thread::sleep_for(10ms
);
172 EXPECT_TRUE(l1
.haslock
);
176 EXPECT_TRUE(waitThread1
.timed_join(10000ms
));
179 locker
<std::shared_lock
<CSharedSection
>> l2(sec
, &mutex
, &event
);
180 locker
<std::shared_lock
<CSharedSection
>> l3(sec
, &mutex
, &event
);
181 locker
<std::shared_lock
<CSharedSection
>> l4(sec
, &mutex
, &event
);
182 locker
<std::shared_lock
<CSharedSection
>> l5(sec
, &mutex
, &event
);
184 std::unique_lock
<CSharedSection
> lock(sec
);
185 thread
waitThread1(l2
);
186 thread
waitThread2(l3
);
187 thread
waitThread3(l4
);
188 thread
waitThread4(l5
);
190 EXPECT_TRUE(waitForThread(mutex
, 4, 10000ms
));
191 std::this_thread::sleep_for(10ms
);
193 EXPECT_TRUE(!l2
.haslock
);
194 EXPECT_TRUE(!l3
.haslock
);
195 EXPECT_TRUE(!l4
.haslock
);
196 EXPECT_TRUE(!l5
.haslock
);
200 EXPECT_TRUE(waitForWaiters(event
, 4, 10000ms
));
202 EXPECT_TRUE(l2
.haslock
);
203 EXPECT_TRUE(l3
.haslock
);
204 EXPECT_TRUE(l4
.haslock
);
205 EXPECT_TRUE(l5
.haslock
);
209 EXPECT_TRUE(waitThread1
.timed_join(10000ms
));
210 EXPECT_TRUE(waitThread2
.timed_join(10000ms
));
211 EXPECT_TRUE(waitThread3
.timed_join(10000ms
));
212 EXPECT_TRUE(waitThread4
.timed_join(10000ms
));