From dc8c21a9e9d7fb174f822778734556d1f37e6ae0 Mon Sep 17 00:00:00 2001 From: Christopher Dykes Date: Mon, 9 May 2016 17:23:41 -0700 Subject: [PATCH] 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 --- folly/Preprocessor.h | 11 +++++++++ folly/Synchronized.h | 57 +++++++++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/folly/Preprocessor.h b/folly/Preprocessor.h index 393016bd..800608d4 100644 --- a/folly/Preprocessor.h +++ b/folly/Preprocessor.h @@ -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 diff --git a/folly/Synchronized.h b/folly/Synchronized.h index 5ea2ad54..4b6a25b8 100644 --- a/folly/Synchronized.h +++ b/folly/Synchronized.h @@ -680,40 +680,49 @@ void swap(Synchronized& lhs, Synchronized& rhs) { * Refer to folly/docs/Synchronized.md for a detailed explanation and more * examples. */ -#define SYNCHRONIZED(...) \ - FOLLY_PUSH_WARNING \ - FOLLY_GCC_DISABLE_WARNING(shadow) \ - 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 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_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 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. -- 2.34.1