2 * Copyright 2016 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include <folly/LockTraits.h>
17 #include <folly/LockTraitsBoost.h>
19 #include <gtest/gtest.h>
22 #include <folly/RWSpinLock.h>
23 #include <folly/SharedMutex.h>
24 #include <folly/SpinLock.h>
26 using namespace folly;
28 TEST(LockTraits, std_mutex) {
29 using traits = LockTraits<std::mutex>;
30 static_assert(!traits::is_timed, "std:mutex is not a timed lock");
31 static_assert(!traits::is_shared, "std:mutex is not a shared lock");
35 traits::unlock(mutex);
37 lock_shared_or_unique(mutex);
38 unlock_shared_or_unique(mutex);
41 TEST(LockTraits, SharedMutex) {
42 using traits = LockTraits<SharedMutex>;
43 static_assert(traits::is_timed, "SharedMutex is a timed lock");
44 static_assert(traits::is_shared, "SharedMutex is a shared lock");
48 traits::unlock(mutex);
50 traits::lock_shared(mutex);
51 traits::lock_shared(mutex);
52 traits::unlock_shared(mutex);
53 traits::unlock_shared(mutex);
55 lock_shared_or_unique(mutex);
56 lock_shared_or_unique(mutex);
57 unlock_shared_or_unique(mutex);
58 unlock_shared_or_unique(mutex);
61 TEST(LockTraits, SpinLock) {
62 using traits = LockTraits<SpinLock>;
63 static_assert(!traits::is_timed, "folly::SpinLock is not a timed lock");
64 static_assert(!traits::is_shared, "folly::SpinLock is not a shared lock");
68 traits::unlock(mutex);
70 lock_shared_or_unique(mutex);
71 unlock_shared_or_unique(mutex);
74 TEST(LockTraits, RWSpinLock) {
75 using traits = LockTraits<RWSpinLock>;
76 static_assert(!traits::is_timed, "folly::RWSpinLock is not a timed lock");
77 static_assert(traits::is_shared, "folly::RWSpinLock is a shared lock");
81 traits::unlock(mutex);
83 traits::lock_shared(mutex);
84 traits::lock_shared(mutex);
85 traits::unlock_shared(mutex);
86 traits::unlock_shared(mutex);
88 lock_shared_or_unique(mutex);
89 lock_shared_or_unique(mutex);
90 unlock_shared_or_unique(mutex);
91 unlock_shared_or_unique(mutex);
94 TEST(LockTraits, boost_mutex) {
95 using traits = LockTraits<boost::mutex>;
96 static_assert(!traits::is_timed, "boost::mutex is not a timed lock");
97 static_assert(!traits::is_shared, "boost::mutex is not a shared lock");
101 traits::unlock(mutex);
103 lock_shared_or_unique(mutex);
104 unlock_shared_or_unique(mutex);
107 TEST(LockTraits, boost_recursive_mutex) {
108 using traits = LockTraits<boost::recursive_mutex>;
110 !traits::is_timed, "boost::recursive_mutex is not a timed lock");
112 !traits::is_shared, "boost::recursive_mutex is not a shared lock");
114 boost::recursive_mutex mutex;
117 traits::unlock(mutex);
118 traits::unlock(mutex);
120 lock_shared_or_unique(mutex);
121 lock_shared_or_unique(mutex);
122 unlock_shared_or_unique(mutex);
123 unlock_shared_or_unique(mutex);
126 #if FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES
127 TEST(LockTraits, timed_mutex) {
128 using traits = LockTraits<std::timed_mutex>;
129 static_assert(traits::is_timed, "std::timed_mutex is a timed lock");
130 static_assert(!traits::is_shared, "std::timed_mutex is not a shared lock");
132 std::timed_mutex mutex;
134 bool gotLock = traits::try_lock_for(mutex, std::chrono::milliseconds(1));
135 EXPECT_FALSE(gotLock) << "should not have been able to acquire the "
136 << "timed_mutex a second time";
137 traits::unlock(mutex);
139 lock_shared_or_unique(mutex);
140 gotLock = try_lock_shared_or_unique_for(mutex, std::chrono::milliseconds(1));
141 EXPECT_FALSE(gotLock) << "should not have been able to acquire the "
142 << "timed_mutex a second time";
143 unlock_shared_or_unique(mutex);
146 TEST(LockTraits, recursive_timed_mutex) {
147 using traits = LockTraits<std::recursive_timed_mutex>;
148 static_assert(traits::is_timed, "std::recursive_timed_mutex is a timed lock");
150 !traits::is_shared, "std::recursive_timed_mutex is not a shared lock");
152 std::recursive_timed_mutex mutex;
154 auto gotLock = traits::try_lock_for(mutex, std::chrono::milliseconds(10));
155 EXPECT_TRUE(gotLock) << "should have been able to acquire the "
156 << "recursive_timed_mutex a second time";
157 traits::unlock(mutex);
158 traits::unlock(mutex);
160 lock_shared_or_unique(mutex);
161 gotLock = try_lock_shared_or_unique_for(mutex, std::chrono::milliseconds(10));
162 EXPECT_TRUE(gotLock) << "should have been able to acquire the "
163 << "recursive_timed_mutex a second time";
164 unlock_shared_or_unique(mutex);
165 unlock_shared_or_unique(mutex);
168 TEST(LockTraits, boost_shared_mutex) {
169 using traits = LockTraits<boost::shared_mutex>;
170 static_assert(traits::is_timed, "boost::shared_mutex is a timed lock");
171 static_assert(traits::is_shared, "boost::shared_mutex is a shared lock");
173 boost::shared_mutex mutex;
175 auto gotLock = traits::try_lock_for(mutex, std::chrono::milliseconds(1));
176 EXPECT_FALSE(gotLock) << "should not have been able to acquire the "
177 << "shared_mutex a second time";
178 gotLock = traits::try_lock_shared_for(mutex, std::chrono::milliseconds(1));
179 EXPECT_FALSE(gotLock) << "should not have been able to acquire the "
180 << "shared_mutex a second time";
181 traits::unlock(mutex);
183 traits::lock_shared(mutex);
184 gotLock = traits::try_lock_for(mutex, std::chrono::milliseconds(1));
185 EXPECT_FALSE(gotLock) << "should not have been able to acquire the "
186 << "shared_mutex a second time";
187 gotLock = traits::try_lock_shared_for(mutex, std::chrono::milliseconds(10));
188 EXPECT_TRUE(gotLock) << "should have been able to acquire the "
189 << "shared_mutex a second time in shared mode";
190 traits::unlock_shared(mutex);
191 traits::unlock_shared(mutex);
193 lock_shared_or_unique(mutex);
194 gotLock = traits::try_lock_for(mutex, std::chrono::milliseconds(1));
195 EXPECT_FALSE(gotLock) << "should not have been able to acquire the "
196 << "shared_mutex a second time";
197 gotLock = try_lock_shared_or_unique_for(mutex, std::chrono::milliseconds(10));
198 EXPECT_TRUE(gotLock) << "should have been able to acquire the "
199 << "shared_mutex a second time in shared mode";
200 unlock_shared_or_unique(mutex);
201 unlock_shared_or_unique(mutex);
203 #endif // FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES