Add nameof & scope_exit

This commit is contained in:
mutouyun 2025-01-07 10:14:27 +08:00 committed by 木头云
parent f987e35870
commit b3d520cd25
6 changed files with 187 additions and 0 deletions

View File

@ -0,0 +1,43 @@
/**
* \file libimp/nameof.h
* \author mutouyun (orz@orzz.org)
* \brief Gets the name string of a type.
*/
#pragma once
#include <typeinfo>
#include <string>
#include <cstring>
#include "libipc/imp/export.h"
#include "libipc/imp/span.h"
#include "libipc/imp/detect_plat.h"
namespace ipc {
/**
* \brief The conventional way to obtain demangled symbol name.
* \see https://www.boost.org/doc/libs/1_80_0/libs/core/doc/html/core/demangle.html
*
* \param name the mangled name
* \return std::string a human-readable demangled type name
*/
IPC_EXPORT std::string demangle(std::string name) noexcept;
/**
* \brief Returns an implementation defined string containing the name of the type.
* \see https://en.cppreference.com/w/cpp/types/type_info/name
*
* \tparam T a type
* \return std::string a human-readable demangled type name
*/
template <typename T>
std::string nameof() noexcept {
LIBIPC_TRY {
return demangle(typeid(T).name());
} LIBIPC_CATCH(...) {
return {};
}
}
} // namespace ipc

View File

@ -0,0 +1,77 @@
/**
* \file libimp/scope_exit.h
* \author mutouyun (orz@orzz.org)
* \brief Execute guard function when the enclosing scope exits.
*/
#pragma once
#include <utility> // std::forward, std::move
#include <functional> // std::function
#include <type_traits>
#include "libipc/imp/detect_plat.h"
namespace ipc {
template <typename F = std::function<void()>>
class scope_exit {
F destructor_;
mutable bool released_;
public:
template <typename G>
explicit scope_exit(G &&destructor) noexcept
: destructor_(std::forward<G>(destructor))
, released_ (false) {}
scope_exit(scope_exit &&other) noexcept
: destructor_(std::move(other.destructor_))
, released_ (std::exchange(other.released_, true)) /*release rhs*/ {}
scope_exit &operator=(scope_exit &&other) noexcept {
destructor_ = std::move(other.destructor_);
released_ = std::exchange(other.released_, true);
return *this;
}
~scope_exit() noexcept {
if (!released_) destructor_();
}
void release() const noexcept {
released_ = true;
}
void do_exit() noexcept {
if (released_) return;
destructor_();
released_ = true;
}
void swap(scope_exit &other) noexcept {
std::swap(destructor_, other.destructor_);
std::swap(released_ , other.released_);
}
};
/// \brief Creates a scope_exit object.
template <typename F>
auto make_scope_exit(F &&destructor) noexcept {
return scope_exit<std::decay_t<F>>(std::forward<F>(destructor));
}
namespace detail_scope_exit {
struct scope_exit_helper {
template <typename F>
auto operator=(F &&f) const noexcept {
return make_scope_exit(std::forward<F>(f));
}
};
} // namespace detail_scope_exit
#define LIBIPC_SCOPE_EXIT($VAL) \
LIBIPC_UNUSED auto $VAL = ::ipc::detail_scope_exit::scope_exit_helper{}
} // namespace ipc

View File

@ -5,6 +5,8 @@ set (PACKAGE_VERSION 1.3.0)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES) aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/sync SRC_FILES) aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/sync SRC_FILES)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/platform SRC_FILES) aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/platform SRC_FILES)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/imp SRC_FILES)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/mem SRC_FILES)
file(GLOB HEAD_FILES file(GLOB HEAD_FILES
${LIBIPC_PROJECT_DIR}/include/libipc/*.h ${LIBIPC_PROJECT_DIR}/include/libipc/*.h

View File

@ -0,0 +1,7 @@
#include "libipc/imp/detect_plat.h"
#if defined(LIBIPC_CC_GNUC)
# include "libipc/platform/gnuc/demangle.h"
#else
# include "libipc/platform/win/demangle.h"
#endif

View File

@ -0,0 +1,43 @@
/**
* \file libipc/platform/gnuc/demangle.h
* \author mutouyun (orz@orzz.org)
*/
#pragma once
#include <cxxabi.h> // abi::__cxa_demangle
#include <cstdlib> // std::malloc
#include "libipc/imp/nameof.h"
#include "libipc/imp/scope_exit.h"
#include "libipc/imp/detect_plat.h"
namespace ipc {
/**
* \brief The conventional way to obtain demangled symbol name.
* \see https://www.boost.org/doc/libs/1_80_0/libs/core/doc/html/core/demangle.html
*
* \param name the mangled name
* \return std::string a human-readable demangled type name
*/
std::string demangle(std::string name) noexcept {
/// \see https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
std::size_t sz = name.size() + 1;
char *buffer = static_cast<char *>(std::malloc(sz));
int status = 0;
char *realname = abi::__cxa_demangle(name.data(), buffer, &sz, &status);
if (realname == nullptr) {
std::free(buffer);
return {};
}
LIBIPC_SCOPE_EXIT(guard) = [realname] {
std::free(realname);
};
LIBIPC_TRY {
return std::move(name.assign(realname, sz));
} LIBIPC_CATCH(...) {
return {};
}
}
} // namespace ipc

View File

@ -0,0 +1,15 @@
/**
* \file libipc/platform/win/demangle.h
* \author mutouyun (orz@orzz.org)
*/
#pragma once
#include "libipc/imp/nameof.h"
namespace ipc {
std::string demangle(std::string name) noexcept {
return std::move(name);
}
} // namespace ipc