folly: fix clang's -Wundefined-var-template
[folly.git] / folly / Synchronized.h
index 312d33743fa6a37b12b3e1d8da750de92b6927d6..4b6a25b80cb71ebc5d9c2b66c38342eacd5e82c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * @author: Andrei Alexandrescu (andrei.alexandrescu@fb.com)
  */
 
-#ifndef SYNCHRONIZED_H_
-#define SYNCHRONIZED_H_
+#pragma once
 
 #include <type_traits>
 #include <mutex>
 #include <boost/thread.hpp>
 #include <folly/Preprocessor.h>
+#include <folly/SharedMutex.h>
 #include <folly/Traits.h>
 
 namespace folly {
@@ -224,7 +224,7 @@ releaseReadWrite(T& mutex) {
  * refer to the namespace detail below, which implements the
  * primitives for mutexes in std and boost.
  */
-template <class T, class Mutex = boost::shared_mutex>
+template <class T, class Mutex = SharedMutex>
 struct Synchronized {
   /**
    * Default constructor leaves both members call their own default
@@ -282,6 +282,14 @@ struct Synchronized {
   explicit Synchronized(T&& rhs) noexcept(nxMoveCtor)
       : datum_(std::move(rhs)) {}
 
+  /**
+   * Lets you construct non-movable types in-place. Use the constexpr
+   * instance `construct_in_place` as the first argument.
+   */
+  template <typename... Args>
+  explicit Synchronized(construct_in_place_t, Args&&... args)
+      : datum_(std::forward<Args>(args)...) {}
+
   /**
    * The canonical assignment operator only assigns the data, NOT the
    * mutex. It locks the two objects in ascending order of their
@@ -672,37 +680,49 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) {
  * Refer to folly/docs/Synchronized.md for a detailed explanation and more
  * examples.
  */
-#define SYNCHRONIZED(...)                                       \
-  if (bool SYNCHRONIZED_state = false) {} else                  \
-    for (auto SYNCHRONIZED_lockedPtr =                          \
-           (FB_ARG_2_OR_1(__VA_ARGS__)).operator->();           \
-         !SYNCHRONIZED_state; SYNCHRONIZED_state = true)        \
-      for (auto& FB_ARG_1(__VA_ARGS__) =                        \
-             *SYNCHRONIZED_lockedPtr.operator->();              \
-           !SYNCHRONIZED_state; SYNCHRONIZED_state = true)
-
-#define TIMED_SYNCHRONIZED(timeout, ...)                           \
-  if (bool SYNCHRONIZED_state = false) {} else                     \
-    for (auto SYNCHRONIZED_lockedPtr =                             \
-           (FB_ARG_2_OR_1(__VA_ARGS__)).timedAcquire(timeout);     \
-         !SYNCHRONIZED_state; SYNCHRONIZED_state = true)           \
-      for (auto FB_ARG_1(__VA_ARGS__) =                            \
-             SYNCHRONIZED_lockedPtr.operator->();                  \
-           !SYNCHRONIZED_state; SYNCHRONIZED_state = true)
+#define SYNCHRONIZED(...)                                             \
+  FOLLY_PUSH_WARNING                                                  \
+  FOLLY_GCC_DISABLE_WARNING(shadow)                                   \
+  if (bool SYNCHRONIZED_state = false) {                              \
+  } else                                                              \
+    for (auto SYNCHRONIZED_lockedPtr =                                \
+             (FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).operator->(); \
+         !SYNCHRONIZED_state;                                         \
+         SYNCHRONIZED_state = true)                                   \
+      for (auto& FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)) =                \
+               *SYNCHRONIZED_lockedPtr.operator->();                  \
+           !SYNCHRONIZED_state;                                       \
+           SYNCHRONIZED_state = true)                                 \
+  FOLLY_POP_WARNING
+
+#define TIMED_SYNCHRONIZED(timeout, ...)                                       \
+  if (bool SYNCHRONIZED_state = false) {                                       \
+  } else                                                                       \
+    for (auto SYNCHRONIZED_lockedPtr =                                         \
+             (FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).timedAcquire(timeout); \
+         !SYNCHRONIZED_state;                                                  \
+         SYNCHRONIZED_state = true)                                            \
+      for (auto FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)) =                          \
+               SYNCHRONIZED_lockedPtr.operator->();                            \
+           !SYNCHRONIZED_state;                                                \
+           SYNCHRONIZED_state = true)
 
 /**
  * Similar to SYNCHRONIZED, but only uses a read lock.
  */
-#define SYNCHRONIZED_CONST(...)                         \
-  SYNCHRONIZED(FB_ARG_1(__VA_ARGS__),                   \
-               (FB_ARG_2_OR_1(__VA_ARGS__)).asConst())
+#define SYNCHRONIZED_CONST(...)            \
+  SYNCHRONIZED(                            \
+      FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)), \
+      (FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).asConst())
 
 /**
  * Similar to TIMED_SYNCHRONIZED, but only uses a read lock.
  */
-#define TIMED_SYNCHRONIZED_CONST(timeout, ...)                  \
-  TIMED_SYNCHRONIZED(timeout, FB_ARG_1(__VA_ARGS__),            \
-                     (FB_ARG_2_OR_1(__VA_ARGS__)).asConst())
+#define TIMED_SYNCHRONIZED_CONST(timeout, ...) \
+  TIMED_SYNCHRONIZED(                          \
+      timeout,                                 \
+      FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)),     \
+      (FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).asConst())
 
 /**
  * Temporarily disables synchronization inside a SYNCHRONIZED block.
@@ -711,7 +731,7 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) {
   for (decltype(SYNCHRONIZED_lockedPtr.typeHackDoNotUse())      \
          SYNCHRONIZED_state3(&SYNCHRONIZED_lockedPtr);          \
        !SYNCHRONIZED_state; SYNCHRONIZED_state = true)          \
-    for (auto name = *SYNCHRONIZED_state3.operator->();         \
+    for (auto& name = *SYNCHRONIZED_state3.operator->();        \
          !SYNCHRONIZED_state; SYNCHRONIZED_state = true)
 
 /**
@@ -750,5 +770,3 @@ void lockInOrder(P1& p1, P2& p2) {
             else
 
 } /* namespace folly */
-
-#endif // SYNCHRONIZED_H_