diff --git a/include/libimp/result.h b/include/libimp/result.h index f27f0b3..5097282 100644 --- a/include/libimp/result.h +++ b/include/libimp/result.h @@ -27,7 +27,8 @@ class LIBIMP_EXPORT result_code { public: result_code() noexcept; - result_code(bool ok, std::uint64_t value = {}) noexcept; + result_code(std::uint64_t value) noexcept; + result_code(bool ok, std::uint64_t value) noexcept; std::uint64_t value() const noexcept; bool ok() const noexcept; @@ -103,7 +104,11 @@ public: using default_traits_t = DefTraits; result() noexcept = default; - result(bool ok, T value = default_traits_t::value()) noexcept + + result(T value) noexcept + : result(true, std::move(value)) {} + + result(bool ok, T value) noexcept : code_(ok, default_traits_t::cast_to_code(value)) {} T value() const noexcept { return default_traits_t::cast_from_code(code_.value()); } diff --git a/src/libimp/result.cpp b/src/libimp/result.cpp index e6f624b..4036fe8 100644 --- a/src/libimp/result.cpp +++ b/src/libimp/result.cpp @@ -21,7 +21,10 @@ result_code_info info_cast(std::uint64_t status) noexcept { } // namespace result_code::result_code() noexcept - : result_code(false) {} + : result_code(false, {}) {} + +result_code::result_code(std::uint64_t value) noexcept + : result_code(true, value) {} result_code::result_code(bool ok, std::uint64_t code) noexcept : status_(make_status(ok, code)) {} diff --git a/src/libipc/platform/posix/def.h b/src/libipc/platform/posix/def.h index 1032935..d6c53b1 100644 --- a/src/libipc/platform/posix/def.h +++ b/src/libipc/platform/posix/def.h @@ -10,6 +10,7 @@ LIBIPC_NAMESPACE_BEG_ namespace posix { enum : int { + succ = 0, failed = -1, }; diff --git a/src/libipc/platform/posix/shm_impl.h b/src/libipc/platform/posix/shm_impl.h index f95f7e7..f5e23e6 100644 --- a/src/libipc/platform/posix/shm_impl.h +++ b/src/libipc/platform/posix/shm_impl.h @@ -31,13 +31,23 @@ struct shm_handle { void *memp; }; -/** - * @see https://man7.org/linux/man-pages/man3/shm_open.3.html - * https://man7.org/linux/man-pages/man3/fstat.3p.html - * https://man7.org/linux/man-pages/man3/ftruncate.3p.html - * https://man7.org/linux/man-pages/man2/mmap.2.html - */ -result shm_open(std::string name, std::size_t size, mode::type type) noexcept { +namespace { + +shm_handle *valid(shm_t h) noexcept { + LIBIMP_LOG_(); + if (h == nullptr) { + log.error("shm handle is null."); + return nullptr; + } + auto shm = static_cast(h); + if (shm->memp == nullptr) { + log.error("memory pointer is null."); + return nullptr; + } + return shm; +} + +result shm_open_fd(std::string const &name, mode::type type) noexcept { LIBIMP_LOG_(); if (name.empty()) { log.error("name is empty."); @@ -48,7 +58,6 @@ result shm_open(std::string name, std::size_t size, mode::type type) noex int flag = O_RDWR; switch (type) { case mode::open: - size = 0; break; // The check for the existence of the object, // and its creation if it does not exist, are performed atomically. @@ -65,50 +74,64 @@ result shm_open(std::string name, std::size_t size, mode::type type) noex } /// @brief Create/Open POSIX shared memory bject - int fd = ::shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP | - S_IROTH | S_IWOTH); - if (fd == posix::failed) { + return ::shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | + S_IROTH | S_IWOTH); +} + +result_code ftruncate_fd(int fd, std::size_t size) noexcept { + LIBIMP_LOG_(); + /// @see https://man7.org/linux/man-pages/man3/ftruncate.3p.html + if (::ftruncate(fd, size) != posix::succ) { + auto err = sys::error(); + log.error("ftruncate({}, {}) fails. error = {}", fd, size, err); + return err.code(); + } + return {posix::succ}; +} + +} // namespace + +/** + * @see https://man7.org/linux/man-pages/man3/shm_open.3.html + * https://man7.org/linux/man-pages/man3/fstat.3p.html + * https://man7.org/linux/man-pages/man2/mmap.2.html + */ +result shm_open(std::string name, std::size_t size, mode::type type) noexcept { + LIBIMP_LOG_(); + auto fd = shm_open_fd(name, type); + if (!fd) return {}; + if (*fd == posix::failed) { log.error("shm_open fails. error = {}", sys::error()); return {}; } - LIBIMP_UNUSED auto guard = std::unique_ptr(&fd, [](int *pfd) { - if (pfd != nullptr) ::close(*pfd); - }); + LIBIMP_UNUSED auto guard = std::unique_ptr { + &fd, [](decltype(fd) *pfd) { + if (pfd != nullptr) ::close(**pfd); + }}; /// @brief Try to get the size of this fd struct stat st; - if (::fstat(fd, &st) == posix::failed) { + if (::fstat(*fd, &st) == posix::failed) { log.error("fstat fails. error = {}", sys::error()); - ::shm_unlink(name.c_str()); return {}; } /// @brief Truncate this fd to a specified length - auto ftruncate = [&log, &name](int fd, std::size_t size) { - if (::ftruncate(fd, size) != 0) { - log.error("ftruncate fails. error = {}", sys::error()); - ::shm_unlink(name.c_str()); - return false; - } - return true; - }; - if (size == 0) { size = static_cast(st.st_size); - if (!ftruncate(fd, size)) return {}; + if (!ftruncate_fd(*fd, size)) return {}; } else if (st.st_size > 0) { /// @remark Based on the actual size. size = static_cast(st.st_size); } else { // st.st_size <= 0 - if (!ftruncate(fd, size)) return {}; + if (!ftruncate_fd(*fd, size)) return {}; } /// @brief Creates a new mapping in the virtual address space of the calling process. - void *mem = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + void *mem = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0); if (mem == MAP_FAILED) { log.error("mmap fails. error = {}", sys::error()); - ::shm_unlink(name.c_str()); return {}; } return new shm_handle{std::move(name), size, mem}; @@ -119,23 +142,16 @@ result shm_open(std::string name, std::size_t size, mode::type type) noex */ result_code shm_close(shm_t h) noexcept { LIBIMP_LOG_(); - if (h == nullptr) { - log.error("shm handle is null."); - return {}; - } - auto shm = static_cast(h); - if (shm->memp == nullptr) { - log.error("memory pointer is null."); - return {}; - } + auto shm = valid(h); + if (shm == nullptr) return {}; if (::munmap(shm->memp, shm->f_sz) == posix::failed) { - auto ec = sys::error_code(); - log.error("munmap fails. error = {}", sys::error(ec)); - return ec; + auto err = sys::error(); + log.error("munmap({}, {}) fails. error = {}", shm->memp, shm->f_sz, err); + return err.code(); } /// @brief no unlink the file. delete shm; - return {true}; + return {posix::succ}; } LIBIPC_NAMESPACE_END_ diff --git a/src/libipc/platform/win/shm_impl.h b/src/libipc/platform/win/shm_impl.h index 0df9a8f..bda8d92 100644 --- a/src/libipc/platform/win/shm_impl.h +++ b/src/libipc/platform/win/shm_impl.h @@ -40,7 +40,7 @@ result_code shm_close(shm_t h) noexcept { auto shm = static_cast(h); mmap_release(shm->h_fmap, shm->memp); delete shm; - return {true}; + return {0}; } LIBIPC_NAMESPACE_END_ diff --git a/test/test_imp_result.cpp b/test/test_imp_result.cpp index 87f9cd4..8230469 100644 --- a/test/test_imp_result.cpp +++ b/test/test_imp_result.cpp @@ -12,7 +12,7 @@ TEST(result, ok) { EXPECT_FALSE(ret.ok()); EXPECT_EQ(ret.value(), 0); - ret = {true}; + ret = {true, 0}; EXPECT_TRUE(ret); EXPECT_TRUE(ret.ok()); EXPECT_EQ(ret.value(), 0); @@ -29,7 +29,7 @@ TEST(result, code) { EXPECT_TRUE(ret.ok()); EXPECT_EQ(ret.value(), 1234); - ret = {false}; + ret = {false, 0}; EXPECT_FALSE(ret); EXPECT_FALSE(ret.ok()); EXPECT_EQ(ret.value(), 0); @@ -62,7 +62,7 @@ TEST(result, fmt) { EXPECT_EQ(fmt::format("{}", r1), "[fail, value = 0]"); imp::result_code r2(true, 65537); EXPECT_EQ(fmt::format("{}", r2), "[succ, value = 65537]"); - imp::result_code r3(true); + imp::result_code r3(0); EXPECT_EQ(fmt::format("{}", r3), "[succ, value = 0]"); } {