Refactor the windows api adaptation layer

This commit is contained in:
mutouyun 2024-09-28 20:44:10 +08:00
parent 7491a33d85
commit 5eafc13c1a
4 changed files with 96 additions and 76 deletions

View File

@ -15,6 +15,7 @@
#include "libimp/system.h"
#include "libimp/codecvt.h"
#include "libimp/span.h"
#include "libimp/detect_plat.h"
#include "libipc/def.h"
@ -33,10 +34,10 @@ inline tstring to_tstring(std::string const &str) {
}
/**
* \brief Create a SECURITY_ATTRIBUTES structure singleton
* \brief Creates or opens a SECURITY_ATTRIBUTES structure singleton
* \see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85)
*/
inline LPSECURITY_ATTRIBUTES get_sa() {
inline LPSECURITY_ATTRIBUTES get_security_descriptor() {
static struct initiator {
SECURITY_DESCRIPTOR sd_;
@ -46,7 +47,7 @@ inline LPSECURITY_ATTRIBUTES get_sa() {
initiator() {
using namespace ::LIBIMP;
LIBIMP_LOG_("get_sa");
LIBIMP_LOG_("get_security_descriptor");
if (!::InitializeSecurityDescriptor(&sd_, SECURITY_DESCRIPTOR_REVISION)) {
log.error("failed: InitializeSecurityDescriptor(SECURITY_DESCRIPTOR_REVISION). "
"error = ", sys::error());
@ -96,7 +97,7 @@ inline result<void> close_handle(HANDLE h) noexcept {
*
* \return File mapping object HANDLE, NULL on error.
*/
inline result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept {
inline result<HANDLE> open_file_mapping(std::string const &file, std::size_t size, mode::type type) noexcept {
LIBIMP_LOG_();
if (file.empty()) {
log.error("file name is empty.");
@ -121,7 +122,7 @@ inline result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode:
// Creates or opens a named or unnamed file mapping object for a specified file.
auto try_create = [&]() -> result<HANDLE> {
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, winapi::get_sa(), PAGE_READWRITE | SEC_COMMIT,
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, winapi::get_security_descriptor(), PAGE_READWRITE | SEC_COMMIT,
/// \remark dwMaximumSizeHigh always 0 here.
0, static_cast<DWORD>(size), t_name.c_str());
if (h == NULL) {
@ -159,7 +160,7 @@ inline result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode:
* \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
*/
inline result<LPVOID> mmap_memof(HANDLE h) {
inline result<LPVOID> address_of_file_mapping(HANDLE h) {
LIBIMP_LOG_();
if (h == NULL) {
log.error("handle is null.");
@ -178,7 +179,7 @@ inline 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
*/
inline result<SIZE_T> mmap_sizeof(LPCVOID mem) {
inline result<SIZE_T> region_size_of_address(LPCVOID mem) {
LIBIMP_LOG_();
if (mem == NULL) {
log.error("memory pointer is null.");
@ -197,7 +198,7 @@ inline 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
*/
inline result<void> mmap_release(HANDLE h, LPCVOID mem) {
inline result<void> close_file_mapping(HANDLE h, LPCVOID mem) {
LIBIMP_LOG_();
if (h == NULL) {
log.error("handle is null.");
@ -219,6 +220,8 @@ enum class wait_result {
timeout
};
LIBIMP_INLINE_CONSTEXPR std::int64_t const infinite_time = -1;
/**
* \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
@ -263,5 +266,79 @@ inline result<wait_result> wait_for_multiple_objects(span<HANDLE const> handles,
return wait_result::timeout;
}
/**
* \brief Retrieves the current value of the performance counter,
* which is a high resolution (<1us) time stamp that can be used for time-interval measurements.
* \see https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
*/
inline result<std::int64_t> query_performance_counter() noexcept {
LIBIMP_LOG_();
std::int64_t pc;
BOOL r = ::QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&pc));
if (!r) {
auto err = sys::error();
log.error("failed: QueryPerformanceCounter(). error = ", err);
return err;
}
return pc;
}
/**
* \brief Creates or opens a named or unnamed mutex object.
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa
* \return Mutex object HANDLE, NULL on error.
*/
inline result<HANDLE> open_mutex(char const *name, bool initial_owner) noexcept {
LIBIMP_LOG_();
HANDLE h = ::CreateMutexA(winapi::get_security_descriptor(), initial_owner, name);
if (h == NULL) {
auto err = sys::error();
log.error("failed: CreateMutexA(", initial_owner, ", ", name, "). error = ", err);
return err;
}
return h;
}
/**
* \brief Releases ownership of the specified mutex object.
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex
*/
inline result<bool> release_mutex(HANDLE h) noexcept {
LIBIMP_LOG_();
if (::ReleaseMutex(h)) {
return true;
}
auto err = sys::error();
log.error("failed: ReleaseMutex. error = ", err);
return err;
}
/**
* \brief Locks the mutex, blocks if the mutex is not available.
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
*/
inline result<bool> wait_mutex(HANDLE h, std::int64_t ms) noexcept {
LIBIMP_LOG_();
// If the mutex is abandoned, we need to release it and try again.
for (;;) {
auto r = winapi::wait_for_single_object(h, ms);
if (!r) {
return r.error();
}
if (*r == winapi::wait_result::object_0) {
return true;
}
if (*r == winapi::wait_result::abandoned) {
log.info("failed: WaitForSingleObject(", ms, "). The mutex is abandoned, try again.");
auto rr = release_mutex(h);
if (rr) {
continue;
}
return rr.error();
}
return false;
}
}
} // namespace winapi
LIBIPC_NAMESPACE_END_

View File

@ -42,7 +42,7 @@ bool is_valid(evt_t evt) noexcept {
result<evt_t> evt_open(std::string name) noexcept {
LIBIMP_LOG_();
auto t_name = winapi::to_tstring(name);
auto h = ::CreateEvent(winapi::get_sa(),
auto h = ::CreateEvent(winapi::get_security_descriptor(),
/*bManualReset*/ FALSE,
/*bInitialState*/FALSE,
/*lpName*/ t_name.c_str());

View File

@ -6,78 +6,21 @@
#include "libimp/log.h"
#include "libimp/system.h"
#include "libpmr/new.h"
#include "libipc/mutex.h"
#include "api.h"
#include "sync_id.h"
LIBIPC_NAMESPACE_BEG_
using namespace ::LIBIMP;
using namespace ::LIBPMR;
struct mutex_handle {
};
namespace winapi {
/**
* \brief Creates or opens a named or unnamed mutex object.
* \see https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa
* \return Mutex object HANDLE, NULL on error.
*/
result<HANDLE> mutex_open_or_create(char const *name, bool initial_owner) noexcept {
LIBIMP_LOG_();
HANDLE h = ::CreateMutexA(winapi::get_sa(), initial_owner, name);
if (h == NULL) {
auto err = sys::error();
log.error("failed: CreateMutexA(", initial_owner, ", ", name, "). error = ", err);
return err;
}
return h;
}
/**
* \brief Releases ownership of the specified mutex object.
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-releasemutex
*/
result<bool> mutex_release(HANDLE h) noexcept {
LIBIMP_LOG_();
if (::ReleaseMutex(h)) {
return true;
}
auto err = sys::error();
log.error("failed: ReleaseMutex. error = ", err);
return err;
}
/**
* \brief Locks the mutex, blocks if the mutex is not available.
* \see https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
*/
result<bool> mutex_wait(HANDLE h, std::int64_t ms) noexcept {
LIBIMP_LOG_();
for (;;) {
auto r = winapi::wait_for_single_object(h, ms);
if (!r) {
return r.error();
}
if (*r == winapi::wait_result::object_0) {
return true;
}
if (*r == winapi::wait_result::abandoned) {
log.info("failed: WaitForSingleObject(", ms, "). The mutex is abandoned, try again.");
auto rr = mutex_release(h);
if (rr) {
continue;
}
return rr.error();
}
return false;
}
}
} // namespace winapi
result<mutex_t> mutex_open(span<::LIBIMP::byte> mem) noexcept {
return {};
}

View File

@ -28,20 +28,20 @@ struct shm_handle {
result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noexcept {
LIBIMP_LOG_();
auto h = winapi::mmap_open(name, size, type);
auto h = winapi::open_file_mapping(name, size, type);
if (*h == NULL) {
log.error("failed: mmap_open(name = ", name, ", size = ", size, ", type = ", type, ").");
log.error("failed: OpenFileMapping(name = ", name, ", size = ", size, ", type = ", type, ").");
return h.error();
}
auto mem = winapi::mmap_memof(*h);
auto mem = winapi::address_of_file_mapping(*h);
if (*mem == NULL) {
log.error("failed: mmap_memof(", *h, ").");
log.error("failed: MapViewOfFile(", *h, ").");
winapi::close_handle(*h);
return mem.error();
}
auto sz = winapi::mmap_sizeof(*mem);
auto sz = winapi::region_size_of_address(*mem);
if (!sz) {
log.error("failed: mmap_sizeof(", *mem, ").");
log.error("failed: RegionSizeOfMemory(", *mem, ").");
winapi::close_handle(*h);
return sz.error();
}
@ -55,7 +55,7 @@ result<void> shm_close(shm_t h) noexcept {
return std::make_error_code(std::errc::invalid_argument);
}
auto shm = static_cast<shm_handle *>(h);
auto ret = winapi::mmap_release(shm->h_fmap, shm->memp);
auto ret = winapi::close_file_mapping(shm->h_fmap, shm->memp);
$delete(shm);
return ret;
}