proxygen
LockTraits.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
25 #pragma once
26 
27 #include <chrono>
28 #include <type_traits>
29 
31 
32 // Android, OSX, and Cygwin don't have timed mutexes
33 #if defined(ANDROID) || defined(__ANDROID__) || defined(__APPLE__) || \
34  defined(__CYGWIN__)
35 #define FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES 0
36 #else
37 #define FOLLY_LOCK_TRAITS_HAVE_TIMED_MUTEXES 1
38 #endif
39 
40 namespace folly {
41 namespace detail {
42 
43 namespace member {
45 FOLLY_CREATE_MEMBER_INVOKE_TRAITS(try_lock_for, try_lock_for);
46 FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock_shared, lock_shared);
47 FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock_upgrade, lock_upgrade);
48 } // namespace member
49 
57 enum class MutexLevel { UNIQUE, SHARED, UPGRADE };
58 
63 template <bool is_unique, bool is_shared, bool is_upgrade>
65 template <>
66 struct MutexLevelValueImpl<true, false, false> {
67  static constexpr MutexLevel value = MutexLevel::UNIQUE;
68 };
69 template <>
70 struct MutexLevelValueImpl<true, true, false> {
71  static constexpr MutexLevel value = MutexLevel::SHARED;
72 };
73 template <>
74 struct MutexLevelValueImpl<true, true, true> {
75  static constexpr MutexLevel value = MutexLevel::UPGRADE;
76 };
77 
84 template <class Mutex>
86  private:
87  // assert that the mutex type has basic lock and unlock functions
88  static_assert(
90  "The mutex type must support lock and unlock functions");
91 
92  using duration = std::chrono::milliseconds;
93 
94  public:
95  static constexpr bool has_lock_unique = true;
96  static constexpr bool has_lock_timed =
98  static constexpr bool has_lock_shared =
100  static constexpr bool has_lock_upgrade =
102 };
103 
111 template <class Mutex, MutexLevel level, bool is_timed>
113 
114 template <class Mutex>
116  static constexpr bool is_timed{false};
117  static constexpr bool is_shared{false};
118  static constexpr bool is_upgrade{false};
119 
123  static void lock(Mutex& mutex) {
124  mutex.lock();
125  }
126 
130  static void unlock(Mutex& mutex) {
131  mutex.unlock();
132  }
133 
137  static bool try_lock(Mutex& mutex) {
138  return mutex.try_lock();
139  }
140 };
141 
146 template <class Mutex>
148  : public LockTraitsImpl<Mutex, MutexLevel::UNIQUE, false> {
149  static constexpr bool is_timed{false};
150  static constexpr bool is_shared{true};
151  static constexpr bool is_upgrade{false};
152 
156  static void lock_shared(Mutex& mutex) {
157  mutex.lock_shared();
158  }
159 
163  static void unlock_shared(Mutex& mutex) {
164  mutex.unlock_shared();
165  }
166 
170  static bool try_lock_shared(Mutex& mutex) {
171  return mutex.try_lock_shared();
172  }
173 };
174 
203 template <class Mutex>
204 struct LockTraitsImpl<Mutex, MutexLevel::UPGRADE, false>
205  : public LockTraitsImpl<Mutex, MutexLevel::SHARED, false> {
206  static constexpr bool is_timed{false};
207  static constexpr bool is_shared{true};
208  static constexpr bool is_upgrade{true};
209 
213  static void lock_upgrade(Mutex& mutex) {
214  mutex.lock_upgrade();
215  }
216 
220  static void unlock_upgrade(Mutex& mutex) {
221  mutex.unlock_upgrade();
222  }
223 
227  static bool try_lock_upgrade(Mutex& mutex) {
228  return mutex.try_lock_upgrade();
229  }
230 
235  mutex.unlock_upgrade_and_lock();
236  }
237 
242  mutex.unlock_and_lock_upgrade();
243  }
244 
249  mutex.unlock_and_lock_shared();
250  }
251 
256  mutex.unlock_upgrade_and_lock_shared();
257  }
258 };
259 
260 template <class Mutex>
262  : public LockTraitsImpl<Mutex, MutexLevel::UNIQUE, false> {
263  static constexpr bool is_timed{true};
264  static constexpr bool is_shared{false};
265  static constexpr bool is_upgrade{false};
266 
272  template <class Rep, class Period>
273  static bool try_lock_for(
274  Mutex& mutex,
275  const std::chrono::duration<Rep, Period>& timeout) {
276  return mutex.try_lock_for(timeout);
277  }
278 };
279 
285 template <class Mutex>
287  : public LockTraitsImpl<Mutex, MutexLevel::SHARED, false>,
288  public LockTraitsImpl<Mutex, MutexLevel::UNIQUE, true> {
289  static constexpr bool is_timed{true};
290  static constexpr bool is_shared{true};
291  static constexpr bool is_upgrade{false};
292 
298  template <class Rep, class Period>
299  static bool try_lock_for(
300  Mutex& mutex,
301  const std::chrono::duration<Rep, Period>& timeout) {
302  return mutex.try_lock_for(timeout);
303  }
304 
310  template <class Rep, class Period>
311  static bool try_lock_shared_for(
312  Mutex& mutex,
313  const std::chrono::duration<Rep, Period>& timeout) {
314  return mutex.try_lock_shared_for(timeout);
315  }
316 };
317 
318 template <class Mutex>
319 struct LockTraitsImpl<Mutex, MutexLevel::UPGRADE, true>
320  : public LockTraitsImpl<Mutex, MutexLevel::UPGRADE, false>,
321  public LockTraitsImpl<Mutex, MutexLevel::SHARED, true> {
322  static constexpr bool is_timed{true};
323  static constexpr bool is_shared{true};
324  static constexpr bool is_upgrade{true};
325 
331  template <class Rep, class Period>
332  static bool try_lock_upgrade_for(
333  Mutex& mutex,
334  const std::chrono::duration<Rep, Period>& timeout) {
335  return mutex.try_lock_upgrade_for(timeout);
336  }
337 
343  template <class Rep, class Period>
345  Mutex& mutex,
346  const std::chrono::duration<Rep, Period>& timeout) {
347  return mutex.try_unlock_upgrade_and_lock_for(timeout);
348  }
349 };
350 
371 template <template <typename...> class LockTraits>
373  template <typename Mutex>
374  static void unlock(Mutex& mutex) {
376  }
377 };
378 template <template <typename...> class LockTraits>
380  template <typename Mutex>
381  static void unlock(Mutex& mutex) {
383  }
384 };
385 template <template <typename...> class LockTraits>
387  template <typename Mutex>
388  static void unlock(Mutex& mutex) {
390  }
391 };
392 
393 } // namespace detail
394 
446 template <class Mutex>
448  : public detail::LockTraitsImpl<
449  Mutex,
450  detail::MutexLevelValueImpl<
451  detail::LockInterfaceDispatcher<Mutex>::has_lock_unique,
452  detail::LockInterfaceDispatcher<Mutex>::has_lock_shared,
453  detail::LockInterfaceDispatcher<Mutex>::has_lock_upgrade>::value,
454  detail::LockInterfaceDispatcher<Mutex>::has_lock_timed> {};
455 
456 template <class Mutex>
457 struct LockTraits : public LockTraitsBase<Mutex> {};
458 
459 /*
460  * Lock policy classes.
461  *
462  * These can be used as template parameters to provide compile-time
463  * selection over the type of lock operation to perform.
464  */
470 
471  template <class Mutex>
474  return std::true_type{};
475  }
476  template <class Mutex, class Rep, class Period>
477  static bool try_lock_for(
478  Mutex& mutex,
479  const std::chrono::duration<Rep, Period>& timeout) {
480  return LockTraits<Mutex>::try_lock_for(mutex, timeout);
481  }
482 };
483 
490 
491  template <class Mutex>
494  return std::true_type{};
495  }
496  template <class Mutex, class Rep, class Period>
497  static bool try_lock_for(
498  Mutex& mutex,
499  const std::chrono::duration<Rep, Period>& timeout) {
500  return LockTraits<Mutex>::try_lock_shared_for(mutex, timeout);
501  }
502 };
503 
513 
514  template <class Mutex>
517  return std::true_type{};
518  }
519  template <class Mutex, class Rep, class Period>
520  static bool try_lock_for(
521  Mutex& mutex,
522  const std::chrono::duration<Rep, Period>& timeout) {
523  return LockTraits<Mutex>::try_lock_upgrade_for(mutex, timeout);
524  }
525 };
526 
527 /*****************************************************************************
528  * Policies for optional mutex locking
529  ****************************************************************************/
536 
537  template <class Mutex>
538  static bool lock(Mutex& mutex) {
539  return LockTraits<Mutex>::try_lock(mutex);
540  }
541 };
542 
549 
550  template <class Mutex>
551  static bool lock(Mutex& mutex) {
553  }
554 };
555 
562 
563  template <class Mutex>
564  static bool lock(Mutex& mutex) {
566  }
567 };
568 
569 /*****************************************************************************
570  * Policies for all the transitions from possible mutex levels
571  ****************************************************************************/
580  template <class Mutex>
583  return std::true_type{};
584  }
585  template <class Mutex, class Rep, class Period>
586  static bool try_lock_for(
587  Mutex& mutex,
588  const std::chrono::duration<Rep, Period>& timeout) {
590  }
591 };
592 
601  template <class Mutex>
604  return std::true_type{};
605  }
606  template <class Mutex, class Rep, class Period>
607  static bool try_lock_for(
608  Mutex& mutex,
609  const std::chrono::duration<Rep, Period>&) {
611 
612  // downgrade should be non blocking and should succeed
613  return true;
614  }
615 };
616 
625  template <class Mutex>
628  return std::true_type{};
629  }
630  template <class Mutex, class Rep, class Period>
631  static bool try_lock_for(
632  Mutex& mutex,
633  const std::chrono::duration<Rep, Period>&) {
635 
636  // downgrade should be non blocking and should succeed
637  return true;
638  }
639 };
640 
649  template <class Mutex>
652  return std::true_type{};
653  }
654  template <class Mutex, class Rep, class Period>
655  static bool try_lock_for(
656  Mutex& mutex,
657  const std::chrono::duration<Rep, Period>&) {
659 
660  // downgrade should be non blocking and should succeed
661  return true;
662  }
663 };
664 
665 } // namespace folly
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:472
static bool lock(Mutex &mutex)
Definition: LockTraits.h:551
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:520
static void unlock(Mutex &mutex)
Definition: LockTraits.h:381
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:626
static bool try_lock_shared_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:311
static bool try_unlock_upgrade_and_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:344
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:586
static void unlock(Mutex &mutex)
Definition: LockTraits.h:388
#define Mutex
static void unlock(Mutex &mutex)
Definition: LockTraits.h:374
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
std::chrono::milliseconds duration
Definition: LockTraits.h:92
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &)
Definition: LockTraits.h:655
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:602
bool_constant< true > true_type
Definition: gtest-port.h:2210
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &)
Definition: LockTraits.h:607
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:515
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock, lock)
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &)
Definition: LockTraits.h:631
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:581
auto lock(SynchronizedLocker...lockersIn) -> std::tuple< typename SynchronizedLocker::LockedPtr... >
Definition: Synchronized.h:871
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:497
#define UPGRADE
Definition: http_parser.c:144
static const char *const value
Definition: Conv.cpp:50
static bool lock(Mutex &mutex)
Definition: LockTraits.h:538
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:477
std::enable_if< ExprIsConst< Constness >::value, Map >::type member(Return(Class::*member)() const)
Definition: Base.h:605
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:492
std::mutex mutex
static bool lock(Mutex &mutex)
Definition: LockTraits.h:564
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:299
static bool try_lock_upgrade_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:332
static std::true_type lock(Mutex &mutex)
Definition: LockTraits.h:650
static bool try_lock_for(Mutex &mutex, const std::chrono::duration< Rep, Period > &timeout)
Definition: LockTraits.h:273