Refactor default_traits to include support for enum types

This commit is contained in:
mutouyun 2024-09-21 18:57:02 +08:00
parent 1c2fee0d72
commit f38d77beb9
3 changed files with 77 additions and 30 deletions

View File

@ -92,7 +92,8 @@ struct default_traits<void, ___> {
};
template <typename T>
struct default_traits<T, std::enable_if_t<std::is_integral<T>::value>> : generic_traits<T> {
struct default_traits<T, std::enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value>>
: generic_traits<T> {
/// \brief Custom initialization.
static constexpr void init_code(typename generic_traits<T>::storage_t &code,
T value, bool ok) noexcept {
@ -192,7 +193,7 @@ std::string default_traits<void, ___>::format(result<void> const &r) {
}
template <typename T>
std::string default_traits<T, std::enable_if_t<std::is_integral<T>::value>>
std::string default_traits<T, std::enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value>>
::format(result<T> const &r) noexcept {
return fmt(*r);
}

View File

@ -14,10 +14,12 @@
#include "libimp/log.h"
#include "libimp/system.h"
#include "libimp/codecvt.h"
#include "libimp/span.h"
#include "libipc/def.h"
LIBIPC_NAMESPACE_BEG_
using namespace ::LIBIMP;
namespace winapi {
@ -94,7 +96,7 @@ inline result<void> close_handle(HANDLE h) noexcept {
*
* \return File mapping object HANDLE, NULL on error.
*/
result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept {
inline result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept {
LIBIMP_LOG_();
if (file.empty()) {
log.error("file name is empty.");
@ -157,7 +159,7 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
* \brief Maps a view of a file mapping into the address space of a calling process.
* \see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile
*/
result<LPVOID> mmap_memof(HANDLE h) {
inline result<LPVOID> mmap_memof(HANDLE h) {
LIBIMP_LOG_();
if (h == NULL) {
log.error("handle is null.");
@ -176,7 +178,7 @@ result<LPVOID> mmap_memof(HANDLE h) {
* \brief Retrieves the size about a range of pages in the virtual address space of the calling process.
* \see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualquery
*/
result<SIZE_T> mmap_sizeof(LPCVOID mem) {
inline result<SIZE_T> mmap_sizeof(LPCVOID mem) {
LIBIMP_LOG_();
if (mem == NULL) {
log.error("memory pointer is null.");
@ -195,7 +197,7 @@ result<SIZE_T> mmap_sizeof(LPCVOID mem) {
* \brief Unmaps a mapped view of a file from the calling process's address space.
* \see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-unmapviewoffile
*/
result<void> mmap_release(HANDLE h, LPCVOID mem) {
inline result<void> mmap_release(HANDLE h, LPCVOID mem) {
LIBIMP_LOG_();
if (h == NULL) {
log.error("handle is null.");
@ -211,5 +213,55 @@ result<void> mmap_release(HANDLE h, LPCVOID mem) {
return winapi::close_handle(h);
}
enum class wait_result {
object_0,
abandoned,
timeout
};
/**
* \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
*/
inline result<wait_result> wait_for_single_object(HANDLE h, std::int64_t ms) noexcept {
LIBIMP_LOG_();
DWORD dwMilliseconds = (ms < 0) ? INFINITE : static_cast<DWORD>(ms);
DWORD r = ::WaitForSingleObject(h, dwMilliseconds);
if (r == WAIT_FAILED) {
auto err = sys::error();
log.error("failed: WaitForSingleObject(", h, ", ", dwMilliseconds, "). error = ", err);
return err;
}
if (r == WAIT_OBJECT_0) {
return wait_result::object_0;
}
if (r == WAIT_ABANDONED) {
return wait_result::abandoned;
}
return wait_result::timeout;
}
/**
* \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
*/
inline result<wait_result> wait_for_multiple_objects(span<HANDLE const> handles, std::int64_t ms) noexcept {
LIBIMP_LOG_();
DWORD dwMilliseconds = (ms < 0) ? INFINITE : static_cast<DWORD>(ms);
DWORD r = ::WaitForMultipleObjects(static_cast<DWORD>(handles.size()), handles.data(), FALSE, dwMilliseconds);
if (r == WAIT_FAILED) {
auto err = sys::error();
log.error("failed: WaitForMultipleObjects(", handles.size(), ", ", dwMilliseconds, "). error = ", err);
return err;
}
if ((r >= WAIT_OBJECT_0) && (r < WAIT_OBJECT_0 + handles.size())) {
return wait_result::object_0;
}
if ((r >= WAIT_ABANDONED_0) && (r < WAIT_ABANDONED_0 + handles.size())) {
return wait_result::abandoned;
}
return wait_result::timeout;
}
} // namespace winapi
LIBIPC_NAMESPACE_END_

View File

@ -95,21 +95,18 @@ result<bool> evt_wait(evt_t evt, std::int64_t ms) noexcept {
log.error("handle is null.");
return std::make_error_code(std::errc::invalid_argument);
}
DWORD dwMilliseconds = (ms < 0) ? INFINITE : static_cast<DWORD>(ms);
auto r = ::WaitForSingleObject(evt->h_event, dwMilliseconds);
if (r == WAIT_TIMEOUT) {
return false;
auto r = winapi::wait_for_single_object(evt->h_event, ms);
if (!r) {
return r.error();
}
if (r == WAIT_ABANDONED_0) {
log.error("failed: WaitForSingleObject(", evt->h_event, ", ", dwMilliseconds, "). error = WAIT_ABANDONED_0");
return {};
}
if (r == WAIT_OBJECT_0) {
if (*r == winapi::wait_result::object_0) {
return true;
}
auto err = sys::error();
log.error("failed: WaitForSingleObject(", evt->h_event, ", ", dwMilliseconds, "). error = ", err);
return err;
if (*r == winapi::wait_result::abandoned) {
log.error("failed: WaitForSingleObject(", evt->h_event, ", ", ms, "). error = WAIT_ABANDONED");
return false;
}
return false;
}
/**
@ -132,21 +129,18 @@ result<bool> evt_wait(::LIBIMP::span<evt_t const> evts, std::int64_t ms) noexcep
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;
auto r = winapi::wait_for_multiple_objects(handles, ms);
if (!r) {
return r.error();
}
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())) {
if (*r == winapi::wait_result::object_0) {
return true;
}
auto err = sys::error();
log.error("failed: WaitForMultipleObjects(", handles.size(), ", ", dwMilliseconds, "). error = ", err);
return err;
if (*r == winapi::wait_result::abandoned) {
log.error("failed: WaitForMultipleObjects(", handles.size(), ", ", ms, "). error = WAIT_ABANDONED");
return false;
}
return false;
}
LIBIPC_NAMESPACE_END_