diff --git a/meson.build b/meson.build index aecb5db..b5e6b79 100644 --- a/meson.build +++ b/meson.build @@ -28,6 +28,7 @@ basic_tests = ['ManualResetInitialState', 'AutoResetInitialState', 'ManualResetBasicTests', 'AutoResetBasicTests', + 'EventContention', ] # Tests that required wfmo wfmo_tests = [ diff --git a/tests/EventContention.cpp b/tests/EventContention.cpp new file mode 100644 index 0000000..828c226 --- /dev/null +++ b/tests/EventContention.cpp @@ -0,0 +1,39 @@ +// This tests contention on an auto-reset event that is always available at a high level, to verify +// that other threads acquiring the protective pthread mutex don't result in a spurious WAIT_TIMEOUT +// error for any `WaitForEvent()` callers. +// +// See https://github.com/neosmart/pevents/issues/18 + +#ifdef _WIN32 +#include +#endif +#include +#include +#include +#include + +using namespace neosmart; + +int main() { + // Create an auto-reset event that is initially signalled + neosmart_event_t event = CreateEvent(false, true); + + + // Create n threads to constantly call SetEvent() in a tight loop + for (int i = 0; i < 16; ++i) { + std::thread t1([&] { + SetEvent(event); + }); + t1.detach(); + } + + // Call WaitForEvent() in a tight loop; we can expect it to always be available. + for (int i = 0; i < 200000; ++i) { + int result = WaitForEvent(event, 0); + assert(result == 0); + // Guarantee this thread always calls `WaitForEvent()` on a signalled event + SetEvent(event); + } + + return 0; +}