Skip to content

Commit

Permalink
Refactor the windows api adaptation layer
Browse files Browse the repository at this point in the history
  • Loading branch information
mutouyun committed Sep 28, 2024
1 parent 7491a33 commit 5eafc13
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 76 deletions.
93 changes: 85 additions & 8 deletions src/libipc/platform/win/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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_;
Expand All @@ -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());
Expand Down Expand Up @@ -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.");
Expand All @@ -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) {
Expand Down Expand Up @@ -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.");
Expand All @@ -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.");
Expand All @@ -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.");
Expand All @@ -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
Expand Down Expand Up @@ -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_
2 changes: 1 addition & 1 deletion src/libipc/platform/win/event_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
63 changes: 3 additions & 60 deletions src/libipc/platform/win/mutex_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
}
Expand Down
14 changes: 7 additions & 7 deletions src/libipc/platform/win/shm_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand All @@ -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;
}
Expand Down

0 comments on commit 5eafc13

Please sign in to comment.