upd: [imp] improve interface of result

This commit is contained in:
mutouyun 2022-11-06 17:39:08 +08:00
parent 0a88c53aeb
commit 94cae29b42
6 changed files with 75 additions and 50 deletions

View File

@ -27,7 +27,8 @@ class LIBIMP_EXPORT result_code {
public: public:
result_code() noexcept; 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; std::uint64_t value() const noexcept;
bool ok() const noexcept; bool ok() const noexcept;
@ -103,7 +104,11 @@ public:
using default_traits_t = DefTraits; using default_traits_t = DefTraits;
result() noexcept = default; 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)) {} : code_(ok, default_traits_t::cast_to_code(value)) {}
T value() const noexcept { return default_traits_t::cast_from_code(code_.value()); } T value() const noexcept { return default_traits_t::cast_from_code(code_.value()); }

View File

@ -21,7 +21,10 @@ result_code_info info_cast(std::uint64_t status) noexcept {
} // namespace } // namespace
result_code::result_code() noexcept 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 result_code::result_code(bool ok, std::uint64_t code) noexcept
: status_(make_status(ok, code)) {} : status_(make_status(ok, code)) {}

View File

@ -10,6 +10,7 @@ LIBIPC_NAMESPACE_BEG_
namespace posix { namespace posix {
enum : int { enum : int {
succ = 0,
failed = -1, failed = -1,
}; };

View File

@ -31,13 +31,23 @@ struct shm_handle {
void *memp; void *memp;
}; };
/** namespace {
* @see https://man7.org/linux/man-pages/man3/shm_open.3.html
* https://man7.org/linux/man-pages/man3/fstat.3p.html shm_handle *valid(shm_t h) noexcept {
* https://man7.org/linux/man-pages/man3/ftruncate.3p.html LIBIMP_LOG_();
* https://man7.org/linux/man-pages/man2/mmap.2.html if (h == nullptr) {
*/ log.error("shm handle is null.");
result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noexcept { return nullptr;
}
auto shm = static_cast<shm_handle *>(h);
if (shm->memp == nullptr) {
log.error("memory pointer is null.");
return nullptr;
}
return shm;
}
result<int> shm_open_fd(std::string const &name, mode::type type) noexcept {
LIBIMP_LOG_(); LIBIMP_LOG_();
if (name.empty()) { if (name.empty()) {
log.error("name is empty."); log.error("name is empty.");
@ -48,7 +58,6 @@ result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noex
int flag = O_RDWR; int flag = O_RDWR;
switch (type) { switch (type) {
case mode::open: case mode::open:
size = 0;
break; break;
// The check for the existence of the object, // The check for the existence of the object,
// and its creation if it does not exist, are performed atomically. // and its creation if it does not exist, are performed atomically.
@ -65,50 +74,64 @@ result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noex
} }
/// @brief Create/Open POSIX shared memory bject /// @brief Create/Open POSIX shared memory bject
int fd = ::shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR | return ::shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH); S_IROTH | S_IWOTH);
if (fd == posix::failed) { }
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_t> 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()); log.error("shm_open fails. error = {}", sys::error());
return {}; return {};
} }
LIBIMP_UNUSED auto guard = std::unique_ptr<int, void (*)(int *)>(&fd, [](int *pfd) { LIBIMP_UNUSED auto guard = std::unique_ptr<decltype(fd), void (*)(decltype(fd) *)> {
if (pfd != nullptr) ::close(*pfd); &fd, [](decltype(fd) *pfd) {
}); if (pfd != nullptr) ::close(**pfd);
}};
/// @brief Try to get the size of this fd /// @brief Try to get the size of this fd
struct stat st; struct stat st;
if (::fstat(fd, &st) == posix::failed) { if (::fstat(*fd, &st) == posix::failed) {
log.error("fstat fails. error = {}", sys::error()); log.error("fstat fails. error = {}", sys::error());
::shm_unlink(name.c_str());
return {}; return {};
} }
/// @brief Truncate this fd to a specified length /// @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) { if (size == 0) {
size = static_cast<std::size_t>(st.st_size); size = static_cast<std::size_t>(st.st_size);
if (!ftruncate(fd, size)) return {}; if (!ftruncate_fd(*fd, size)) return {};
} else if (st.st_size > 0) { } else if (st.st_size > 0) {
/// @remark Based on the actual size. /// @remark Based on the actual size.
size = static_cast<std::size_t>(st.st_size); size = static_cast<std::size_t>(st.st_size);
} else { // st.st_size <= 0 } 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. /// @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) { if (mem == MAP_FAILED) {
log.error("mmap fails. error = {}", sys::error()); log.error("mmap fails. error = {}", sys::error());
::shm_unlink(name.c_str());
return {}; return {};
} }
return new shm_handle{std::move(name), size, mem}; return new shm_handle{std::move(name), size, mem};
@ -119,23 +142,16 @@ result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noex
*/ */
result_code shm_close(shm_t h) noexcept { result_code shm_close(shm_t h) noexcept {
LIBIMP_LOG_(); LIBIMP_LOG_();
if (h == nullptr) { auto shm = valid(h);
log.error("shm handle is null."); if (shm == nullptr) return {};
return {};
}
auto shm = static_cast<shm_handle *>(h);
if (shm->memp == nullptr) {
log.error("memory pointer is null.");
return {};
}
if (::munmap(shm->memp, shm->f_sz) == posix::failed) { if (::munmap(shm->memp, shm->f_sz) == posix::failed) {
auto ec = sys::error_code(); auto err = sys::error();
log.error("munmap fails. error = {}", sys::error(ec)); log.error("munmap({}, {}) fails. error = {}", shm->memp, shm->f_sz, err);
return ec; return err.code();
} }
/// @brief no unlink the file. /// @brief no unlink the file.
delete shm; delete shm;
return {true}; return {posix::succ};
} }
LIBIPC_NAMESPACE_END_ LIBIPC_NAMESPACE_END_

