mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2026-02-07 18:26:41 +08:00
add: [ipc] add Windows implementation of event
This commit is contained in:
parent
5a3ecbbc69
commit
08b6649946
@ -19,7 +19,7 @@ LIBIPC_NAMESPACE_BEG_
|
|||||||
struct evt_handle;
|
struct evt_handle;
|
||||||
using evt_t = evt_handle *;
|
using evt_t = evt_handle *;
|
||||||
|
|
||||||
/// \brief Create a new event object with a name.
|
/// \brief Creates or opens a named event object.
|
||||||
LIBIMP_EXPORT ::LIBIMP::result<evt_t> evt_open(std::string name) noexcept;
|
LIBIMP_EXPORT ::LIBIMP::result<evt_t> evt_open(std::string name) noexcept;
|
||||||
|
|
||||||
/// \brief Close the event object.
|
/// \brief Close the event object.
|
||||||
@ -32,8 +32,10 @@ LIBIMP_EXPORT std::string evt_name(evt_t) noexcept;
|
|||||||
/// \brief Sets the event object to the signaled state.
|
/// \brief Sets the event object to the signaled state.
|
||||||
LIBIMP_EXPORT ::LIBIMP::result<void> evt_set(evt_t) noexcept;
|
LIBIMP_EXPORT ::LIBIMP::result<void> evt_set(evt_t) noexcept;
|
||||||
|
|
||||||
/// \brief Waits until one of the specified event objects is in the signaled state.
|
/// \brief Waits until the specified object is in the signaled state or the time-out interval elapses.
|
||||||
LIBIMP_EXPORT ::LIBIMP::result<bool> evt_wait(evt_t, std::int64_t ms) noexcept;
|
LIBIMP_EXPORT ::LIBIMP::result<bool> 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<bool> evt_wait(::LIBIMP::span<evt_t>, std::int64_t ms) noexcept;
|
LIBIMP_EXPORT ::LIBIMP::result<bool> evt_wait(::LIBIMP::span<evt_t>, std::int64_t ms) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -41,9 +41,11 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC
|
target_link_libraries(${PROJECT_NAME} PUBLIC
|
||||||
$<$<NOT:$<STREQUAL:${CMAKE_SYSTEM_NAME},QNX>>:pthread>
|
$<$<NOT:$<STREQUAL:${CMAKE_SYSTEM_NAME},QNX>>:pthread>
|
||||||
$<$<NOT:$<OR:$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>,$<STREQUAL:${CMAKE_SYSTEM_NAME},QNX>>>:rt>)
|
$<$<NOT:$<OR:$<STREQUAL:${CMAKE_SYSTEM_NAME},Windows>,$<STREQUAL:${CMAKE_SYSTEM_NAME},QNX>>>:rt>
|
||||||
|
"-Wl,--whole-archive" imp pmr "-Wl,--no-whole-archive")
|
||||||
|
else()
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC imp pmr)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC imp)
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS ${PROJECT_NAME}
|
TARGETS ${PROJECT_NAME}
|
||||||
|
|||||||
27
src/libipc/event.cpp
Normal file
27
src/libipc/event.cpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#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"
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
|
/// \brief C style event access interface implementation.
|
||||||
|
|
||||||
|
std::string evt_name(evt_t evt) noexcept {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (!is_valid(evt)) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return evt->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief The event object.
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_END_
|
||||||
155
src/libipc/platform/win/event_impl.h
Normal file
155
src/libipc/platform/win/event_impl.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/**
|
||||||
|
* \file libipc/platform/win/event_impl.h
|
||||||
|
* \author mutouyun (orz@orzz.org)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
#include "libimp/log.h"
|
||||||
|
#include "libipc/event.h"
|
||||||
|
|
||||||
|
#include "get_sa.h"
|
||||||
|
#include "to_tchar.h"
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
using namespace ::LIBIMP;
|
||||||
|
|
||||||
|
struct evt_handle {
|
||||||
|
std::string name;
|
||||||
|
HANDLE h_event;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool is_valid(evt_t evt) noexcept {
|
||||||
|
return (evt != nullptr) && (evt->h_event != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates or opens a named event object.
|
||||||
|
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventa
|
||||||
|
* \param name The name of the event object. The name is limited to MAX_PATH characters. Name comparison is case sensitive.
|
||||||
|
* \return A handle to the event object, NULL on error.
|
||||||
|
*/
|
||||||
|
result<evt_t> 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());
|
||||||
|
if (h == NULL) {
|
||||||
|
auto err = sys::error();
|
||||||
|
log.error("failed: CreateEvent(FALSE, FALSE, ", name, "). error = ", err);
|
||||||
|
return {nullptr, err};
|
||||||
|
}
|
||||||
|
return new evt_handle{std::move(name), h};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Closes an open object handle.
|
||||||
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
|
||||||
|
*/
|
||||||
|
result<void> evt_close(evt_t evt) noexcept {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
LIBIMP_UNUSED auto guard = std::unique_ptr<evt_handle>(evt);
|
||||||
|
if (!is_valid(evt)) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!::CloseHandle(evt->h_event)) {
|
||||||
|
auto err = sys::error();
|
||||||
|
log.error("failed: CloseHandle(", evt->h_event, "). error = ", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return no_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sets the specified event object to the signaled state.
|
||||||
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setevent
|
||||||
|
*/
|
||||||
|
result<void> evt_set(evt_t evt) noexcept {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (!is_valid(evt)) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (!::SetEvent(evt->h_event)) {
|
||||||
|
auto err = sys::error();
|
||||||
|
log.error("failed: SetEvent(", evt->h_event, "). error = ", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return no_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Waits until the specified object is in the signaled state or the time-out interval elapses.
|
||||||
|
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
|
||||||
|
*/
|
||||||
|
result<bool> evt_wait(evt_t evt, std::int64_t ms) noexcept {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (!is_valid(evt)) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
DWORD dwMilliseconds = (ms < 0) ? INFINITE : static_cast<DWORD>(ms);
|
||||||
|
auto r = ::WaitForSingleObject(evt->h_event, dwMilliseconds);
|
||||||
|
if (r == WAIT_TIMEOUT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (r == WAIT_ABANDONED_0) {
|
||||||
|
log.error("failed: WaitForSingleObject(", evt->h_event, ", ", dwMilliseconds, "). error = WAIT_ABANDONED_0");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (r == WAIT_OBJECT_0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto err = sys::error();
|
||||||
|
log.error("failed: WaitForSingleObject(", evt->h_event, ", ", dwMilliseconds, "). error = ", err);
|
||||||
|
return {false, err};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \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<bool> evt_wait(::LIBIMP::span<evt_t> evts, std::int64_t ms) noexcept {
|
||||||
|
LIBIMP_LOG_();
|
||||||
|
if (evts.empty()) {
|
||||||
|
log.error("evts handle is empty.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
// Conversion of the event handle array to the windows handle array.
|
||||||
|
std::vector<HANDLE> handles(evts.size());
|
||||||
|
for (std::size_t i = 0; i < evts.size(); ++i) {
|
||||||
|
if (!is_valid(evts[i])) {
|
||||||
|
log.error("handle is null.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
handles[i] = evts[i]->h_event;
|
||||||
|
}
|
||||||
|
// Wait for the events.
|
||||||
|
DWORD dwMilliseconds = (ms < 0) ? INFINITE : static_cast<DWORD>(ms);
|
||||||
|
auto r = ::WaitForMultipleObjects(static_cast<DWORD>(handles.size()), handles.data(), FALSE, dwMilliseconds);
|
||||||
|
if (r == WAIT_TIMEOUT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((r >= WAIT_ABANDONED_0) && (r < WAIT_ABANDONED_0 + handles.size())) {
|
||||||
|
log.error("failed: WaitForMultipleObjects(", handles.size(), ", ", dwMilliseconds, "). error = WAIT_ABANDONED_0 + ", r - WAIT_ABANDONED_0);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if ((r >= WAIT_OBJECT_0) && (r < WAIT_OBJECT_0 + handles.size())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto err = sys::error();
|
||||||
|
log.error("failed: WaitForMultipleObjects(", handles.size(), ", ", dwMilliseconds, "). error = ", err);
|
||||||
|
return {false, err};
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBIPC_NAMESPACE_END_
|
||||||
@ -53,12 +53,12 @@ result<void> mmap_close(HANDLE h) {
|
|||||||
* \see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfilemappinga
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfilemappinga
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga
|
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga
|
||||||
*
|
*
|
||||||
* \param file Specifies the name of the file mapping object
|
* \param file Specifies the name of the file mapping object.
|
||||||
* \param size Specifies the size required to create a file mapping object.
|
* \param size Specifies the size required to create a file mapping object.
|
||||||
* This size is ignored when opening an existing file mapping object
|
* This size is ignored when opening an existing file mapping object.
|
||||||
* \param type Combinable open modes, create | open
|
* \param type Combinable open modes, create | open.
|
||||||
*
|
*
|
||||||
* \return File mapping object HANDLE, NULL on error
|
* \return File mapping object HANDLE, NULL on error.
|
||||||
*/
|
*/
|
||||||
result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept {
|
result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user