blob: 28b1a7f9b32479243af3c98cfad98909175484fe [file] [log] [blame]
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),