View File

@ -40,7 +40,7 @@ result_code shm_close(shm_t h) noexcept {
auto shm = static_cast<shm_handle *>(h); auto shm = static_cast<shm_handle *>(h);
mmap_release(shm->h_fmap, shm->memp); mmap_release(shm->h_fmap, shm->memp);
delete shm; delete shm;
return {true}; return {0};
} }
LIBIPC_NAMESPACE_END_ LIBIPC_NAMESPACE_END_

View File

@ -12,7 +12,7 @@ TEST(result, ok) {
EXPECT_FALSE(ret.ok()); EXPECT_FALSE(ret.ok());
EXPECT_EQ(ret.value(), 0); EXPECT_EQ(ret.value(), 0);
ret = {true}; ret = {true, 0};
EXPECT_TRUE(ret); EXPECT_TRUE(ret);
EXPECT_TRUE(ret.ok()); EXPECT_TRUE(ret.ok());
EXPECT_EQ(ret.value(), 0); EXPECT_EQ(ret.value(), 0);
@ -29,7 +29,7 @@ TEST(result, code) {
EXPECT_TRUE(ret.ok()); EXPECT_TRUE(ret.ok());
EXPECT_EQ(ret.value(), 1234); EXPECT_EQ(ret.value(), 1234);
ret = {false}; ret = {false, 0};
EXPECT_FALSE(ret); EXPECT_FALSE(ret);
EXPECT_FALSE(ret.ok()); EXPECT_FALSE(ret.ok());
EXPECT_EQ(ret.value(), 0); EXPECT_EQ(ret.value(), 0);
@ -62,7 +62,7 @@ TEST(result, fmt) {
EXPECT_EQ(fmt::format("{}", r1), "[fail, value = 0]"); EXPECT_EQ(fmt::format("{}", r1), "[fail, value = 0]");
imp::result_code r2(true, 65537); imp::result_code r2(true, 65537);
EXPECT_EQ(fmt::format("{}", r2), "[succ, value = 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]"); EXPECT_EQ(fmt::format("{}", r3), "[succ, value = 0]");
} }
{ {