/*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2011-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* Lets you construct non-movable types in-place. Use the constexpr
- * instance `construct_in_place` as the first argument.
+ * instance `in_place` as the first argument.
*/
template <typename... Args>
- explicit Synchronized(construct_in_place_t, Args&&... args)
+ explicit Synchronized(in_place_t, Args&&... args)
: datum_(std::forward<Args>(args)...) {}
/**
/**
* Attempts to acquire for a given number of milliseconds. If
- * acquisition is unsuccessful, the returned LockedPtr is NULL.
+ * acquisition is unsuccessful, the returned LockedPtr is nullptr.
*
* NOTE: This API is deprecated. Use lock(), wlock(), or rlock() instead.
* In the future it will be marked with a deprecation attribute to emit
/**
* Attempts to acquire for a given number of milliseconds. If
- * acquisition is unsuccessful, the returned ConstLockedPtr is NULL.
+ * acquisition is unsuccessful, the returned ConstLockedPtr is nullptr.
*
* NOTE: This API is deprecated. Use lock(), wlock(), or rlock() instead.
* In the future it will be marked with a deprecation attribute to emit
swap(datum_, rhs);
}
+ /**
+ * Assign another datum and return the original value. Recommended
+ * because it keeps the mutex held only briefly.
+ */
+ T exchange(T&& rhs) {
+ swap(rhs);
+ return std::move(rhs);
+ }
+
/**
* Copies datum to a given target.
*/
std::is_const<SynchronizedType>::value,
typename SynchronizedType::ConstLockedPtr,
typename SynchronizedType::LockedPtr>::type;
-} // detail
+} // namespace detail
/**
* A helper base class for implementing LockedPtr.
lhs.swap(rhs);
}
+/**
+ * Disambiguate the name var by concatenating the line number of the original
+ * point of expansion. This avoids shadowing warnings for nested
+ * SYNCHRONIZEDs. The name is consistent if used multiple times within
+ * another macro.
+ * Only for internal use.
+ */
+#define SYNCHRONIZED_VAR(var) FB_CONCATENATE(SYNCHRONIZED_##var##_, __LINE__)
+
/**
* SYNCHRONIZED is the main facility that makes Synchronized<T>
* helpful. It is a pseudo-statement that introduces a scope where the
*/
#define SYNCHRONIZED(...) \
FOLLY_PUSH_WARNING \
- FOLLY_GCC_DISABLE_WARNING(shadow) \
+ FOLLY_GCC_DISABLE_WARNING("-Wshadow") \
FOLLY_MSVC_DISABLE_WARNING(4189) /* initialized but unreferenced */ \
FOLLY_MSVC_DISABLE_WARNING(4456) /* declaration hides local */ \
FOLLY_MSVC_DISABLE_WARNING(4457) /* declaration hides parameter */ \
FOLLY_MSVC_DISABLE_WARNING(4458) /* declaration hides member */ \
FOLLY_MSVC_DISABLE_WARNING(4459) /* declaration hides global */ \
FOLLY_GCC_DISABLE_NEW_SHADOW_WARNINGS \
- if (bool SYNCHRONIZED_state = false) { \
+ if (bool SYNCHRONIZED_VAR(state) = false) { \
} else \
- for (auto SYNCHRONIZED_lockedPtr = \
+ for (auto SYNCHRONIZED_VAR(lockedPtr) = \
(FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).operator->(); \
- !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true) \
+ !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true) \
for (auto& FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)) = \
- *SYNCHRONIZED_lockedPtr.operator->(); \
- !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true) \
+ *SYNCHRONIZED_VAR(lockedPtr).operator->(); \
+ !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true) \
FOLLY_POP_WARNING
#define TIMED_SYNCHRONIZED(timeout, ...) \
- if (bool SYNCHRONIZED_state = false) { \
+ if (bool SYNCHRONIZED_VAR(state) = false) { \
} else \
- for (auto SYNCHRONIZED_lockedPtr = \
+ for (auto SYNCHRONIZED_VAR(lockedPtr) = \
(FB_VA_GLUE(FB_ARG_2_OR_1, (__VA_ARGS__))).timedAcquire(timeout); \
- !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true) \
+ !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true) \
for (auto FB_VA_GLUE(FB_ARG_1, (__VA_ARGS__)) = \
- (!SYNCHRONIZED_lockedPtr \
+ (!SYNCHRONIZED_VAR(lockedPtr) \
? nullptr \
- : SYNCHRONIZED_lockedPtr.operator->()); \
- !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true)
+ : SYNCHRONIZED_VAR(lockedPtr).operator->()); \
+ !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true)
/**
* Similar to SYNCHRONIZED, but only uses a read lock.
* different data). Synchronization is done in increasing address of
* object order, so there is no deadlock risk.
*/
-#define SYNCHRONIZED_DUAL(n1, e1, n2, e2) \
- if (bool SYNCHRONIZED_state = false) { \
- } else \
- for (auto SYNCHRONIZED_ptrs = acquireLockedPair(e1, e2); \
- !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true) \
- for (auto& n1 = *SYNCHRONIZED_ptrs.first; !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true) \
- for (auto& n2 = *SYNCHRONIZED_ptrs.second; !SYNCHRONIZED_state; \
- SYNCHRONIZED_state = true)
+#define SYNCHRONIZED_DUAL(n1, e1, n2, e2) \
+ if (bool SYNCHRONIZED_VAR(state) = false) { \
+ } else \
+ for (auto SYNCHRONIZED_VAR(ptrs) = acquireLockedPair(e1, e2); \
+ !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true) \
+ for (auto& n1 = *SYNCHRONIZED_VAR(ptrs).first; !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true) \
+ for (auto& n2 = *SYNCHRONIZED_VAR(ptrs).second; \
+ !SYNCHRONIZED_VAR(state); \
+ SYNCHRONIZED_VAR(state) = true)
} /* namespace folly */