mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-06 16:56:45 +08:00
upd: [ipc] allow shm error codes to be passed out
This commit is contained in:
parent
375c25bd1e
commit
03dce063f9
@ -17,23 +17,25 @@
|
||||
|
||||
LIBIMP_NAMESPACE_BEG_
|
||||
|
||||
using result_type = std::uint64_t;
|
||||
|
||||
/**
|
||||
* @brief Use the least significant (in Little-Endian) of
|
||||
* a 64-bit unsigned integer to indicate success or failure,
|
||||
* so the data significant bit cannot exceed 63 bits.
|
||||
*/
|
||||
class LIBIMP_EXPORT result_code {
|
||||
std::uint64_t status_;
|
||||
result_type status_;
|
||||
|
||||
public:
|
||||
result_code() noexcept;
|
||||
result_code(std::uint64_t value) noexcept;
|
||||
result_code(bool ok, std::uint64_t value) noexcept;
|
||||
result_code(result_type value) noexcept;
|
||||
result_code(bool ok, result_type value) noexcept;
|
||||
|
||||
std::uint64_t value() const noexcept;
|
||||
result_type value() const noexcept;
|
||||
bool ok() const noexcept;
|
||||
|
||||
std::uint64_t operator*() const noexcept {
|
||||
result_type operator*() const noexcept {
|
||||
return value();
|
||||
}
|
||||
explicit operator bool() const noexcept {
|
||||
@ -62,10 +64,10 @@ template <typename T>
|
||||
struct default_traits<T, std::enable_if_t<std::is_integral<T>::value>> {
|
||||
constexpr static T value() noexcept { return 0; }
|
||||
|
||||
static std::uint64_t cast_to_code(T value) noexcept {
|
||||
return static_cast<std::uint64_t>(value);
|
||||
static result_type cast_to_code(T value) noexcept {
|
||||
return static_cast<result_type>(value);
|
||||
}
|
||||
static T cast_from_code(std::uint64_t code) noexcept {
|
||||
static T cast_from_code(result_type code) noexcept {
|
||||
return static_cast<T>(code);
|
||||
}
|
||||
template <typename Out>
|
||||
@ -78,10 +80,10 @@ template <typename T>
|
||||
struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> {
|
||||
constexpr static T value() noexcept { return nullptr; }
|
||||
|
||||
static std::uint64_t cast_to_code(T value) noexcept {
|
||||
return reinterpret_cast<std::uint64_t>(value);
|
||||
static result_type cast_to_code(T value) noexcept {
|
||||
return reinterpret_cast<result_type>(value);
|
||||
}
|
||||
static T cast_from_code(std::uint64_t code) noexcept {
|
||||
static T cast_from_code(result_type code) noexcept {
|
||||
return reinterpret_cast<T>(code);
|
||||
}
|
||||
template <typename Out>
|
||||
@ -89,7 +91,7 @@ struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> {
|
||||
if LIBIMP_LIKELY(r) {
|
||||
return format_to(out, "{}", static_cast<void *>(*r));
|
||||
}
|
||||
return format_to(out, "{}, code = {}", static_cast<void *>(*r), r.code());
|
||||
return format_to(out, "{}, code = {}", static_cast<void *>(*r), r.code_value());
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,12 +139,12 @@ public:
|
||||
: code_(default_traits_t::value() != value,
|
||||
default_traits_t::cast_to_code(value)) {}
|
||||
|
||||
result(std::nullptr_t, std::uint64_t code) noexcept
|
||||
result(std::nullptr_t, result_type code) noexcept
|
||||
: code_(false, code) {}
|
||||
|
||||
T value() const noexcept { return code_.ok() ? default_traits_t::cast_from_code(code_.value()) : nullptr; }
|
||||
bool ok() const noexcept { return code_.ok(); }
|
||||
std::uint64_t code() const noexcept { return code_.value(); }
|
||||
result_type code_value() const noexcept { return code_.value(); }
|
||||
|
||||
T operator*() const noexcept {
|
||||
return value();
|
||||
@ -171,7 +173,7 @@ struct fmt::formatter<::LIBIMP_::result<T, D>> {
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<::LIBIMP_::result_code>
|
||||
: formatter<::LIBIMP_::result<std::uint64_t>> {
|
||||
: formatter<::LIBIMP_::result<::LIBIMP_::result_type>> {
|
||||
template <typename FormatContext>
|
||||
auto format(::LIBIMP_::result_code r, FormatContext &ctx) {
|
||||
return format_to(ctx.out(), "[{}, value = {}]", (r ? "succ" : "fail"), *r);
|
||||
|
||||
@ -25,7 +25,9 @@ namespace sys {
|
||||
*/
|
||||
result_code error_code() noexcept {
|
||||
auto err = ::GetLastError();
|
||||
if (err == ERROR_SUCCESS) return {true};
|
||||
if (err == ERROR_SUCCESS) {
|
||||
return {ERROR_SUCCESS};
|
||||
}
|
||||
return {false, std::uint64_t(err)};
|
||||
}
|
||||
|
||||
@ -82,7 +84,7 @@ std::string error_str(result_code code) noexcept {
|
||||
* https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo
|
||||
* https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo
|
||||
*/
|
||||
std::int64_t conf(info r) noexcept {
|
||||
result<std::int64_t> conf(info r) noexcept {
|
||||
LIBIMP_LOG_();
|
||||
switch (r) {
|
||||
case info::page_size: {
|
||||
@ -92,7 +94,7 @@ std::int64_t conf(info r) noexcept {
|
||||
}
|
||||
default:
|
||||
log.error("invalid info = {}", enum_cast(r));
|
||||
return -1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -33,15 +33,18 @@ namespace {
|
||||
* @brief Closes an open object handle.
|
||||
* @see https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
|
||||
*/
|
||||
void mmap_close(HANDLE h) {
|
||||
result_code mmap_close(HANDLE h) {
|
||||
LIBIMP_LOG_();
|
||||
if (h == NULL) {
|
||||
log.error("handle is null.");
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
if (!::CloseHandle(h)) {
|
||||
log.error("CloseHandle fails. error = {}", sys::error());
|
||||
auto err = sys::error();
|
||||
log.error("CloseHandle({}) fails. error = {}", h, err);
|
||||
return err.code();
|
||||
}
|
||||
return {ERROR_SUCCESS};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,35 +60,38 @@ void mmap_close(HANDLE h) {
|
||||
*
|
||||
* @return File mapping object HANDLE, NULL on error
|
||||
*/
|
||||
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_();
|
||||
if (file.empty()) {
|
||||
log.error("file name is empty.");
|
||||
return NULL;
|
||||
return {};
|
||||
}
|
||||
auto t_name = detail::to_tstring(file);
|
||||
if (t_name.empty()) {
|
||||
log.error("file name is empty. (TCHAR conversion failed)");
|
||||
return NULL;
|
||||
return {};
|
||||
}
|
||||
|
||||
/// @brief Opens a named file mapping object.
|
||||
auto try_open = [&]() -> HANDLE {
|
||||
auto try_open = [&]() -> result<HANDLE> {
|
||||
HANDLE h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, t_name.c_str());
|
||||
if (h == NULL) {
|
||||
log.error("OpenFileMapping fails. error = {}", sys::error());
|
||||
auto err = sys::error();
|
||||
log.error("OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, {}) fails. error = {}", file, err);
|
||||
return {nullptr, err.value()};
|
||||
}
|
||||
return h;
|
||||
};
|
||||
|
||||
/// @brief Creates or opens a named or unnamed file mapping object for a specified file.
|
||||
auto try_create = [&]() -> HANDLE {
|
||||
auto try_create = [&]() -> result<HANDLE> {
|
||||
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, detail::get_sa(), PAGE_READWRITE | SEC_COMMIT,
|
||||
/// @remark dwMaximumSizeHigh always 0 here.
|
||||
0, static_cast<DWORD>(size), t_name.c_str());
|
||||
if (h == NULL) {
|
||||
log.error("CreateFileMapping fails. error = {}", sys::error());
|
||||
return NULL;
|
||||
auto err = sys::error();
|
||||
log.error("CreateFileMapping(PAGE_READWRITE | SEC_COMMIT, {}, {}) fails. error = {}", size, file, err);
|
||||
return {nullptr, err.value()};
|
||||
}
|
||||
return h;
|
||||
};
|
||||
@ -99,15 +105,16 @@ HANDLE mmap_open(std::string const &file, std::size_t size, mode::type type) noe
|
||||
return try_open();
|
||||
} else if (!(type & mode::create)) {
|
||||
log.error("mode type is invalid. type = {}", type);
|
||||
return NULL;
|
||||
return {};
|
||||
}
|
||||
HANDLE h = try_create();
|
||||
auto h = try_create();
|
||||
if (!h) return h;
|
||||
/// @remark If the object exists before the function call, the function returns a handle to the existing object
|
||||
/// (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS.
|
||||
if ((type == mode::create) && (::GetLastError() == ERROR_ALREADY_EXISTS)) {
|
||||
mmap_close(h);
|
||||
log.info("the file being created already exists. file = {}, type = {}", file, type);
|
||||
return NULL;
|
||||
mmap_close(*h);
|
||||
return {};
|
||||
}
|
||||
return h;
|
||||
}
|
||||
@ -116,16 +123,17 @@ HANDLE mmap_open(std::string const &file, std::size_t size, mode::type type) noe
|
||||
* @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
|
||||
*/
|
||||
LPVOID mmap_memof(HANDLE h) {
|
||||
result<LPVOID> mmap_memof(HANDLE h) {
|
||||
LIBIMP_LOG_();
|
||||
if (h == NULL) {
|
||||
log.error("handle is null.");
|
||||
return NULL;
|
||||
return {};
|
||||
}
|
||||
LPVOID mem = ::MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
if (h == NULL) {
|
||||
log.error("MapViewOfFile fails. error = {}", sys::error());
|
||||
return NULL;
|
||||
if (mem == NULL) {
|
||||
auto err = sys::error();
|
||||
log.error("MapViewOfFile({}, FILE_MAP_ALL_ACCESS) fails. error = {}", h, err);
|
||||
return {nullptr, err.value()};
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
@ -134,16 +142,17 @@ 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
|
||||
*/
|
||||
SIZE_T mmap_sizeof(LPCVOID mem) {
|
||||
result<SIZE_T> mmap_sizeof(LPCVOID mem) {
|
||||
LIBIMP_LOG_();
|
||||
if (mem == NULL) {
|
||||
log.error("memory pointer is null.");
|
||||
return 0;
|
||||
return {};
|
||||
}
|
||||
MEMORY_BASIC_INFORMATION mem_info {};
|
||||
if (::VirtualQuery(mem, &mem_info, sizeof(mem_info)) == 0) {
|
||||
log.error("VirtualQuery fails. error = {}", sys::error());
|
||||
return 0;
|
||||
auto err = sys::error();
|
||||
log.error("VirtualQuery({}) fails. error = {}", mem, err);
|
||||
return {false, (SIZE_T)err.value()};
|
||||
}
|
||||
return mem_info.RegionSize;
|
||||
}
|
||||
@ -152,20 +161,20 @@ 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
|
||||
*/
|
||||
void mmap_release(HANDLE h, LPCVOID mem) {
|
||||
result_code mmap_release(HANDLE h, LPCVOID mem) {
|
||||
LIBIMP_LOG_();
|
||||
if (h == NULL) {
|
||||
log.error("handle is null.");
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
if (mem == NULL) {
|
||||
log.error("memory pointer is null.");
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
if (!::UnmapViewOfFile(mem)) {
|
||||
log.warning("UnmapViewOfFile fails. error = {}", sys::error());
|
||||
}
|
||||
mmap_close(h);
|
||||
return mmap_close(h);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -22,13 +22,21 @@ result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noex
|
||||
auto h = mmap_open(name, size, type);
|
||||
if (h == NULL) {
|
||||
log.error("mmap_open failed.");
|
||||
return {nullptr, *sys::error_code()};
|
||||
return {nullptr, h.code_value()};
|
||||
}
|
||||
auto mem = mmap_memof(h);
|
||||
if (mem == NULL) {
|
||||
log.warning("mmap_memof failed.");
|
||||
auto mem = mmap_memof(*h);
|
||||
if (*mem == NULL) {
|
||||
log.error("mmap_memof failed.");
|
||||
mmap_close(*h);
|
||||
return {nullptr, mem.code_value()};
|
||||
}
|
||||
return new shm_handle{std::move(name), mmap_sizeof(mem), mem, h};
|
||||
auto sz = mmap_sizeof(*mem);
|
||||
if (!sz) {
|
||||
log.error("mmap_sizeof failed.");
|
||||
mmap_close(*h);
|
||||
return {nullptr, static_cast<result_type>(sz.value())};
|
||||
}
|
||||
return new shm_handle{std::move(name), *sz, *mem, *h};
|
||||
}
|
||||
|
||||
result_code shm_close(shm_t h) noexcept {
|
||||
@ -38,9 +46,9 @@ result_code shm_close(shm_t h) noexcept {
|
||||
return {};
|
||||
}
|
||||
auto shm = static_cast<shm_handle *>(h);
|
||||
mmap_release(shm->h_fmap, shm->memp);
|
||||
auto ret = mmap_release(shm->h_fmap, shm->memp);
|
||||
delete shm;
|
||||
return {0};
|
||||
return ret;
|
||||
}
|
||||
|
||||
LIBIPC_NAMESPACE_END_
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user