diff options
Diffstat (limited to 'absl/base')
-rw-r--r-- | absl/base/config.h | 24 | ||||
-rw-r--r-- | absl/base/exception_safety_testing_test.cc | 4 | ||||
-rw-r--r-- | absl/base/internal/exception_safety_testing.h | 19 | ||||
-rw-r--r-- | absl/base/thread_annotations.h | 31 |
4 files changed, 54 insertions, 24 deletions
diff --git a/absl/base/config.h b/absl/base/config.h index 500bc8c8..3eb24abf 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -382,6 +382,19 @@ #endif #endif +// ABSL_HAVE_STD_VARIANT +// +// Checks whether C++17 std::optional is available. +#ifdef ABSL_HAVE_STD_VARIANT +#error "ABSL_HAVE_STD_VARIANT cannot be directly set." +#endif + +#ifdef __has_include +#if __has_include(<variant>) && __cplusplus >= 201703L +#define ABSL_HAVE_STD_VARIANT 1 +#endif +#endif + // ABSL_HAVE_STD_STRING_VIEW // // Checks whether C++17 std::string_view is available. @@ -396,17 +409,18 @@ #endif // For MSVC, `__has_include` is supported in VS 2017 15.3, which is later than -// the support for <optional>, <any>, <string_view>. So we use _MSC_VER to check -// whether we have VS 2017 RTM (when <optional>, <any>, <string_view> is -// implemented) or higher. -// Also, `__cplusplus` is not correctly set by MSVC, so we use `_MSVC_LANG` to -// check the language version. +// the support for <optional>, <any>, <string_view>, <variant>. So we use +// _MSC_VER to check whether we have VS 2017 RTM (when <optional>, <any>, +// <string_view>, <variant> is implemented) or higher. Also, `__cplusplus` is +// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language +// version. // TODO(zhangxy): fix tests before enabling aliasing for `std::any`, // `std::string_view`. #if defined(_MSC_VER) && _MSC_VER >= 1910 && \ ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402) // #define ABSL_HAVE_STD_ANY 1 #define ABSL_HAVE_STD_OPTIONAL 1 +#define ABSL_HAVE_STD_VARIANT 1 // #define ABSL_HAVE_STD_STRING_VIEW 1 #endif diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc index 041d780f..94a7e4f7 100644 --- a/absl/base/exception_safety_testing_test.cc +++ b/absl/base/exception_safety_testing_test.cc @@ -27,7 +27,9 @@ namespace absl { namespace { +using ::absl::exceptions_internal::SetCountdown; using ::absl::exceptions_internal::TestException; +using ::absl::exceptions_internal::UnsetCountdown; // EXPECT_NO_THROW can't inspect the thrown inspection in general. template <typename F> @@ -54,7 +56,7 @@ TEST_F(ThrowingValueTest, Throws) { // It's not guaranteed that every operator only throws *once*. The default // ctor only throws once, though, so use it to make sure we only throw when // the countdown hits 0 - exceptions_internal::countdown = 2; + SetCountdown(2); ExpectNoThrow([]() { ThrowingValue<> bomb; }); ExpectNoThrow([]() { ThrowingValue<> bomb; }); EXPECT_THROW(ThrowingValue<> bomb, TestException); diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h index 3493b5e2..48a292b3 100644 --- a/absl/base/internal/exception_safety_testing.h +++ b/absl/base/internal/exception_safety_testing.h @@ -94,6 +94,12 @@ class TestBadAllocException : public std::bad_alloc, public TestException { extern int countdown; +// Allows the countdown variable to be set manually (defaulting to the initial +// value of 0) +inline void SetCountdown(int i = 0) { countdown = i; } +// Sets the countdown to the terminal value -1 +inline void UnsetCountdown() { SetCountdown(-1); } + void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false); testing::AssertionResult FailureMessage(const TestException& e, @@ -134,7 +140,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl( const Invariant& invariant) { auto t_ptr = factory(); absl::optional<testing::AssertionResult> current_res; - exceptions_internal::countdown = count; + SetCountdown(count); try { operation(t_ptr.get()); } catch (const exceptions_internal::TestException& e) { @@ -143,7 +149,7 @@ absl::optional<testing::AssertionResult> TestSingleInvariantAtCountdownImpl( *current_res << e.what() << " failed invariant check"; } } - exceptions_internal::countdown = -1; + UnsetCountdown(); return current_res; } @@ -196,11 +202,6 @@ inline absl::optional<testing::AssertionResult> TestAllInvariantsAtCountdown( extern exceptions_internal::NoThrowTag no_throw_ctor; extern exceptions_internal::StrongGuaranteeTagType strong_guarantee; -// These are useful for tests which just construct objects and make sure there -// are no leaks. -inline void SetCountdown() { exceptions_internal::countdown = 0; } -inline void UnsetCountdown() { exceptions_internal::countdown = -1; } - // A test class which is convertible to bool. The conversion can be // instrumented to throw at a controlled time. class ThrowingBool { @@ -731,10 +732,10 @@ struct ConstructorTracker { template <typename T, typename... Args> T TestThrowingCtor(Args&&... args) { struct Cleanup { - ~Cleanup() { UnsetCountdown(); } + ~Cleanup() { exceptions_internal::UnsetCountdown(); } } c; for (int count = 0;; ++count) { - exceptions_internal::countdown = count; + exceptions_internal::SetCountdown(count); try { return T(std::forward<Args>(args)...); } catch (const exceptions_internal::TestException&) { diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index 0da3badc..8d30b932 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -47,10 +47,17 @@ // mutex. GUARDED_BY() allows the user to specify a particular mutex that // should be held when accessing the annotated variable. // +// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to +// local variables, a local variable and its associated mutex can often be +// combined into a small class or struct, thereby allowing the annotation. +// // Example: // -// Mutex mu; -// int p1 GUARDED_BY(mu); +// class Foo { +// Mutex mu_; +// int p1_ GUARDED_BY(mu_); +// ... +// }; #define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) // PT_GUARDED_BY() @@ -59,17 +66,20 @@ // by a mutex when dereferencing the pointer. // // Example: -// Mutex mu; -// int *p1 PT_GUARDED_BY(mu); +// class Foo { +// Mutex mu_; +// int *p1_ PT_GUARDED_BY(mu_); +// ... +// }; // // Note that a pointer variable to a shared memory location could itself be a // shared variable. // // Example: // -// // `q`, guarded by `mu1`, points to a shared memory location that is -// // guarded by `mu2`: -// int *q GUARDED_BY(mu1) PT_GUARDED_BY(mu2); +// // `q_`, guarded by `mu1_`, points to a shared memory location that is +// // guarded by `mu2_`: +// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_); #define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) // ACQUIRED_AFTER() / ACQUIRED_BEFORE() @@ -80,10 +90,13 @@ // (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER // and ACQUIRED_BEFORE.) // +// As with GUARDED_BY, this is only applicable to mutexes that are shared +// fields or global variables. +// // Example: // -// Mutex m1; -// Mutex m2 ACQUIRED_AFTER(m1); +// Mutex m1_; +// Mutex m2_ ACQUIRED_AFTER(m1_); #define ACQUIRED_AFTER(...) \ THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) |