| diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h |
| index 25b7d194..4a5cde33 100644 |
| --- a/googletest/include/gtest/internal/gtest-port.h |
| +++ b/googletest/include/gtest/internal/gtest-port.h |
| @@ -1237,9 +1237,6 @@ class GTEST_API_ AutoHandle { |
| // Nothing to do here. |
| |
| #else |
| -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ |
| -/* class A needs to have dll-interface to be used by clients of class B */) |
| - |
| // Allows a controller thread to pause execution of newly created |
| // threads until notified. Instances of this class must be created |
| // and destroyed in the controller thread. |
| @@ -1247,6 +1244,39 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ |
| // This class is only for testing Google Test's own constructs. Do not |
| // use it in user tests, either directly or indirectly. |
| // TODO(b/203539622): Replace unconditionally with absl::Notification. |
| +#ifdef GTEST_OS_WINDOWS_MINGW |
| +// GCC version < 13 with the win32 thread model does not provide std::mutex and |
| +// std::condition_variable in the <mutex> and <condition_variable> headers. So |
| +// we implement the Notification class using a Windows manual-reset event. See |
| +// https://gcc.gnu.org/gcc-13/changes.html#windows. |
| +class GTEST_API_ Notification { |
| + public: |
| + Notification(); |
| + Notification(const Notification&) = delete; |
| + Notification& operator=(const Notification&) = delete; |
| + ~Notification(); |
| + |
| + // Notifies all threads created with this notification to start. Must |
| + // be called from the controller thread. |
| + void Notify(); |
| + |
| + // Blocks until the controller thread notifies. Must be called from a test |
| + // thread. |
| + void WaitForNotification(); |
| + |
| + private: |
| + // Assume that Win32 HANDLE type is equivalent to void*. Doing so allows us to |
| + // avoid including <windows.h> in this header file. Including <windows.h> is |
| + // undesirable because it defines a lot of symbols and macros that tend to |
| + // conflict with client code. This assumption is verified by |
| + // WindowsTypesTest.HANDLEIsVoidStar. |
| + typedef void* Handle; |
| + Handle event_; |
| +}; |
| +#else |
| +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ |
| +/* class A needs to have dll-interface to be used by clients of class B */) |
| + |
| class GTEST_API_ Notification { |
| public: |
| Notification() : notified_(false) {} |
| @@ -1274,6 +1304,7 @@ class GTEST_API_ Notification { |
| bool notified_; |
| }; |
| GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 |
| +#endif // GTEST_OS_WINDOWS_MINGW |
| #endif // GTEST_HAS_NOTIFICATION_ |
| |
| // On MinGW, we can have both GTEST_OS_WINDOWS and GTEST_HAS_PTHREAD |
| diff --git a/googletest/src/gtest-port.cc b/googletest/src/gtest-port.cc |
| index 1038ad7b..53d41d38 100644 |
| --- a/googletest/src/gtest-port.cc |
| +++ b/googletest/src/gtest-port.cc |
| @@ -302,6 +302,22 @@ bool AutoHandle::IsCloseable() const { |
| return handle_ != nullptr && handle_ != INVALID_HANDLE_VALUE; |
| } |
| |
| +#if !GTEST_HAS_NOTIFICATION_ && defined(GTEST_OS_WINDOWS_MINGW) |
| +Notification::Notification() { |
| + // Create a manual-reset event object. |
| + event_ = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); |
| + GTEST_CHECK_(event_ != nullptr); |
| +} |
| + |
| +Notification::~Notification() { ::CloseHandle(event_); } |
| + |
| +void Notification::Notify() { GTEST_CHECK_(::SetEvent(event_)); } |
| + |
| +void Notification::WaitForNotification() { |
| + GTEST_CHECK_(::WaitForSingleObject(event_, INFINITE) == WAIT_OBJECT_0); |
| +} |
| +#endif // !GTEST_HAS_NOTIFICATION_ && defined(GTEST_OS_WINDOWS_MINGW) |
| + |
| Mutex::Mutex() |
| : owner_thread_id_(0), |
| type_(kDynamic), |