diff --git a/include/libipc/event.h b/include/libipc/event.h index d10e622..ee56ac7 100644 --- a/include/libipc/event.h +++ b/include/libipc/event.h @@ -36,7 +36,7 @@ LIBIMP_EXPORT ::LIBIMP::result evt_set(evt_t) noexcept; LIBIMP_EXPORT ::LIBIMP::result evt_wait(evt_t, std::int64_t ms) noexcept; /// \brief Waits until one or all of the specified objects are in the signaled state or the time-out interval elapses. -LIBIMP_EXPORT ::LIBIMP::result evt_wait(::LIBIMP::span, std::int64_t ms) noexcept; +LIBIMP_EXPORT ::LIBIMP::result evt_wait(::LIBIMP::span, std::int64_t ms) noexcept; /** * \brief The event object. diff --git a/src/libipc/event.cpp b/src/libipc/event.cpp index 3f14aef..81fb9cb 100644 --- a/src/libipc/event.cpp +++ b/src/libipc/event.cpp @@ -1,8 +1,6 @@ #include "libimp/log.h" -#include "libimp/detect_plat.h" - #include "libimp/detect_plat.h" #if defined(LIBIMP_OS_WIN) # include "libipc/platform/win/event_impl.h" diff --git a/src/libipc/platform/win/event_impl.h b/src/libipc/platform/win/event_impl.h index ca892f6..90e1f64 100644 --- a/src/libipc/platform/win/event_impl.h +++ b/src/libipc/platform/win/event_impl.h @@ -42,7 +42,10 @@ bool is_valid(evt_t evt) noexcept { result evt_open(std::string name) noexcept { LIBIMP_LOG_(); auto t_name = detail::to_tstring(name); - auto h = ::CreateEvent(detail::get_sa(), FALSE, FALSE, t_name.c_str()); + auto h = ::CreateEvent(detail::get_sa(), + /*bManualReset*/ FALSE, + /*bInitialState*/FALSE, + /*lpName*/ t_name.c_str()); if (h == NULL) { auto err = sys::error(); log.error("failed: CreateEvent(FALSE, FALSE, ", name, "). error = ", err); @@ -119,7 +122,7 @@ result evt_wait(evt_t evt, std::int64_t ms) noexcept { * \brief Waits until one or all of the specified objects are in the signaled state or the time-out interval elapses. * \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitformultipleobjects */ -result evt_wait(::LIBIMP::span evts, std::int64_t ms) noexcept { +result evt_wait(::LIBIMP::span evts, std::int64_t ms) noexcept { LIBIMP_LOG_(); if (evts.empty()) { log.error("evts handle is empty."); diff --git a/test/ipc/test_ipc_event.cpp b/test/ipc/test_ipc_event.cpp index fcd9c51..a0332b1 100644 --- a/test/ipc/test_ipc_event.cpp +++ b/test/ipc/test_ipc_event.cpp @@ -1,4 +1,6 @@ +#include + #include "gtest/gtest.h" #include @@ -10,10 +12,88 @@ TEST(event, open_close) { ASSERT_TRUE(ipc::evt_close(*evt)); } +TEST(event, wait_timeout) { + auto evt = ipc::evt_open("test"); + ASSERT_TRUE(evt); + ASSERT_FALSE(*ipc::evt_wait(*evt, 0)); + ASSERT_TRUE(ipc::evt_close(*evt)); +} + TEST(event, set_wait) { auto evt = ipc::evt_open("test"); ASSERT_TRUE(evt); ASSERT_TRUE(ipc::evt_set(*evt)); - ASSERT_TRUE(ipc::evt_wait(*evt, 0)); + ASSERT_TRUE(*ipc::evt_wait(*evt, 0)); ASSERT_TRUE(ipc::evt_close(*evt)); } + +TEST(event, unicast) { + auto evt = ipc::evt_open("test"); + ASSERT_TRUE(evt); + int success = 0; + auto wait = [evt, &success] { + if (*ipc::evt_wait(*evt, 200)) ++success; + }; + auto th1 = std::thread(wait); + auto th2 = std::thread(wait); + auto th3 = std::thread(wait); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ASSERT_TRUE(ipc::evt_set(*evt)); + th1.join(); + th2.join(); + th3.join(); + ASSERT_TRUE(ipc::evt_close(*evt)); + ASSERT_EQ(success, 1); +} + +TEST(event, wait_multi_timeout) { + auto evt1 = ipc::evt_open("test1"); + ASSERT_TRUE(evt1); + auto evt2 = ipc::evt_open("test2"); + ASSERT_TRUE(evt2); + auto evt3 = ipc::evt_open("test3"); + ASSERT_TRUE(evt3); + ASSERT_FALSE(*ipc::evt_wait(imp::make_span({*evt1, *evt2, *evt3}), 0)); + ASSERT_TRUE(ipc::evt_close(*evt1)); + ASSERT_TRUE(ipc::evt_close(*evt2)); + ASSERT_TRUE(ipc::evt_close(*evt3)); +} + +TEST(event, set_wait_multi) { + auto evt1 = ipc::evt_open("test1"); + ASSERT_TRUE(evt1); + auto evt2 = ipc::evt_open("test2"); + ASSERT_TRUE(evt2); + auto evt3 = ipc::evt_open("test3"); + ASSERT_TRUE(evt3); + ASSERT_TRUE(ipc::evt_set(*evt2)); + ASSERT_TRUE(*ipc::evt_wait(imp::make_span({*evt1, *evt2, *evt3}), 0)); + ASSERT_TRUE(ipc::evt_close(*evt1)); + ASSERT_TRUE(ipc::evt_close(*evt2)); + ASSERT_TRUE(ipc::evt_close(*evt3)); +} + +TEST(event, unicast_multi) { + auto evt1 = ipc::evt_open("test1"); + ASSERT_TRUE(evt1); + auto evt2 = ipc::evt_open("test2"); + ASSERT_TRUE(evt2); + auto evt3 = ipc::evt_open("test3"); + ASSERT_TRUE(evt3); + int success = 0; + auto wait = [evt1, evt2, evt3, &success] { + if (*ipc::evt_wait(imp::make_span({*evt1, *evt2, *evt3}), 200)) ++success; + }; + auto th1 = std::thread(wait); + auto th2 = std::thread(wait); + auto th3 = std::thread(wait); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ASSERT_TRUE(ipc::evt_set(*evt3)); + th1.join(); + th2.join(); + th3.join(); + ASSERT_TRUE(ipc::evt_close(*evt1)); + ASSERT_TRUE(ipc::evt_close(*evt2)); + ASSERT_TRUE(ipc::evt_close(*evt3)); + ASSERT_EQ(success, 1); +}