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