Commit dc8c21a9 authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot 9

Deal with some oddities of MSVC's preprocessor

Summary: MSVC's preprocessor is different in how it deals with passing arguments expanded from `__VA_ARGS__`, so we have to add a stub to force it to expand the arguments.

Reviewed By: yfeldblum

Differential Revision: D3256328

fbshipit-source-id: 551434833d40e55498a9ab352eb74acdfd094835
parent d65a097e
......@@ -46,6 +46,10 @@
#define FB_THIRD(a, b, ...) __VA_ARGS__
#endif
// MSVC's preprocessor is a pain, so we have to
// forcefully expand the VA args in some places.
#define FB_VA_GLUE(a, b) a b
/**
* Helper macro that extracts the first argument out of a list of any
* number of arguments.
......@@ -57,7 +61,14 @@
* number of arguments. If only one argument is given, it returns
* that.
*/
#ifdef _MSC_VER
// GCC refuses to expand this correctly if this macro itself was
// called with FB_VA_GLUE :(
#define FB_ARG_2_OR_1(...) \
FB_VA_GLUE(FB_ARG_2_OR_1_IMPL, (__VA_ARGS__, __VA_ARGS__))
#else
#define FB_ARG_2_OR_1(...) FB_ARG_2_OR_1_IMPL(__VA_ARGS__, __VA_ARGS__)
#endif
// Support macro for the above
#define FB_ARG_2_OR_1_IMPL(a, b, ...) b
......
......@@ -683,37 +683,46 @@ void swap(Synchronized<T, M>& lhs, Synchronized<T, M>& rhs) {
#define SYNCHRONIZED(...) \
FOLLY_PUSH_WARNING \
FOLLY_GCC_DISABLE_WARNING(shadow) \
if (bool SYNCHRONIZED_state = false) {} else \
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__) = \
(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) \
!SYNCHRONIZED_state; \
SYNCHRONIZED_state = true) \
FOLLY_POP_WARNING
#define TIMED_SYNCHRONIZED(timeout, ...) \
if (bool SYNCHRONIZED_state = false) {} else \
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__) = \
(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)
!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())
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())
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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment