mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
upd: comment style
This commit is contained in:
parent
3880639699
commit
424bb73c94
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libconcur/concurrent.h
|
* \file libconcur/concurrent.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define different policies for concurrent queue.
|
* \brief Define different policies for concurrent queue.
|
||||||
* @date 2022-11-07
|
* \date 2022-11-07
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -17,10 +17,10 @@
|
|||||||
|
|
||||||
LIBCONCUR_NAMESPACE_BEG_
|
LIBCONCUR_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief The queue index type.
|
/// \brief The queue index type.
|
||||||
using index_t = std::uint32_t;
|
using index_t = std::uint32_t;
|
||||||
|
|
||||||
/// @brief Multiplicity of the relationship.
|
/// \brief Multiplicity of the relationship.
|
||||||
namespace relation {
|
namespace relation {
|
||||||
|
|
||||||
class single {};
|
class single {};
|
||||||
@ -28,7 +28,7 @@ class multi {};
|
|||||||
|
|
||||||
} // namespace relation
|
} // namespace relation
|
||||||
|
|
||||||
/// @brief Transmission mode
|
/// \brief Transmission mode
|
||||||
namespace trans {
|
namespace trans {
|
||||||
|
|
||||||
class unicast {};
|
class unicast {};
|
||||||
@ -36,52 +36,52 @@ class broadcast {};
|
|||||||
|
|
||||||
} // namespace trans
|
} // namespace trans
|
||||||
|
|
||||||
/// @brief Determines whether type T can be implicitly converted to type U.
|
/// \brief Determines whether type T can be implicitly converted to type U.
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
using is_convertible = typename std::enable_if<std::is_convertible<T *, U *>::value>::type;
|
using is_convertible = typename std::enable_if<std::is_convertible<T *, U *>::value>::type;
|
||||||
|
|
||||||
/// @brief Check whether the context type is valid.
|
/// \brief Check whether the context type is valid.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_context = decltype(typename std::enable_if<std::is_convertible<decltype(
|
using is_context = decltype(typename std::enable_if<std::is_convertible<decltype(
|
||||||
std::declval<T>().valid()), bool>::value>::type(),
|
std::declval<T>().valid()), bool>::value>::type(),
|
||||||
std::declval<index_t>() % std::declval<T>().circ_size);
|
std::declval<index_t>() % std::declval<T>().circ_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculate the corresponding queue position modulo the index value.
|
* \brief Calculate the corresponding queue position modulo the index value.
|
||||||
*
|
*
|
||||||
* @tparam C a context type
|
* \tparam C a context type
|
||||||
* @param ctx a context object
|
* \param ctx a context object
|
||||||
* @param idx a context array index
|
* \param idx a context array index
|
||||||
* @return index_t - a corresponding queue position
|
* \return index_t - a corresponding queue position
|
||||||
*/
|
*/
|
||||||
template <typename C, typename = is_context<C>>
|
template <typename C, typename = is_context<C>>
|
||||||
constexpr index_t trunc_index(C const &ctx, index_t idx) noexcept {
|
constexpr index_t trunc_index(C const &ctx, index_t idx) noexcept {
|
||||||
/// @remark `circ_size == 2^N` => `idx & (circ_size - 1)`
|
/// \remark `circ_size == 2^N` => `idx & (circ_size - 1)`
|
||||||
return ctx.valid() ? (idx % ctx.circ_size) : 0;
|
return ctx.valid() ? (idx % ctx.circ_size) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Producer algorithm implementation.
|
/// \brief Producer algorithm implementation.
|
||||||
template <typename TransModT, typename RelationT>
|
template <typename TransModT, typename RelationT>
|
||||||
struct producer;
|
struct producer;
|
||||||
|
|
||||||
/// @brief Consumer algorithm implementation.
|
/// \brief Consumer algorithm implementation.
|
||||||
template <typename TransModT, typename RelationT>
|
template <typename TransModT, typename RelationT>
|
||||||
struct consumer;
|
struct consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Algorithm definition under unicast transmission model.
|
* \brief Algorithm definition under unicast transmission model.
|
||||||
*
|
*
|
||||||
* @ref A bounded wait-free(almost) zero-copy MPMC queue written in C++11.
|
* \ref A bounded wait-free(almost) zero-copy MPMC queue written in C++11.
|
||||||
* Modified from MengRao/WFMPMC.
|
* Modified from MengRao/WFMPMC.
|
||||||
* Copyright (c) 2018. Meng Rao (https://github.com/MengRao/WFMPMC).
|
* Copyright (c) 2018. Meng Rao (https://github.com/MengRao/WFMPMC).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// @brief Single-write producer model implementation.
|
/// \brief Single-write producer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct producer<trans::unicast, relation::single> {
|
struct producer<trans::unicast, relation::single> {
|
||||||
|
|
||||||
struct context_impl {
|
struct context_impl {
|
||||||
/// @brief Write index.
|
/// \brief Write index.
|
||||||
alignas(cache_line_size) index_t w_idx {0};
|
alignas(cache_line_size) index_t w_idx {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,26 +93,26 @@ struct producer<trans::unicast, relation::single> {
|
|||||||
auto w_cur = trunc_index(ctx, w_idx);
|
auto w_cur = trunc_index(ctx, w_idx);
|
||||||
auto &elem = elems[w_cur];
|
auto &elem = elems[w_cur];
|
||||||
auto f_ct = elem.get_flag();
|
auto f_ct = elem.get_flag();
|
||||||
/// @remark Verify index.
|
/// \remark Verify index.
|
||||||
if ((f_ct != state::invalid_value) &&
|
if ((f_ct != state::invalid_value) &&
|
||||||
(f_ct != w_idx)) {
|
(f_ct != w_idx)) {
|
||||||
return false; // full
|
return false; // full
|
||||||
}
|
}
|
||||||
/// @remark Get a valid index and iterate backwards.
|
/// \remark Get a valid index and iterate backwards.
|
||||||
ctx.w_idx += 1;
|
ctx.w_idx += 1;
|
||||||
/// @remark Set data & flag.
|
/// \remark Set data & flag.
|
||||||
elem.set_data(std::forward<U>(src));
|
elem.set_data(std::forward<U>(src));
|
||||||
elem.set_flag(static_cast<index_t>(~w_idx));
|
elem.set_flag(static_cast<index_t>(~w_idx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Multi-write producer model implementation.
|
/// \brief Multi-write producer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct producer<trans::unicast, relation::multi> {
|
struct producer<trans::unicast, relation::multi> {
|
||||||
|
|
||||||
struct context_impl {
|
struct context_impl {
|
||||||
/// @brief Write index.
|
/// \brief Write index.
|
||||||
alignas(cache_line_size) std::atomic<index_t> w_idx {0};
|
alignas(cache_line_size) std::atomic<index_t> w_idx {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,16 +125,16 @@ struct producer<trans::unicast, relation::multi> {
|
|||||||
auto w_cur = trunc_index(ctx, w_idx);
|
auto w_cur = trunc_index(ctx, w_idx);
|
||||||
auto &elem = elems[w_cur];
|
auto &elem = elems[w_cur];
|
||||||
auto f_ct = elem.get_flag();
|
auto f_ct = elem.get_flag();
|
||||||
/// @remark Verify index.
|
/// \remark Verify index.
|
||||||
if ((f_ct != state::invalid_value) &&
|
if ((f_ct != state::invalid_value) &&
|
||||||
(f_ct != w_idx)) {
|
(f_ct != w_idx)) {
|
||||||
return false; // full
|
return false; // full
|
||||||
}
|
}
|
||||||
/// @remark Get a valid index and iterate backwards.
|
/// \remark Get a valid index and iterate backwards.
|
||||||
if (!ctx.w_idx.compare_exchange_weak(w_idx, w_idx + 1, std::memory_order_acq_rel)) {
|
if (!ctx.w_idx.compare_exchange_weak(w_idx, w_idx + 1, std::memory_order_acq_rel)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/// @remark Set data & flag.
|
/// \remark Set data & flag.
|
||||||
elem.set_data(std::forward<U>(src));
|
elem.set_data(std::forward<U>(src));
|
||||||
elem.set_flag(static_cast<index_t>(~w_idx));
|
elem.set_flag(static_cast<index_t>(~w_idx));
|
||||||
return true;
|
return true;
|
||||||
@ -142,12 +142,12 @@ struct producer<trans::unicast, relation::multi> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Single-read consumer model implementation.
|
/// \brief Single-read consumer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct consumer<trans::unicast, relation::single> {
|
struct consumer<trans::unicast, relation::single> {
|
||||||
|
|
||||||
struct context_impl {
|
struct context_impl {
|
||||||
/// @brief Read index.
|
/// \brief Read index.
|
||||||
alignas(cache_line_size) index_t r_idx {0};
|
alignas(cache_line_size) index_t r_idx {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -159,25 +159,25 @@ struct consumer<trans::unicast, relation::single> {
|
|||||||
auto r_cur = trunc_index(ctx, r_idx);
|
auto r_cur = trunc_index(ctx, r_idx);
|
||||||
auto &elem = elems[r_cur];
|
auto &elem = elems[r_cur];
|
||||||
auto f_ct = elem.get_flag();
|
auto f_ct = elem.get_flag();
|
||||||
/// @remark Verify index.
|
/// \remark Verify index.
|
||||||
if (f_ct != static_cast<index_t>(~r_idx)) {
|
if (f_ct != static_cast<index_t>(~r_idx)) {
|
||||||
return false; // empty
|
return false; // empty
|
||||||
}
|
}
|
||||||
/// @remark Get a valid index and iterate backwards.
|
/// \remark Get a valid index and iterate backwards.
|
||||||
ctx.r_idx += 1;
|
ctx.r_idx += 1;
|
||||||
/// @remark Get data & set flag.
|
/// \remark Get data & set flag.
|
||||||
des = elem.get_data();
|
des = elem.get_data();
|
||||||
elem.set_flag(r_idx + static_cast<index_t>(elems.size()));
|
elem.set_flag(r_idx + static_cast<index_t>(elems.size()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Multi-read consumer model implementation.
|
/// \brief Multi-read consumer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct consumer<trans::unicast, relation::multi> {
|
struct consumer<trans::unicast, relation::multi> {
|
||||||
|
|
||||||
struct context_impl {
|
struct context_impl {
|
||||||
/// @brief Read index.
|
/// \brief Read index.
|
||||||
alignas(cache_line_size) std::atomic<index_t> r_idx {0};
|
alignas(cache_line_size) std::atomic<index_t> r_idx {0};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -190,15 +190,15 @@ struct consumer<trans::unicast, relation::multi> {
|
|||||||
auto r_cur = trunc_index(ctx, r_idx);
|
auto r_cur = trunc_index(ctx, r_idx);
|
||||||
auto &elem = elems[r_cur];
|
auto &elem = elems[r_cur];
|
||||||
auto f_ct = elem.get_flag();
|
auto f_ct = elem.get_flag();
|
||||||
/// @remark Verify index.
|
/// \remark Verify index.
|
||||||
if (f_ct != static_cast<index_t>(~r_idx)) {
|
if (f_ct != static_cast<index_t>(~r_idx)) {
|
||||||
return false; // empty
|
return false; // empty
|
||||||
}
|
}
|
||||||
/// @remark Get a valid index and iterate backwards.
|
/// \remark Get a valid index and iterate backwards.
|
||||||
if (!ctx.r_idx.compare_exchange_weak(r_idx, r_idx + 1, std::memory_order_acq_rel)) {
|
if (!ctx.r_idx.compare_exchange_weak(r_idx, r_idx + 1, std::memory_order_acq_rel)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/// @remark Get data & set flag.
|
/// \remark Get data & set flag.
|
||||||
des = elem.get_data();
|
des = elem.get_data();
|
||||||
elem.set_flag(r_idx + static_cast<index_t>(elems.size()));
|
elem.set_flag(r_idx + static_cast<index_t>(elems.size()));
|
||||||
return true;
|
return true;
|
||||||
@ -207,41 +207,41 @@ struct consumer<trans::unicast, relation::multi> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Algorithm definition under broadcast transmission model.
|
* \brief Algorithm definition under broadcast transmission model.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// @brief Single-write producer model implementation.
|
/// \brief Single-write producer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct producer<trans::broadcast, relation::single> {
|
struct producer<trans::broadcast, relation::single> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Multi-write producer model implementation.
|
/// \brief Multi-write producer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct producer<trans::broadcast, relation::multi> {
|
struct producer<trans::broadcast, relation::multi> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Single-read consumer model implementation.
|
/// \brief Single-read consumer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct consumer<trans::broadcast, relation::single> {
|
struct consumer<trans::broadcast, relation::single> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Multi-read consumer model implementation.
|
/// \brief Multi-read consumer model implementation.
|
||||||
template <>
|
template <>
|
||||||
struct consumer<trans::broadcast, relation::multi> {
|
struct consumer<trans::broadcast, relation::multi> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Producer-consumer implementation.
|
* \brief Producer-consumer implementation.
|
||||||
*
|
*
|
||||||
* @tparam TransModT transmission mode (trans::unicast/trans::broadcast)
|
* \tparam TransModT transmission mode (trans::unicast/trans::broadcast)
|
||||||
* @tparam ProdModT producer relationship model (relation::single/relation::multi)
|
* \tparam ProdModT producer relationship model (relation::single/relation::multi)
|
||||||
* @tparam ConsModT consumer relationship model (relation::single/relation::multi)
|
* \tparam ConsModT consumer relationship model (relation::single/relation::multi)
|
||||||
*/
|
*/
|
||||||
template <typename TransModT, typename ProdModT, typename ConsModT>
|
template <typename TransModT, typename ProdModT, typename ConsModT>
|
||||||
struct prod_cons : producer<TransModT, ProdModT>
|
struct prod_cons : producer<TransModT, ProdModT>
|
||||||
, consumer<TransModT, ConsModT> {
|
, consumer<TransModT, ConsModT> {
|
||||||
|
|
||||||
/// @brief Mixing producer and consumer context definitions.
|
/// \brief Mixing producer and consumer context definitions.
|
||||||
struct context : producer<TransModT, ProdModT>::context_impl
|
struct context : producer<TransModT, ProdModT>::context_impl
|
||||||
, consumer<TransModT, ConsModT>::context_impl {
|
, consumer<TransModT, ConsModT>::context_impl {
|
||||||
index_t const circ_size;
|
index_t const circ_size;
|
||||||
@ -254,7 +254,7 @@ struct prod_cons : producer<TransModT, ProdModT>
|
|||||||
: circ_size(static_cast<index_t>(elems.size())) {}
|
: circ_size(static_cast<index_t>(elems.size())) {}
|
||||||
|
|
||||||
constexpr bool valid() const noexcept {
|
constexpr bool valid() const noexcept {
|
||||||
/// @remark circ_size must be a power of two.
|
/// \remark circ_size must be a power of two.
|
||||||
return (circ_size > 1) && ((circ_size & (circ_size - 1)) == 0);
|
return (circ_size > 1) && ((circ_size & (circ_size - 1)) == 0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libconcur/def.h
|
* \file libconcur/def.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the trivial configuration information for concurrency.
|
* \brief Define the trivial configuration information for concurrency.
|
||||||
* @date 2022-11-07
|
* \date 2022-11-07
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
LIBCONCUR_NAMESPACE_BEG_
|
LIBCONCUR_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief Constants.
|
/// \brief Constants.
|
||||||
|
|
||||||
enum : std::size_t {
|
enum : std::size_t {
|
||||||
/// @brief Minimum offset between two objects to avoid false sharing.
|
/// \brief Minimum offset between two objects to avoid false sharing.
|
||||||
/// @see https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size
|
/// \see https://en.cppreference.com/w/cpp/thread/hardware_destructive_interference_size
|
||||||
cache_line_size =
|
cache_line_size =
|
||||||
#if defined(LIBIMP_CPP_17) && defined(__cpp_lib_hardware_interference_size)
|
#if defined(LIBIMP_CPP_17) && defined(__cpp_lib_hardware_interference_size)
|
||||||
( std::hardware_destructive_interference_size < alignof(std::max_align_t) ) ? 64
|
( std::hardware_destructive_interference_size < alignof(std::max_align_t) ) ? 64
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libconcur/element.h
|
* \file libconcur/element.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define concurrent queue element abstraction.
|
* \brief Define concurrent queue element abstraction.
|
||||||
* @date 2022-11-19
|
* \date 2022-11-19
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -20,11 +20,11 @@
|
|||||||
LIBCONCUR_NAMESPACE_BEG_
|
LIBCONCUR_NAMESPACE_BEG_
|
||||||
namespace state {
|
namespace state {
|
||||||
|
|
||||||
/// @brief The state flag type for the queue element.
|
/// \brief The state flag type for the queue element.
|
||||||
using flag_t = std::uint64_t;
|
using flag_t = std::uint64_t;
|
||||||
|
|
||||||
enum : flag_t {
|
enum : flag_t {
|
||||||
/// @brief The invalid state value.
|
/// \brief The invalid state value.
|
||||||
invalid_value = (std::numeric_limits<flag_t>::max)(),
|
invalid_value = (std::numeric_limits<flag_t>::max)(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,12 +32,12 @@ enum : flag_t {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class element {
|
class element {
|
||||||
/// @brief Committed flag.
|
/// \brief Committed flag.
|
||||||
alignas(cache_line_size) std::atomic<state::flag_t> f_ct_;
|
alignas(cache_line_size) std::atomic<state::flag_t> f_ct_;
|
||||||
/// @brief The user data segment.
|
/// \brief The user data segment.
|
||||||
T data_;
|
T data_;
|
||||||
|
|
||||||
/// @brief Disable copy & move.
|
/// \brief Disable copy & move.
|
||||||
element(element const &) = delete;
|
element(element const &) = delete;
|
||||||
element &operator=(element const &) = delete;
|
element &operator=(element const &) = delete;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libconcur/queue.h
|
* \file libconcur/queue.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define concurrent queue.
|
* \brief Define concurrent queue.
|
||||||
* @date 2022-11-19
|
* \date 2022-11-19
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/byte.h
|
* \file libimp/byte.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the byte type.
|
* \brief Define the byte type.
|
||||||
* @date 2022-11-12
|
* \date 2022-11-12
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -37,8 +37,8 @@ using is_not_byte =
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A distinct type that implements the concept of byte as specified in the C++ language definition.
|
* \brief A distinct type that implements the concept of byte as specified in the C++ language definition.
|
||||||
* @see https://en.cppreference.com/w/cpp/types/byte
|
* \see https://en.cppreference.com/w/cpp/types/byte
|
||||||
*/
|
*/
|
||||||
class byte {
|
class byte {
|
||||||
std::uint8_t bits_;
|
std::uint8_t bits_;
|
||||||
@ -63,8 +63,8 @@ public:
|
|||||||
|
|
||||||
#ifdef LIBIMP_CPP_LIB_BYTE_
|
#ifdef LIBIMP_CPP_LIB_BYTE_
|
||||||
explicit constexpr operator std::byte() const noexcept {
|
explicit constexpr operator std::byte() const noexcept {
|
||||||
/// @brief C++17 relaxed enum class initialization rules.
|
/// \brief C++17 relaxed enum class initialization rules.
|
||||||
/// @see https://en.cppreference.com/w/cpp/language/enum#enum_relaxed_init_cpp17
|
/// \see https://en.cppreference.com/w/cpp/language/enum#enum_relaxed_init_cpp17
|
||||||
return std::byte{bits_};
|
return std::byte{bits_};
|
||||||
}
|
}
|
||||||
#endif // LIBIMP_CPP_LIB_BYTE_
|
#endif // LIBIMP_CPP_LIB_BYTE_
|
||||||
@ -79,7 +79,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Non-member functions.
|
* \brief Non-member functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename T, typename = detail::is_integral<T>>
|
template <typename T, typename = detail::is_integral<T>>
|
||||||
@ -87,7 +87,7 @@ constexpr T to_integer(byte b) noexcept {
|
|||||||
return T(b);
|
return T(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief std::operator<<, operator>>
|
/// \brief std::operator<<, operator>>
|
||||||
|
|
||||||
template <typename T, typename = detail::is_integral<T>>
|
template <typename T, typename = detail::is_integral<T>>
|
||||||
constexpr byte operator<<(byte b, T shift) noexcept {
|
constexpr byte operator<<(byte b, T shift) noexcept {
|
||||||
@ -99,7 +99,7 @@ constexpr byte operator>>(byte b, T shift) noexcept {
|
|||||||
return byte(to_integer<unsigned>(b) >> shift);
|
return byte(to_integer<unsigned>(b) >> shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief std::operator<<=, operator>>=
|
/// \brief std::operator<<=, operator>>=
|
||||||
|
|
||||||
template <typename T, typename = detail::is_integral<T>>
|
template <typename T, typename = detail::is_integral<T>>
|
||||||
constexpr byte &operator<<=(byte &b, T shift) noexcept {
|
constexpr byte &operator<<=(byte &b, T shift) noexcept {
|
||||||
@ -111,20 +111,20 @@ constexpr byte &operator>>=(byte &b, T shift) noexcept {
|
|||||||
return b = b >> shift;
|
return b = b >> shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief std::operator|, operator&, operator^, operator~
|
/// \brief std::operator|, operator&, operator^, operator~
|
||||||
|
|
||||||
constexpr byte operator|(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) | to_integer<unsigned>(r)); }
|
constexpr byte operator|(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) | to_integer<unsigned>(r)); }
|
||||||
constexpr byte operator&(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) & to_integer<unsigned>(r)); }
|
constexpr byte operator&(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) & to_integer<unsigned>(r)); }
|
||||||
constexpr byte operator^(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) ^ to_integer<unsigned>(r)); }
|
constexpr byte operator^(byte l, byte r) noexcept { return byte(to_integer<unsigned>(l) ^ to_integer<unsigned>(r)); }
|
||||||
constexpr byte operator~(byte b) noexcept { return byte(~to_integer<unsigned>(b)); }
|
constexpr byte operator~(byte b) noexcept { return byte(~to_integer<unsigned>(b)); }
|
||||||
|
|
||||||
/// @brief std::operator|=, operator&=, operator^=
|
/// \brief std::operator|=, operator&=, operator^=
|
||||||
|
|
||||||
constexpr byte &operator|=(byte &l, byte r) noexcept { return l = l | r; }
|
constexpr byte &operator|=(byte &l, byte r) noexcept { return l = l | r; }
|
||||||
constexpr byte &operator&=(byte &l, byte r) noexcept { return l = l & r; }
|
constexpr byte &operator&=(byte &l, byte r) noexcept { return l = l & r; }
|
||||||
constexpr byte &operator^=(byte &l, byte r) noexcept { return l = l ^ r; }
|
constexpr byte &operator^=(byte &l, byte r) noexcept { return l = l ^ r; }
|
||||||
|
|
||||||
/// @brief Cast pointer to byte*.
|
/// \brief Cast pointer to byte*.
|
||||||
|
|
||||||
template <typename T, typename = detail::is_not_byte<T>>
|
template <typename T, typename = detail::is_not_byte<T>>
|
||||||
byte *byte_cast(T *p) noexcept {
|
byte *byte_cast(T *p) noexcept {
|
||||||
@ -136,7 +136,7 @@ byte const *byte_cast(T const *p) noexcept {
|
|||||||
return reinterpret_cast<byte const *>(p);
|
return reinterpret_cast<byte const *>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Cast byte* to a pointer of another type.
|
/// \brief Cast byte* to a pointer of another type.
|
||||||
|
|
||||||
template <typename T, typename = detail::is_not_byte<T>>
|
template <typename T, typename = detail::is_not_byte<T>>
|
||||||
T *byte_cast(byte *p) noexcept {
|
T *byte_cast(byte *p) noexcept {
|
||||||
@ -155,8 +155,8 @@ U *byte_cast(byte const *p) noexcept {
|
|||||||
return reinterpret_cast<U *>(p);
|
return reinterpret_cast<U *>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Converts a span into a view of its underlying bytes.
|
/// \brief Converts a span into a view of its underlying bytes.
|
||||||
/// @see https://en.cppreference.com/w/cpp/container/span/as_bytes
|
/// \see https://en.cppreference.com/w/cpp/container/span/as_bytes
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
typename Byte = typename std::conditional<std::is_const<T>::value, byte const, byte>::type>
|
typename Byte = typename std::conditional<std::is_const<T>::value, byte const, byte>::type>
|
||||||
@ -164,7 +164,7 @@ auto as_bytes(span<T> s) noexcept -> span<Byte> {
|
|||||||
return {byte_cast(s.data()), s.size_bytes()};
|
return {byte_cast(s.data()), s.size_bytes()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom defined fmt_to method for imp::fmt
|
/// \brief Custom defined fmt_to method for imp::fmt
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, ::LIBIMP::byte b) {
|
inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, ::LIBIMP::byte b) {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/codecvt.h
|
* \file libimp/codecvt.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Character set conversion interface
|
* \brief Character set conversion interface
|
||||||
* @date 2022-08-07
|
* \date 2022-08-07
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,10 +15,10 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The transform between UTF-8/16/32
|
* \brief The transform between UTF-8/16/32
|
||||||
*
|
*
|
||||||
* @param des The target string pointer can be nullptr
|
* \param des The target string pointer can be nullptr
|
||||||
* @param dlen The target string length can be 0
|
* \param dlen The target string length can be 0
|
||||||
*/
|
*/
|
||||||
template <typename CharT, typename CharU>
|
template <typename CharT, typename CharU>
|
||||||
LIBIMP_EXPORT std::size_t cvt_cstr(CharT const *src, std::size_t slen, CharU *des, std::size_t dlen) noexcept;
|
LIBIMP_EXPORT std::size_t cvt_cstr(CharT const *src, std::size_t slen, CharU *des, std::size_t dlen) noexcept;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/construct.h
|
* \file libimp/construct.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Construct an object from a memory buffer
|
* \brief Construct an object from a memory buffer
|
||||||
* @date 2022-02-27
|
* \date 2022-02-27
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -18,8 +18,8 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates an object at a given address, like 'construct_at' in c++20
|
* \brief Creates an object at a given address, like 'construct_at' in c++20
|
||||||
* @see https://en.cppreference.com/w/cpp/memory/construct_at
|
* \see https://en.cppreference.com/w/cpp/memory/construct_at
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename T, typename... A>
|
template <typename T, typename... A>
|
||||||
@ -39,8 +39,8 @@ auto construct(void *p, A &&... args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroys an object at a given address, like 'destroy_at' in c++17
|
* \brief Destroys an object at a given address, like 'destroy_at' in c++17
|
||||||
* @see https://en.cppreference.com/w/cpp/memory/destroy_at
|
* \see https://en.cppreference.com/w/cpp/memory/destroy_at
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/countof.h
|
* \file libimp/countof.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Returns the size of the given range
|
* \brief Returns the size of the given range
|
||||||
* @date 2022-03-01
|
* \date 2022-03-01
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://en.cppreference.com/w/cpp/iterator/size
|
* \see https://en.cppreference.com/w/cpp/iterator/size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace detail_countof {
|
namespace detail_countof {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/def.h
|
* \file libimp/def.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the trivial configuration information.
|
* \brief Define the trivial configuration information.
|
||||||
* @date 2022-04-23
|
* \date 2022-04-23
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,6 +15,6 @@
|
|||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief Constants.
|
/// \brief Constants.
|
||||||
|
|
||||||
LIBIMP_NAMESPACE_END_
|
LIBIMP_NAMESPACE_END_
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/detect_plat.h
|
* \file libimp/detect_plat.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define platform detection related interfaces.
|
* \brief Define platform detection related interfaces.
|
||||||
* @date 2022-02-27
|
* \date 2022-02-27
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/// @brief OS check.
|
/// \brief OS check.
|
||||||
|
|
||||||
#if defined(WINCE) || defined(_WIN32_WCE)
|
#if defined(WINCE) || defined(_WIN32_WCE)
|
||||||
# define LIBIMP_OS_WINCE
|
# define LIBIMP_OS_WINCE
|
||||||
@ -35,7 +35,7 @@
|
|||||||
# define LIBIMP_OS_WIN
|
# define LIBIMP_OS_WIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Compiler check.
|
/// \brief Compiler check.
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# define LIBIMP_CC_MSVC _MSC_VER
|
# define LIBIMP_CC_MSVC _MSC_VER
|
||||||
@ -48,8 +48,8 @@
|
|||||||
# error "This compiler is unsupported."
|
# error "This compiler is unsupported."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Instruction set.
|
/// \brief Instruction set.
|
||||||
/// @see https://sourceforge.net/p/predef/wiki/Architectures/
|
/// \see https://sourceforge.net/p/predef/wiki/Architectures/
|
||||||
|
|
||||||
#if defined(_M_X64) || defined(_M_AMD64) || \
|
#if defined(_M_X64) || defined(_M_AMD64) || \
|
||||||
defined(__x86_64__) || defined(__x86_64) || \
|
defined(__x86_64__) || defined(__x86_64) || \
|
||||||
@ -74,7 +74,7 @@
|
|||||||
# define LIBIMP_INSTR_ARM
|
# define LIBIMP_INSTR_ARM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Byte order.
|
/// \brief Byte order.
|
||||||
|
|
||||||
#if defined(__BYTE_ORDER__)
|
#if defined(__BYTE_ORDER__)
|
||||||
# define LIBIMP_ENDIAN_BIG (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
# define LIBIMP_ENDIAN_BIG (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||||
@ -84,7 +84,7 @@
|
|||||||
# define LIBIMP_ENDIAN_LIT (1)
|
# define LIBIMP_ENDIAN_LIT (1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief C++ version.
|
/// \brief C++ version.
|
||||||
|
|
||||||
#if (__cplusplus >= 202002L) && !defined(LIBIMP_CPP_20)
|
#if (__cplusplus >= 202002L) && !defined(LIBIMP_CPP_20)
|
||||||
# define LIBIMP_CPP_20
|
# define LIBIMP_CPP_20
|
||||||
@ -102,7 +102,7 @@
|
|||||||
# error "This C++ version is unsupported."
|
# error "This C++ version is unsupported."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief C++ attributes.
|
/// \brief C++ attributes.
|
||||||
|
|
||||||
#if defined(__has_cpp_attribute)
|
#if defined(__has_cpp_attribute)
|
||||||
# if __has_cpp_attribute(fallthrough)
|
# if __has_cpp_attribute(fallthrough)
|
||||||
@ -165,7 +165,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(LIBIMP_NODISCARD)
|
#if !defined(LIBIMP_NODISCARD)
|
||||||
/// @see https://stackoverflow.com/questions/4226308/msvc-equivalent-of-attribute-warn-unused-result
|
/// \see https://stackoverflow.com/questions/4226308/msvc-equivalent-of-attribute-warn-unused-result
|
||||||
# if defined(LIBIMP_CC_GNUC) && (LIBIMP_CC_GNUC >= 4)
|
# if defined(LIBIMP_CC_GNUC) && (LIBIMP_CC_GNUC >= 4)
|
||||||
# define LIBIMP_NODISCARD __attribute__((warn_unused_result))
|
# define LIBIMP_NODISCARD __attribute__((warn_unused_result))
|
||||||
# elif defined(LIBIMP_CC_MSVC) && (LIBIMP_CC_MSVC >= 1700)
|
# elif defined(LIBIMP_CC_MSVC) && (LIBIMP_CC_MSVC >= 1700)
|
||||||
@ -175,7 +175,7 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @see https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_exceptions.html
|
/// \see https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_exceptions.html
|
||||||
/// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
/// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||||
/// https://stackoverflow.com/questions/6487013/programmatically-determine-whether-exceptions-are-enabled
|
/// https://stackoverflow.com/questions/6487013/programmatically-determine-whether-exceptions-are-enabled
|
||||||
#if defined(__cpp_exceptions) && __cpp_exceptions || \
|
#if defined(__cpp_exceptions) && __cpp_exceptions || \
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/enum_cast.h
|
* \file libimp/enum_cast.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Returns the underlying type of the given enum
|
* \brief Returns the underlying type of the given enum
|
||||||
* @date 2022-03-01
|
* \date 2022-03-01
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
|
/// \brief Returns after converting the value to the underlying type of E.
|
||||||
|
/// \see https://en.cppreference.com/w/cpp/types/underlying_type
|
||||||
template <typename E>
|
template <typename E>
|
||||||
constexpr auto enum_cast(E e) noexcept {
|
constexpr auto enum_cast(E e) noexcept {
|
||||||
return static_cast<std::underlying_type_t<E>>(e);
|
return static_cast<std::underlying_type_t<E>>(e);
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/error.h
|
* \file libimp/error.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief A platform-dependent error code.
|
* \brief A platform-dependent error code.
|
||||||
* @date 2022-12-18
|
* \date 2022-12-18
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -16,8 +16,8 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Serves as the base class for specific error category types.
|
* \brief Serves as the base class for specific error category types.
|
||||||
* @see https://en.cppreference.com/w/cpp/error/error_category
|
* \see https://en.cppreference.com/w/cpp/error/error_category
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT error_category {
|
class LIBIMP_EXPORT error_category {
|
||||||
public:
|
public:
|
||||||
@ -27,47 +27,47 @@ public:
|
|||||||
constexpr error_category() noexcept = default;
|
constexpr error_category() noexcept = default;
|
||||||
virtual ~error_category() noexcept = default;
|
virtual ~error_category() noexcept = default;
|
||||||
|
|
||||||
/// @brief observer
|
/// \brief observer
|
||||||
virtual std::string name() const = 0;
|
virtual std::string name() const = 0;
|
||||||
virtual std::string message(result_code r) const = 0;
|
virtual std::string message(result_code r) const = 0;
|
||||||
|
|
||||||
/// @brief comparison function
|
/// \brief comparison function
|
||||||
bool operator==(error_category const &rhs) const noexcept;
|
bool operator==(error_category const &rhs) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Identifies the generic error category.
|
* \brief Identifies the generic error category.
|
||||||
* @see https://en.cppreference.com/w/cpp/error/generic_category
|
* \see https://en.cppreference.com/w/cpp/error/generic_category
|
||||||
*/
|
*/
|
||||||
LIBIMP_EXPORT error_category const &generic_category() noexcept;
|
LIBIMP_EXPORT error_category const &generic_category() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The error code object.
|
* \brief The error code object.
|
||||||
* @see https://en.cppreference.com/w/cpp/error/error_code
|
* \see https://en.cppreference.com/w/cpp/error/error_code
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT error_code {
|
class LIBIMP_EXPORT error_code {
|
||||||
result_code r_code_;
|
result_code r_code_;
|
||||||
error_category const *ec_;
|
error_category const *ec_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @brief constructors
|
/// \brief constructors
|
||||||
error_code() noexcept;
|
error_code() noexcept;
|
||||||
error_code(result_code r, error_category const &ec) noexcept;
|
error_code(result_code r, error_category const &ec) noexcept;
|
||||||
|
|
||||||
/// @brief observers
|
/// \brief observers
|
||||||
result_code code() const noexcept;
|
result_code code() const noexcept;
|
||||||
result_type value() const noexcept;
|
result_type value() const noexcept;
|
||||||
error_category const &category() const noexcept;
|
error_category const &category() const noexcept;
|
||||||
std::string message() const;
|
std::string message() const;
|
||||||
explicit operator bool() const noexcept;
|
explicit operator bool() const noexcept;
|
||||||
|
|
||||||
/// @brief comparison functions
|
/// \brief comparison functions
|
||||||
friend LIBIMP_EXPORT bool operator==(error_code const &lhs, error_code const &rhs) noexcept;
|
friend LIBIMP_EXPORT bool operator==(error_code const &lhs, error_code const &rhs) noexcept;
|
||||||
friend LIBIMP_EXPORT bool operator!=(error_code const &lhs, error_code const &rhs) noexcept;
|
friend LIBIMP_EXPORT bool operator!=(error_code const &lhs, error_code const &rhs) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief @brief Custom defined fmt_to method for imp::fmt
|
* \brief @brief Custom defined fmt_to method for imp::fmt
|
||||||
*/
|
*/
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/export.h
|
* \file libimp/export.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the symbol export interfaces
|
* \brief Define the symbol export interfaces
|
||||||
* @date 2022-02-27
|
* \date 2022-02-27
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,10 +15,10 @@
|
|||||||
|
|
||||||
#else // defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
#else // defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Compiler & system detection for LIBIMP_DECL_EXPORT & LIBIMP_DECL_IMPORT.
|
* \brief Compiler & system detection for LIBIMP_DECL_EXPORT & LIBIMP_DECL_IMPORT.
|
||||||
* Not using QtCore cause it shouldn't depend on Qt.
|
* Not using QtCore cause it shouldn't depend on Qt.
|
||||||
*/
|
*/
|
||||||
# if defined(LIBIMP_CC_MSVC) || defined(LIBIMP_OS_WIN)
|
# if defined(LIBIMP_CC_MSVC) || defined(LIBIMP_OS_WIN)
|
||||||
# define LIBIMP_DECL_EXPORT __declspec(dllexport)
|
# define LIBIMP_DECL_EXPORT __declspec(dllexport)
|
||||||
# define LIBIMP_DECL_IMPORT __declspec(dllimport)
|
# define LIBIMP_DECL_IMPORT __declspec(dllimport)
|
||||||
@ -32,9 +32,9 @@
|
|||||||
|
|
||||||
#endif // defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
#endif // defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Define LIBIMP_EXPORT for exporting function & class.
|
* \brief Define LIBIMP_EXPORT for exporting function & class.
|
||||||
*/
|
*/
|
||||||
#ifndef LIBIMP_EXPORT
|
#ifndef LIBIMP_EXPORT
|
||||||
# if defined(LIBIMP_LIBRARY_SHARED_BUILDING__)
|
# if defined(LIBIMP_LIBRARY_SHARED_BUILDING__)
|
||||||
# define LIBIMP_EXPORT LIBIMP_DECL_EXPORT
|
# define LIBIMP_EXPORT LIBIMP_DECL_EXPORT
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/fmt.h
|
* \file libimp/fmt.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief String formatting.
|
* \brief String formatting.
|
||||||
* @date 2022-11-26
|
* \date 2022-11-26
|
||||||
*
|
*
|
||||||
* @remarks The current performance is not high,
|
* \remarks The current performance is not high,
|
||||||
* because I use std::sprintf directly for formatting for convenience.
|
* because I use std::sprintf directly for formatting for convenience.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -25,7 +25,7 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The format string reference wrapper.
|
* \brief The format string reference wrapper.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct fmt_ref {
|
struct fmt_ref {
|
||||||
@ -34,12 +34,12 @@ struct fmt_ref {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Conversion specifiers.
|
* \brief Conversion specifiers.
|
||||||
*
|
*
|
||||||
* @remarks Just like printf, the format string is of the form
|
* \remarks Just like printf, the format string is of the form
|
||||||
* [flags][field_width][.precision][conversion_character]
|
* [flags][field_width][.precision][conversion_character]
|
||||||
*
|
*
|
||||||
* @see http://personal.ee.surrey.ac.uk/Personal/R.Bowden/C/printf.html
|
* \see http://personal.ee.surrey.ac.uk/Personal/R.Bowden/C/printf.html
|
||||||
*/
|
*/
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
auto spec(char const (&fstr)[N]) noexcept {
|
auto spec(char const (&fstr)[N]) noexcept {
|
||||||
@ -50,10 +50,10 @@ auto spec(char const (&fstr)[N]) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief String formatting function.
|
* \brief String formatting function.
|
||||||
*
|
*
|
||||||
* @param args arguments that support the fmt output
|
* \param args arguments that support the fmt output
|
||||||
* @return an empty string if the fmt output fails
|
* \return an empty string if the fmt output fails
|
||||||
*/
|
*/
|
||||||
template <typename... A>
|
template <typename... A>
|
||||||
LIBIMP_NODISCARD std::string fmt(A &&...args) {
|
LIBIMP_NODISCARD std::string fmt(A &&...args) {
|
||||||
@ -65,13 +65,13 @@ LIBIMP_NODISCARD std::string fmt(A &&...args) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief String types.
|
/// \brief String types.
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char const * a) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char const * a) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, std::string const &a) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, std::string const &a) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char const * a, span<char const> fstr) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char const * a, span<char const> fstr) noexcept;
|
||||||
inline bool to_string(fmt_context &ctx, std::string const &a, span<char const> fstr) noexcept { return to_string(ctx, a.c_str(), fstr); }
|
inline bool to_string(fmt_context &ctx, std::string const &a, span<char const> fstr) noexcept { return to_string(ctx, a.c_str(), fstr); }
|
||||||
|
|
||||||
/// @brief Character to string conversion.
|
/// \brief Character to string conversion.
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char a) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char a) noexcept;
|
||||||
#if defined(LIBIMP_CPP_20)
|
#if defined(LIBIMP_CPP_20)
|
||||||
inline bool to_string(fmt_context &ctx, char8_t a) noexcept { return to_string(ctx, (char)a); }
|
inline bool to_string(fmt_context &ctx, char8_t a) noexcept { return to_string(ctx, (char)a); }
|
||||||
@ -80,7 +80,7 @@ LIBIMP_EXPORT bool to_string(fmt_context &ctx, wchar_t a) noexcept;
|
|||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char16_t a) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char16_t a) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char32_t a) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, char32_t a) noexcept;
|
||||||
|
|
||||||
/// @brief Conversion of numeric types to strings.
|
/// \brief Conversion of numeric types to strings.
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, signed short a, span<char const> fstr = {}) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, signed short a, span<char const> fstr = {}) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, unsigned short a, span<char const> fstr = {}) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, unsigned short a, span<char const> fstr = {}) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, signed int a, span<char const> fstr = {}) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, signed int a, span<char const> fstr = {}) noexcept;
|
||||||
@ -92,29 +92,29 @@ LIBIMP_EXPORT bool to_string(fmt_context &ctx, unsigned long long a, span<char c
|
|||||||
inline bool to_string(fmt_context &ctx, signed char a, span<char const> fstr = {}) noexcept { return to_string(ctx, (int)a, fstr); }
|
inline bool to_string(fmt_context &ctx, signed char a, span<char const> fstr = {}) noexcept { return to_string(ctx, (int)a, fstr); }
|
||||||
inline bool to_string(fmt_context &ctx, unsigned char a, span<char const> fstr = {}) noexcept { return to_string(ctx, (unsigned)a, fstr); }
|
inline bool to_string(fmt_context &ctx, unsigned char a, span<char const> fstr = {}) noexcept { return to_string(ctx, (unsigned)a, fstr); }
|
||||||
|
|
||||||
/// @brief Conversion of floating point type to strings.
|
/// \brief Conversion of floating point type to strings.
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, double a, span<char const> fstr = {}) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, double a, span<char const> fstr = {}) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, long double a, span<char const> fstr = {}) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, long double a, span<char const> fstr = {}) noexcept;
|
||||||
inline bool to_string(fmt_context &ctx, float a, span<char const> fstr = {}) noexcept { return to_string(ctx, (double)a, fstr); }
|
inline bool to_string(fmt_context &ctx, float a, span<char const> fstr = {}) noexcept { return to_string(ctx, (double)a, fstr); }
|
||||||
|
|
||||||
/// @brief Pointer.
|
/// \brief Pointer.
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, std::nullptr_t) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, std::nullptr_t) noexcept;
|
||||||
template <typename T,
|
template <typename T,
|
||||||
typename = std::enable_if_t<std::is_same<T, void>::value>>
|
typename = std::enable_if_t<std::is_same<T, void>::value>>
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, T const volatile *a) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, T const volatile *a) noexcept;
|
||||||
|
|
||||||
/// @brief Date and time.
|
/// \brief Date and time.
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, std::tm const &a, span<char const> fstr = {}) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, std::tm const &a, span<char const> fstr = {}) noexcept;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert std::time_t to std::string.
|
* \brief Convert std::time_t to std::string.
|
||||||
* @return an empty string if the conversion fails
|
* \return an empty string if the conversion fails
|
||||||
*/
|
*/
|
||||||
inline bool time_to_string(fmt_context &ctx, std::time_t tt, span<char const> fstr) noexcept {
|
inline bool time_to_string(fmt_context &ctx, std::time_t tt, span<char const> fstr) noexcept {
|
||||||
#if defined(LIBIMP_CC_MSVC)
|
#if defined(LIBIMP_CC_MSVC)
|
||||||
/// @see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s
|
/// \see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s
|
||||||
std::tm tm {};
|
std::tm tm {};
|
||||||
if (::localtime_s(&tm, &tt) != 0) {
|
if (::localtime_s(&tm, &tt) != 0) {
|
||||||
return {};
|
return {};
|
||||||
@ -133,7 +133,7 @@ bool to_string(fmt_context &ctx, std::chrono::time_point<Clock, Duration> const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Predefined fmt_to method
|
* \brief Predefined fmt_to method
|
||||||
*/
|
*/
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/fmt_cpo.h
|
* \file libimp/fmt_cpo.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief String formatting CPO.
|
* \brief String formatting CPO.
|
||||||
* @date 2022-11-28
|
* \date 2022-11-28
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The context of fmt.
|
* \brief The context of fmt.
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT fmt_context {
|
class LIBIMP_EXPORT fmt_context {
|
||||||
std::string &joined_;
|
std::string &joined_;
|
||||||
@ -36,7 +36,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Supports custom fmt_to methods for imp::fmt.
|
* \brief Supports custom fmt_to methods for imp::fmt.
|
||||||
*/
|
*/
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/generic.h
|
* \file libimp/generic.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Tools for generic programming.
|
* \brief Tools for generic programming.
|
||||||
* @date 2022-03-01
|
* \date 2022-03-01
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -14,15 +14,15 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Utility metafunction that maps a sequence of any types to the type void
|
* \brief Utility metafunction that maps a sequence of any types to the type void
|
||||||
* @see https://en.cppreference.com/w/cpp/types/void_t
|
* \see https://en.cppreference.com/w/cpp/types/void_t
|
||||||
*/
|
*/
|
||||||
template <typename...>
|
template <typename...>
|
||||||
using void_t = void;
|
using void_t = void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A general pattern for supporting customisable functions
|
* \brief A general pattern for supporting customisable functions
|
||||||
* @see https://www.open-std.org/jtc1/sc22/WG21/docs/papers/2019/p1895r0.pdf
|
* \see https://www.open-std.org/jtc1/sc22/WG21/docs/papers/2019/p1895r0.pdf
|
||||||
*/
|
*/
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@ -42,8 +42,8 @@ struct tag_invoke_t {
|
|||||||
constexpr detail::tag_invoke_t tag_invoke {};
|
constexpr detail::tag_invoke_t tag_invoke {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Circumventing forwarding reference may override copy and move constructs.
|
* \brief Circumventing forwarding reference may override copy and move constructs.
|
||||||
* @see https://mpark.github.io/programming/2014/06/07/beware-of-perfect-forwarding-constructors/
|
* \see https://mpark.github.io/programming/2014/06/07/beware-of-perfect-forwarding-constructors/
|
||||||
*/
|
*/
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/horrible_cast.h
|
* \file libimp/horrible_cast.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @date 2022-04-17
|
* \date 2022-04-17
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/log.h
|
* \file libimp/log.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Simple log output component.
|
* \brief Simple log output component.
|
||||||
* @date 2022-05-22
|
* \date 2022-05-22
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ struct context {
|
|||||||
LIBIMP_EXPORT std::string to_string(context &&) noexcept;
|
LIBIMP_EXPORT std::string to_string(context &&) noexcept;
|
||||||
LIBIMP_EXPORT bool to_string(fmt_context &ctx, context &&) noexcept;
|
LIBIMP_EXPORT bool to_string(fmt_context &ctx, context &&) noexcept;
|
||||||
|
|
||||||
/// @brief Custom defined fmt_to method for imp::fmt
|
/// \brief Custom defined fmt_to method for imp::fmt
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, context &&arg) noexcept {
|
bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, context &&arg) noexcept {
|
||||||
return ::LIBIMP::log::to_string(ctx, std::move(arg));
|
return ::LIBIMP::log::to_string(ctx, std::move(arg));
|
||||||
@ -121,7 +121,7 @@ public:
|
|||||||
printer() noexcept = default;
|
printer() noexcept = default;
|
||||||
|
|
||||||
template <typename T,
|
template <typename T,
|
||||||
/// @remark generic constructor may shadow the default copy constructor
|
/// \remark generic constructor may shadow the default copy constructor
|
||||||
typename = std::enable_if_t<!std::is_same<printer, T>::value>>
|
typename = std::enable_if_t<!std::is_same<printer, T>::value>>
|
||||||
printer(T &p) noexcept
|
printer(T &p) noexcept
|
||||||
: objp_ (static_cast<void *>(&p))
|
: objp_ (static_cast<void *>(&p))
|
||||||
@ -131,17 +131,17 @@ public:
|
|||||||
void output(context) noexcept;
|
void output(context) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Standard console output.
|
/// \brief Standard console output.
|
||||||
class LIBIMP_EXPORT std_t {
|
class LIBIMP_EXPORT std_t {
|
||||||
public:
|
public:
|
||||||
void output(log::level, std::string &&) noexcept;
|
void output(log::level, std::string &&) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Standard console output object.
|
/// \brief Standard console output object.
|
||||||
LIBIMP_EXPORT extern std_t std_out;
|
LIBIMP_EXPORT extern std_t std_out;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Log information grips.
|
* \brief Log information grips.
|
||||||
*/
|
*/
|
||||||
class grip {
|
class grip {
|
||||||
printer printer_;
|
printer printer_;
|
||||||
@ -160,7 +160,7 @@ class grip {
|
|||||||
fmt(std::forward<A>(args)...),
|
fmt(std::forward<A>(args)...),
|
||||||
};
|
};
|
||||||
} LIBIMP_CATCH(std::exception const &e) {
|
} LIBIMP_CATCH(std::exception const &e) {
|
||||||
/// @remark [TBD] std::string constructor may throw an exception
|
/// \remark [TBD] std::string constructor may throw an exception
|
||||||
ctx = {
|
ctx = {
|
||||||
level::failed, std::chrono::system_clock::now(), func_, e.what(),
|
level::failed, std::chrono::system_clock::now(), func_, e.what(),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/nameof.h
|
* \file libimp/nameof.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Gets the name string of a type.
|
* \brief Gets the name string of a type.
|
||||||
* @date 2022-11-26
|
* \date 2022-11-26
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -16,20 +16,20 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The conventional way to obtain demangled symbol name.
|
* \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
|
* \see https://www.boost.org/doc/libs/1_80_0/libs/core/doc/html/core/demangle.html
|
||||||
*
|
*
|
||||||
* @param name the mangled name
|
* \param name the mangled name
|
||||||
* @return std::string a human-readable demangled type name
|
* \return std::string a human-readable demangled type name
|
||||||
*/
|
*/
|
||||||
std::string demangle(span<char const> name) noexcept;
|
std::string demangle(span<char const> name) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns an implementation defined string containing the name of the type.
|
* \brief Returns an implementation defined string containing the name of the type.
|
||||||
* @see https://en.cppreference.com/w/cpp/types/type_info/name
|
* \see https://en.cppreference.com/w/cpp/types/type_info/name
|
||||||
*
|
*
|
||||||
* @tparam T a type
|
* \tparam T a type
|
||||||
* @return std::string a human-readable demangled type name
|
* \return std::string a human-readable demangled type name
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::string nameof() noexcept {
|
std::string nameof() noexcept {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/pimpl.h
|
* \file libimp/pimpl.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Pointer To Implementation (pImpl) idiom
|
* \brief Pointer To Implementation (pImpl) idiom
|
||||||
* @date 2022-02-27
|
* \date 2022-02-27
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/result.h
|
* \file libimp/result.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the return value type with a status code
|
* \brief Define the return value type with a status code
|
||||||
* @date 2022-04-17
|
* \date 2022-04-17
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "libimp/def.h"
|
#include "libimp/def.h"
|
||||||
@ -18,10 +19,10 @@
|
|||||||
|
|
||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
using result_type = std::uint64_t;
|
using result_type = std::tuple<std::uint64_t, bool>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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.
|
||||||
*/
|
*/
|
||||||
@ -62,7 +63,7 @@ namespace detail_result {
|
|||||||
|
|
||||||
template <typename T>
|
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>> {
|
||||||
/// @brief Custom initialization.
|
/// \brief Custom initialization.
|
||||||
constexpr static void init_code(result_code &code) noexcept {
|
constexpr static void init_code(result_code &code) noexcept {
|
||||||
code = {};
|
code = {};
|
||||||
}
|
}
|
||||||
@ -73,17 +74,17 @@ struct default_traits<T, std::enable_if_t<std::is_integral<T>::value>> {
|
|||||||
init_code(code, true, value);
|
init_code(code, true, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom default value.
|
/// \brief Custom default value.
|
||||||
constexpr static T default_value() noexcept {
|
constexpr static T default_value() noexcept {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom type conversions.
|
/// \brief Custom type conversions.
|
||||||
constexpr static T cast_from_code(result_code code) noexcept {
|
constexpr static T cast_from_code(result_code code) noexcept {
|
||||||
return static_cast<T>(code.value());
|
return static_cast<T>(code.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom formatted output.
|
/// \brief Custom formatted output.
|
||||||
static std::string format(result<T> const &r) noexcept {
|
static std::string format(result<T> const &r) noexcept {
|
||||||
return fmt(*r);
|
return fmt(*r);
|
||||||
}
|
}
|
||||||
@ -91,7 +92,7 @@ struct default_traits<T, std::enable_if_t<std::is_integral<T>::value>> {
|
|||||||
|
|
||||||
template <typename T>
|
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>> {
|
||||||
/// @brief Custom initialization.
|
/// \brief Custom initialization.
|
||||||
constexpr static void init_code(result_code &code, T value = default_value()) noexcept {
|
constexpr static void init_code(result_code &code, T value = default_value()) noexcept {
|
||||||
code = {default_value() != value, reinterpret_cast<result_type>(value)};
|
code = {default_value() != value, reinterpret_cast<result_type>(value)};
|
||||||
}
|
}
|
||||||
@ -102,17 +103,17 @@ struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> {
|
|||||||
code = {false, r};
|
code = {false, r};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom default value.
|
/// \brief Custom default value.
|
||||||
constexpr static T default_value() noexcept {
|
constexpr static T default_value() noexcept {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom type conversions.
|
/// \brief Custom type conversions.
|
||||||
constexpr static T cast_from_code(result_code code) noexcept {
|
constexpr static T cast_from_code(result_code code) noexcept {
|
||||||
return code.ok() ? reinterpret_cast<T>(code.value()) : default_value();
|
return code.ok() ? reinterpret_cast<T>(code.value()) : default_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Custom formatted output.
|
/// \brief Custom formatted output.
|
||||||
static std::string format(result<T> const &r) noexcept {
|
static std::string format(result<T> const &r) noexcept {
|
||||||
if LIBIMP_LIKELY(r) {
|
if LIBIMP_LIKELY(r) {
|
||||||
return fmt(static_cast<void *>(*r));
|
return fmt(static_cast<void *>(*r));
|
||||||
@ -126,7 +127,7 @@ struct default_traits<T, std::enable_if_t<std::is_pointer<T>::value>> {
|
|||||||
template <typename T, typename TypeTraits>
|
template <typename T, typename TypeTraits>
|
||||||
class result : public TypeTraits {
|
class result : public TypeTraits {
|
||||||
|
|
||||||
/// @brief Internal data is stored using result_code.
|
/// \brief Internal data is stored using result_code.
|
||||||
result_code code_;
|
result_code code_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -156,7 +157,7 @@ public:
|
|||||||
friend bool operator!=(result const &lhs, result const &rhs) noexcept { return lhs.code_ != rhs.code_; }
|
friend bool operator!=(result const &lhs, result const &rhs) noexcept { return lhs.code_ != rhs.code_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Custom defined fmt_to method for imp::fmt
|
/// \brief Custom defined fmt_to method for imp::fmt
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, result_code r) {
|
inline bool tag_invoke(decltype(::LIBIMP::fmt_to), fmt_context &ctx, result_code r) {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/span.h
|
* \file libimp/span.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Describes an object that can refer to a contiguous sequence of objects
|
* \brief Describes an object that can refer to a contiguous sequence of objects
|
||||||
* @date 2022-10-16
|
* \date 2022-10-16
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -28,7 +28,7 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/// @brief Helper trait for span.
|
/// \brief Helper trait for span.
|
||||||
|
|
||||||
template <typename From, typename To>
|
template <typename From, typename To>
|
||||||
using array_convertible = std::is_convertible<From(*)[], To(*)[]>;
|
using array_convertible = std::is_convertible<From(*)[], To(*)[]>;
|
||||||
@ -56,9 +56,9 @@ using is_sized_sentinel_for =
|
|||||||
typename std::enable_if<std::is_convertible<decltype(std::declval<S>() - std::declval<I>()),
|
typename std::enable_if<std::is_convertible<decltype(std::declval<S>() - std::declval<I>()),
|
||||||
std::ptrdiff_t>::value>::type;
|
std::ptrdiff_t>::value>::type;
|
||||||
|
|
||||||
/// @brief Obtain the address represented by p
|
/// \brief Obtain the address represented by p
|
||||||
/// without forming a reference to the object pointed to by p.
|
/// without forming a reference to the object pointed to by p.
|
||||||
/// @see https://en.cppreference.com/w/cpp/memory/to_address
|
/// \see https://en.cppreference.com/w/cpp/memory/to_address
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T *to_address(T *ptr) noexcept {
|
constexpr T *to_address(T *ptr) noexcept {
|
||||||
@ -76,8 +76,8 @@ constexpr auto to_address(T const &ptr)
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A simple implementation of span.
|
* \brief A simple implementation of span.
|
||||||
* @see https://en.cppreference.com/w/cpp/container/span
|
* \see https://en.cppreference.com/w/cpp/container/span
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class span {
|
class span {
|
||||||
@ -205,7 +205,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Support for span equals comparison.
|
/// \brief Support for span equals comparison.
|
||||||
|
|
||||||
template <typename T, typename U,
|
template <typename T, typename U,
|
||||||
typename = decltype(std::declval<T>() == std::declval<U>())>
|
typename = decltype(std::declval<T>() == std::declval<U>())>
|
||||||
@ -219,9 +219,9 @@ bool operator==(span<T> a, span<U> b) noexcept {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Constructs an object of type T and wraps it in a span.
|
/// \brief Constructs an object of type T and wraps it in a span.
|
||||||
/// Before C++17, template argument deduction for class templates was not supported.
|
/// Before C++17, template argument deduction for class templates was not supported.
|
||||||
/// @see https://en.cppreference.com/w/cpp/language/template_argument_deduction
|
/// \see https://en.cppreference.com/w/cpp/language/template_argument_deduction
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto make_span(T *arr, std::size_t count) noexcept -> span<T> {
|
auto make_span(T *arr, std::size_t count) noexcept -> span<T> {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/system.h
|
* \file libimp/system.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Isolation and encapsulation of system APIs
|
* \brief Isolation and encapsulation of system APIs
|
||||||
* @date 2022-08-07
|
* \date 2022-08-07
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -18,30 +18,30 @@ LIBIMP_NAMESPACE_BEG_
|
|||||||
namespace sys {
|
namespace sys {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get/Set the system error number
|
* \brief Get/Set the system error number
|
||||||
*/
|
*/
|
||||||
LIBIMP_EXPORT result_code error_no() noexcept;
|
LIBIMP_EXPORT result_code error_no() noexcept;
|
||||||
LIBIMP_EXPORT void error_no(result_code) noexcept;
|
LIBIMP_EXPORT void error_no(result_code) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a text description of the system error
|
* \brief Gets a text description of the system error
|
||||||
*/
|
*/
|
||||||
LIBIMP_EXPORT std::string error_str(result_code) noexcept;
|
LIBIMP_EXPORT std::string error_str(result_code) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Identifies the operating system error category.
|
* \brief Identifies the operating system error category.
|
||||||
* @see https://en.cppreference.com/w/cpp/error/system_category
|
* \see https://en.cppreference.com/w/cpp/error/system_category
|
||||||
*/
|
*/
|
||||||
LIBIMP_EXPORT error_category const &category() noexcept;
|
LIBIMP_EXPORT error_category const &category() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A platform-dependent error code.
|
* \brief A platform-dependent error code.
|
||||||
* @see https://en.cppreference.com/w/cpp/error/error_code
|
* \see https://en.cppreference.com/w/cpp/error/error_code
|
||||||
*/
|
*/
|
||||||
LIBIMP_EXPORT error_code error() noexcept;
|
LIBIMP_EXPORT error_code error() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get system configuration information at run time
|
* \brief Get system configuration information at run time
|
||||||
*/
|
*/
|
||||||
enum class info : std::int32_t {
|
enum class info : std::int32_t {
|
||||||
page_size,
|
page_size,
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/def.h
|
* \file libipc/def.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the trivial configuration information.
|
* \brief Define the trivial configuration information.
|
||||||
* @date 2022-02-27
|
* \date 2022-02-27
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief Constants.
|
/// \brief Constants.
|
||||||
|
|
||||||
struct prot {
|
struct prot {
|
||||||
using type = std::uint32_t;
|
using type = std::uint32_t;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/shm.h
|
* \file libipc/shm.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the shared memory access interface
|
* \brief Define the shared memory access interface
|
||||||
* @date 2022-04-17
|
* \date 2022-04-17
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -19,32 +19,32 @@ LIBIPC_NAMESPACE_BEG_
|
|||||||
struct shm_handle;
|
struct shm_handle;
|
||||||
using shm_t = shm_handle *;
|
using shm_t = shm_handle *;
|
||||||
|
|
||||||
/// @brief Create a new shared memory handle with a name of the shared memory file.
|
/// \brief Create a new shared memory handle with a name of the shared memory file.
|
||||||
LIBIMP_EXPORT ::LIBIMP::result<shm_t> shm_open(std::string name,
|
LIBIMP_EXPORT ::LIBIMP::result<shm_t> shm_open(std::string name,
|
||||||
std::size_t size = 0,
|
std::size_t size = 0,
|
||||||
mode::type = mode::create | mode::open) noexcept;
|
mode::type = mode::create | mode::open) noexcept;
|
||||||
|
|
||||||
/// @brief Close the shared memory handle.
|
/// \brief Close the shared memory handle.
|
||||||
LIBIMP_EXPORT ::LIBIMP::result_code shm_close(shm_t) noexcept;
|
LIBIMP_EXPORT ::LIBIMP::result_code shm_close(shm_t) noexcept;
|
||||||
|
|
||||||
/// @brief Gets a memory pointer based on the shared memory handle.
|
/// \brief Gets a memory pointer based on the shared memory handle.
|
||||||
/// @return nullptr on failure.
|
/// \return nullptr on failure.
|
||||||
LIBIMP_EXPORT void *shm_get(shm_t) noexcept;
|
LIBIMP_EXPORT void *shm_get(shm_t) noexcept;
|
||||||
|
|
||||||
/// @brief Gets the memory size based on the shared memory handle.
|
/// \brief Gets the memory size based on the shared memory handle.
|
||||||
/// @return 0 on failure.
|
/// \return 0 on failure.
|
||||||
LIBIMP_EXPORT std::size_t shm_size(shm_t) noexcept;
|
LIBIMP_EXPORT std::size_t shm_size(shm_t) noexcept;
|
||||||
|
|
||||||
/// @brief Sets the memory size based on the shared memory handle.
|
/// \brief Sets the memory size based on the shared memory handle.
|
||||||
/// @remark [TBD]
|
/// \remark [TBD]
|
||||||
LIBIMP_EXPORT ::LIBIMP::result_code shm_size(shm_t, std::size_t) noexcept;
|
LIBIMP_EXPORT ::LIBIMP::result_code shm_size(shm_t, std::size_t) noexcept;
|
||||||
|
|
||||||
/// @brief Gets the name of the shared memory file based on the shared memory handle.
|
/// \brief Gets the name of the shared memory file based on the shared memory handle.
|
||||||
/// @return empty string on failure.
|
/// \return empty string on failure.
|
||||||
LIBIMP_EXPORT std::string shm_name(shm_t) noexcept;
|
LIBIMP_EXPORT std::string shm_name(shm_t) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The shared memory object.
|
* \brief The shared memory object.
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT shared_memory {
|
class LIBIMP_EXPORT shared_memory {
|
||||||
shm_t shm_;
|
shm_t shm_;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/spin_lock.h
|
* \file libipc/spin_lock.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define spin locks
|
* \brief Define spin locks
|
||||||
* @date 2022-02-27
|
* \date 2022-02-27
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -18,12 +18,12 @@
|
|||||||
LIBIPC_NAMESPACE_BEG_
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gives hint to processor that improves performance of spin-wait loops.
|
* \brief Gives hint to processor that improves performance of spin-wait loops.
|
||||||
*/
|
*/
|
||||||
LIBIMP_EXPORT void pause() noexcept;
|
LIBIMP_EXPORT void pause() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Yield to other threads
|
* \brief Yield to other threads
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename K>
|
template <typename K>
|
||||||
@ -60,7 +60,7 @@ inline void sleep(K &k) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Basic spin lock
|
* \brief Basic spin lock
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT spin_lock {
|
class LIBIMP_EXPORT spin_lock {
|
||||||
std::atomic<unsigned> lc_ {0};
|
std::atomic<unsigned> lc_ {0};
|
||||||
@ -71,7 +71,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Support for shared mode spin lock
|
* \brief Support for shared mode spin lock
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT rw_lock {
|
class LIBIMP_EXPORT rw_lock {
|
||||||
std::atomic<unsigned> lc_ {0};
|
std::atomic<unsigned> lc_ {0};
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libpmr/allocator.h
|
* \file libpmr/allocator.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief A generic polymorphic memory allocator.
|
* \brief A generic polymorphic memory allocator.
|
||||||
* @date 2022-11-13
|
* \date 2022-11-13
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -19,15 +19,15 @@
|
|||||||
LIBPMR_NAMESPACE_BEG_
|
LIBPMR_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An allocator which exhibits different allocation behavior
|
* \brief An allocator which exhibits different allocation behavior
|
||||||
* depending upon the memory resource from which it is constructed.
|
* depending upon the memory resource from which it is constructed.
|
||||||
*
|
*
|
||||||
* @remarks Unlike std::pmr::polymorphic_allocator, it does not
|
* \remarks Unlike std::pmr::polymorphic_allocator, it does not
|
||||||
* rely on a specific inheritance relationship and only restricts
|
* rely on a specific inheritance relationship and only restricts
|
||||||
* the interface behavior of the incoming memory resource object to
|
* the interface behavior of the incoming memory resource object to
|
||||||
* conform to std::pmr::memory_resource.
|
* conform to std::pmr::memory_resource.
|
||||||
*
|
*
|
||||||
* @see https://en.cppreference.com/w/cpp/memory/memory_resource
|
* \see https://en.cppreference.com/w/cpp/memory/memory_resource
|
||||||
* https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
|
* https://en.cppreference.com/w/cpp/memory/polymorphic_allocator
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT allocator {
|
class LIBIMP_EXPORT allocator {
|
||||||
@ -51,8 +51,8 @@ class LIBIMP_EXPORT allocator {
|
|||||||
class holder_memory_resource;
|
class holder_memory_resource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A memory resource pointer holder class for type erasure.
|
* \brief A memory resource pointer holder class for type erasure.
|
||||||
* @tparam MR memory resource type
|
* \tparam MR memory resource type
|
||||||
*/
|
*/
|
||||||
template <typename MR>
|
template <typename MR>
|
||||||
class holder_memory_resource<MR, is_memory_resource<MR>> : public holder_base {
|
class holder_memory_resource<MR, is_memory_resource<MR>> : public holder_base {
|
||||||
@ -76,8 +76,8 @@ class LIBIMP_EXPORT allocator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An empty holding class used to calculate a reasonable memory size for the holder.
|
* \brief An empty holding class used to calculate a reasonable memory size for the holder.
|
||||||
* @tparam MR cannot be converted to the type of memory resource
|
* \tparam MR cannot be converted to the type of memory resource
|
||||||
*/
|
*/
|
||||||
template <typename MR, typename U>
|
template <typename MR, typename U>
|
||||||
class holder_memory_resource : public holder_null {
|
class holder_memory_resource : public holder_null {
|
||||||
@ -100,8 +100,8 @@ public:
|
|||||||
allocator(allocator &&other) noexcept;
|
allocator(allocator &&other) noexcept;
|
||||||
allocator &operator=(allocator &&other) & noexcept;
|
allocator &operator=(allocator &&other) & noexcept;
|
||||||
|
|
||||||
/// @brief Constructs a allocator from a memory resource pointer
|
/// \brief Constructs a allocator from a memory resource pointer
|
||||||
/// @remark The lifetime of the pointer must be longer than that of allocator.
|
/// The lifetime of the pointer must be longer than that of allocator.
|
||||||
template <typename T, typename = is_memory_resource<T>>
|
template <typename T, typename = is_memory_resource<T>>
|
||||||
allocator(T *p_mr) : allocator() {
|
allocator(T *p_mr) : allocator() {
|
||||||
if (p_mr == nullptr) return;
|
if (p_mr == nullptr) return;
|
||||||
@ -112,7 +112,7 @@ public:
|
|||||||
bool valid() const noexcept;
|
bool valid() const noexcept;
|
||||||
explicit operator bool() const noexcept;
|
explicit operator bool() const noexcept;
|
||||||
|
|
||||||
/// @brief Allocate/deallocate memory.
|
/// \brief Allocate/deallocate memory.
|
||||||
void *alloc(std::size_t s);
|
void *alloc(std::size_t s);
|
||||||
void free (void *p, std::size_t s);
|
void free (void *p, std::size_t s);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libpmr/def.h
|
* \file libpmr/def.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Define the trivial configuration information for memory resources.
|
* \brief Define the trivial configuration information for memory resources.
|
||||||
* @date 2022-11-13
|
* \date 2022-11-13
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -12,6 +12,6 @@
|
|||||||
|
|
||||||
LIBPMR_NAMESPACE_BEG_
|
LIBPMR_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief Constants.
|
/// \brief Constants.
|
||||||
|
|
||||||
LIBPMR_NAMESPACE_END_
|
LIBPMR_NAMESPACE_END_
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @file libpmr/memory_resource.h
|
* \file libpmr/memory_resource.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
* @brief Implement memory allocation strategies that can be used by pmr::allocator.
|
* \brief Implement memory allocation strategies that can be used by pmr::allocator.
|
||||||
* @date 2022-11-13
|
* \date 2022-11-13
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
LIBPMR_NAMESPACE_BEG_
|
LIBPMR_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief Helper trait for memory resource.
|
/// \brief Helper trait for memory resource.
|
||||||
|
|
||||||
template <typename T, typename = void>
|
template <typename T, typename = void>
|
||||||
struct has_allocate : std::false_type {};
|
struct has_allocate : std::false_type {};
|
||||||
@ -40,23 +40,23 @@ using is_memory_resource =
|
|||||||
has_deallocate<T>::value>::type;
|
has_deallocate<T>::value>::type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A memory resource that uses the
|
* \brief A memory resource that uses the
|
||||||
* standard memory allocation and deallocation interface to allocate memory.
|
* standard memory allocation and deallocation interface to allocate memory.
|
||||||
*
|
*
|
||||||
* @see https://en.cppreference.com/w/cpp/memory/new_delete_resource
|
* \see https://en.cppreference.com/w/cpp/memory/new_delete_resource
|
||||||
*/
|
*/
|
||||||
class LIBIMP_EXPORT new_delete_resource {
|
class LIBIMP_EXPORT new_delete_resource {
|
||||||
public:
|
public:
|
||||||
/// @brief Returns a pointer to a new_delete_resource.
|
/// \brief Returns a pointer to a new_delete_resource.
|
||||||
static new_delete_resource *get() noexcept;
|
static new_delete_resource *get() noexcept;
|
||||||
|
|
||||||
/// @brief Allocates storage with a size of at least bytes bytes, aligned to the specified alignment.
|
/// \brief Allocates storage with a size of at least bytes bytes, aligned to the specified alignment.
|
||||||
/// @remark Returns nullptr if storage of the requested size and alignment cannot be obtained.
|
/// \remark Returns nullptr if storage of the requested size and alignment cannot be obtained.
|
||||||
/// @see https://en.cppreference.com/w/cpp/memory/memory_resource/do_allocate
|
/// \see https://en.cppreference.com/w/cpp/memory/memory_resource/do_allocate
|
||||||
void *allocate(std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept;
|
void *allocate(std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept;
|
||||||
|
|
||||||
/// @brief Deallocates the storage pointed to by p.
|
/// \brief Deallocates the storage pointed to by p.
|
||||||
/// @see https://en.cppreference.com/w/cpp/memory/memory_resource/deallocate
|
/// \see https://en.cppreference.com/w/cpp/memory/memory_resource/deallocate
|
||||||
void deallocate(void *p, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept;
|
void deallocate(void *p, std::size_t bytes, std::size_t alignment = alignof(std::max_align_t)) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -15,19 +15,19 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The transform between local-character-set(UTF-8/GBK/...) and UTF-16/32.
|
* \brief The transform between local-character-set(UTF-8/GBK/...) and UTF-16/32.
|
||||||
*
|
*
|
||||||
* Modified from UnicodeConverter.
|
* Modified from UnicodeConverter.
|
||||||
* Copyright (c) 2010. Jianhui Qin (http://blog.csdn.net/jhqin).
|
* Copyright (c) 2010. Jianhui Qin (http://blog.csdn.net/jhqin).
|
||||||
*
|
*
|
||||||
* @remarks codecvt_utf8_utf16/std::wstring_convert is deprecated.
|
* \remarks codecvt_utf8_utf16/std::wstring_convert is deprecated.
|
||||||
* @see https://codingtidbit.com/2020/02/09/c17-codecvt_utf8-is-deprecated/
|
* \see https://codingtidbit.com/2020/02/09/c17-codecvt_utf8-is-deprecated/
|
||||||
* https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement
|
* https://stackoverflow.com/questions/42946335/deprecated-header-codecvt-replacement
|
||||||
* https://en.cppreference.com/w/cpp/locale/codecvt/in
|
* https://en.cppreference.com/w/cpp/locale/codecvt/in
|
||||||
*/
|
*/
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// @brief X-bit unicode transformation format
|
/// \brief X-bit unicode transformation format
|
||||||
enum class ufmt {
|
enum class ufmt {
|
||||||
utf8,
|
utf8,
|
||||||
utf16,
|
utf16,
|
||||||
@ -53,7 +53,7 @@ template <typename T, ufmt Fmt>
|
|||||||
constexpr bool utf_compatible_v = utf_compatible<T, Fmt>::value;
|
constexpr bool utf_compatible_v = utf_compatible<T, Fmt>::value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-32 --> UTF-8
|
* \brief UTF-32 --> UTF-8
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_char(T src, U* des, std::size_t dlen) noexcept
|
auto cvt_char(T src, U* des, std::size_t dlen) noexcept
|
||||||
@ -91,7 +91,7 @@ auto cvt_char(T src, U* des, std::size_t dlen) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-8 --> UTF-32
|
* \brief UTF-8 --> UTF-32
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_char(T const *src, std::size_t slen, U &des) noexcept
|
auto cvt_char(T const *src, std::size_t slen, U &des) noexcept
|
||||||
@ -138,7 +138,7 @@ auto cvt_char(T const *src, std::size_t slen, U &des) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-32 --> UTF-16
|
* \brief UTF-32 --> UTF-16
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_char(T src, U *des, std::size_t dlen) noexcept
|
auto cvt_char(T src, U *des, std::size_t dlen) noexcept
|
||||||
@ -162,7 +162,7 @@ auto cvt_char(T src, U *des, std::size_t dlen) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-16 --> UTF-32
|
* \brief UTF-16 --> UTF-32
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_char(T const *src, std::size_t slen, U &des)
|
auto cvt_char(T const *src, std::size_t slen, U &des)
|
||||||
@ -188,7 +188,7 @@ auto cvt_char(T const *src, std::size_t slen, U &des)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-16 --> UTF-8
|
* \brief UTF-16 --> UTF-8
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_char(T src, U *des, std::size_t dlen) noexcept
|
auto cvt_char(T src, U *des, std::size_t dlen) noexcept
|
||||||
@ -202,7 +202,7 @@ auto cvt_char(T src, U *des, std::size_t dlen) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-8 --> UTF-16
|
* \brief UTF-8 --> UTF-16
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_char(T const *src, std::size_t slen, U &des)
|
auto cvt_char(T const *src, std::size_t slen, U &des)
|
||||||
@ -218,7 +218,7 @@ auto cvt_char(T const *src, std::size_t slen, U &des)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-32 string --> UTF-8/16 string
|
* \brief UTF-32 string --> UTF-8/16 string
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noexcept
|
auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noexcept
|
||||||
@ -247,7 +247,7 @@ auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noex
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-8/16 string --> UTF-32 string
|
* \brief UTF-8/16 string --> UTF-32 string
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noexcept
|
auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noexcept
|
||||||
@ -276,7 +276,7 @@ auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noex
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief UTF-8/16 string --> UTF-16/8 string
|
* \brief UTF-8/16 string --> UTF-16/8 string
|
||||||
*/
|
*/
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noexcept
|
auto cvt_cstr_utf(T const *src, std::size_t slen, U *des, std::size_t dlen) noexcept
|
||||||
|
|||||||
@ -14,8 +14,8 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Format conversions helpers.
|
* \brief Format conversions helpers.
|
||||||
* @see http://personal.ee.surrey.ac.uk/Personal/R.Bowden/C/printf.html
|
* \see http://personal.ee.surrey.ac.uk/Personal/R.Bowden/C/printf.html
|
||||||
* https://en.cppreference.com/w/cpp/io/c/fprintf
|
* https://en.cppreference.com/w/cpp/io/c/fprintf
|
||||||
*/
|
*/
|
||||||
namespace {
|
namespace {
|
||||||
@ -149,7 +149,7 @@ span<char> fmt_context_sbuf() noexcept {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/// @brief The context of fmt.
|
/// \brief The context of fmt.
|
||||||
|
|
||||||
fmt_context::fmt_context(std::string &j) noexcept
|
fmt_context::fmt_context(std::string &j) noexcept
|
||||||
: joined_(j)
|
: joined_(j)
|
||||||
@ -189,7 +189,7 @@ span<char> fmt_context::buffer(std::size_t sz) noexcept {
|
|||||||
if ((offset_ + sz) < sbuf.size()) {
|
if ((offset_ + sz) < sbuf.size()) {
|
||||||
return sbuf.subspan(offset_);
|
return sbuf.subspan(offset_);
|
||||||
} else {
|
} else {
|
||||||
/// @remark switch the cache to std::string
|
/// \remark switch the cache to std::string
|
||||||
joined_.assign(sbuf.data(), offset_);
|
joined_.assign(sbuf.data(), offset_);
|
||||||
joined_.resize(roundup(offset_ + sz));
|
joined_.resize(roundup(offset_ + sz));
|
||||||
}
|
}
|
||||||
@ -216,7 +216,7 @@ bool fmt_context::append(std::string const &str) noexcept {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief To string conversion.
|
/// \brief To string conversion.
|
||||||
|
|
||||||
bool to_string(fmt_context &ctx, char const *a) noexcept {
|
bool to_string(fmt_context &ctx, char const *a) noexcept {
|
||||||
return to_string(ctx, a, {});
|
return to_string(ctx, a, {});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/platform/gnuc/demangle.h
|
* \file libimp/platform/gnuc/demangle.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,15 +15,15 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The conventional way to obtain demangled symbol name.
|
* \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
|
* \see https://www.boost.org/doc/libs/1_80_0/libs/core/doc/html/core/demangle.html
|
||||||
*
|
*
|
||||||
* @param name the mangled name
|
* \param name the mangled name
|
||||||
* @return std::string a human-readable demangled type name
|
* \return std::string a human-readable demangled type name
|
||||||
*/
|
*/
|
||||||
std::string demangle(span<char const> name) noexcept {
|
std::string demangle(span<char const> name) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
/// @see https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
|
/// \see https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
|
||||||
std::size_t sz = name.size() + 1;
|
std::size_t sz = name.size() + 1;
|
||||||
char *buffer = static_cast<char *>(std::malloc(sz));
|
char *buffer = static_cast<char *>(std::malloc(sz));
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/platform/posix/system.h
|
* \file libimp/platform/posix/system.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ namespace sys {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the system error number
|
* \brief Get the system error number
|
||||||
* https://man7.org/linux/man-pages/man3/errno.3.html
|
* https://man7.org/linux/man-pages/man3/errno.3.html
|
||||||
*/
|
*/
|
||||||
result_code error_no() noexcept {
|
result_code error_no() noexcept {
|
||||||
@ -29,7 +29,7 @@ result_code error_no() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the system error number
|
* \brief Set the system error number
|
||||||
* https://man7.org/linux/man-pages/man3/errno.3.html
|
* https://man7.org/linux/man-pages/man3/errno.3.html
|
||||||
*/
|
*/
|
||||||
void error_no(result_code code) noexcept {
|
void error_no(result_code code) noexcept {
|
||||||
@ -37,7 +37,7 @@ void error_no(result_code code) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a text description of the system error
|
* \brief Gets a text description of the system error
|
||||||
* https://man7.org/linux/man-pages/man3/strerror_l.3.html
|
* https://man7.org/linux/man-pages/man3/strerror_l.3.html
|
||||||
* https://manpages.ubuntu.com/manpages/xenial/en/man3/strerror.3.html
|
* https://manpages.ubuntu.com/manpages/xenial/en/man3/strerror.3.html
|
||||||
*/
|
*/
|
||||||
@ -58,7 +58,7 @@ std::string error_str(result_code code) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets configuration information at run time
|
* \brief Gets configuration information at run time
|
||||||
* https://man7.org/linux/man-pages/man2/getpagesize.2.html
|
* https://man7.org/linux/man-pages/man2/getpagesize.2.html
|
||||||
* https://man7.org/linux/man-pages/man3/sysconf.3.html
|
* https://man7.org/linux/man-pages/man3/sysconf.3.html
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/platform/win/codecvt.h
|
* \file libimp/platform/win/codecvt.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -14,7 +14,7 @@
|
|||||||
LIBIMP_NAMESPACE_BEG_
|
LIBIMP_NAMESPACE_BEG_
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte
|
* https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte
|
||||||
*
|
*
|
||||||
* CP_ACP : The system default Windows ANSI code page.
|
* CP_ACP : The system default Windows ANSI code page.
|
||||||
@ -57,7 +57,7 @@ std::size_t cvt_cstr(wchar_t const *src, std::size_t slen, char *des, std::size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Used for char8_t (since C++20) to wchar_t conversion.
|
* \brief Used for char8_t (since C++20) to wchar_t conversion.
|
||||||
*
|
*
|
||||||
* There is no ut to guarantee correctness (I'm a little lazy here),
|
* There is no ut to guarantee correctness (I'm a little lazy here),
|
||||||
* so if there are any bugs, please contact me in time.
|
* so if there are any bugs, please contact me in time.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/platform/win/demangle.h
|
* \file libimp/platform/win/demangle.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libimp/platform/win/system.h
|
* \file libimp/platform/win/system.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ LIBIMP_NAMESPACE_BEG_
|
|||||||
namespace sys {
|
namespace sys {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the system error number
|
* \brief Get the system error number
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
|
* https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
|
||||||
*/
|
*/
|
||||||
result_code error_no() noexcept {
|
result_code error_no() noexcept {
|
||||||
@ -33,7 +33,7 @@ result_code error_no() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the system error number
|
* \brief Set the system error number
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror
|
* https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror
|
||||||
*/
|
*/
|
||||||
void error_no(result_code code) noexcept {
|
void error_no(result_code code) noexcept {
|
||||||
@ -42,7 +42,7 @@ void error_no(result_code code) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets a text description of the system error
|
* \brief Gets a text description of the system error
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage
|
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage
|
||||||
*/
|
*/
|
||||||
std::string error_str(result_code code) noexcept {
|
std::string error_str(result_code code) noexcept {
|
||||||
@ -81,7 +81,7 @@ std::string error_str(result_code code) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves information about the current system
|
* \brief Retrieves information about the current system
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/platform/posix/mmap.h
|
* \file libipc/platform/posix/mmap.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/platform/posix/shm_impl.h
|
* \file libipc/platform/posix/shm_impl.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ result<int> shm_open_fd(std::string const &name, mode::type type) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Open the object for read-write access.
|
/// \brief Open the object for read-write access.
|
||||||
int flag = O_RDWR;
|
int flag = O_RDWR;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case mode::open:
|
case mode::open:
|
||||||
@ -73,7 +73,7 @@ result<int> shm_open_fd(std::string const &name, mode::type type) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Create/Open POSIX shared memory bject
|
/// \brief Create/Open POSIX shared memory bject
|
||||||
return ::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);
|
||||||
@ -81,7 +81,7 @@ result<int> shm_open_fd(std::string const &name, mode::type type) noexcept {
|
|||||||
|
|
||||||
result_code ftruncate_fd(int fd, std::size_t size) noexcept {
|
result_code ftruncate_fd(int fd, std::size_t size) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
/// @see https://man7.org/linux/man-pages/man3/ftruncate.3p.html
|
/// \see https://man7.org/linux/man-pages/man3/ftruncate.3p.html
|
||||||
if (::ftruncate(fd, size) != posix::succ) {
|
if (::ftruncate(fd, size) != posix::succ) {
|
||||||
auto err = sys::error();
|
auto err = sys::error();
|
||||||
log.error("failed: ftruncate(", fd, ", ", size, "). error = ", err);
|
log.error("failed: ftruncate(", fd, ", ", size, "). error = ", err);
|
||||||
@ -93,7 +93,7 @@ result_code ftruncate_fd(int fd, std::size_t size) noexcept {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://man7.org/linux/man-pages/man3/shm_open.3.html
|
* \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/fstat.3p.html
|
||||||
* https://man7.org/linux/man-pages/man2/mmap.2.html
|
* https://man7.org/linux/man-pages/man2/mmap.2.html
|
||||||
*/
|
*/
|
||||||
@ -112,25 +112,25 @@ result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noex
|
|||||||
if (pfd != nullptr) ::close(**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("failed: fstat(fd = ", *fd, "). error = ", sys::error());
|
log.error("failed: fstat(fd = ", *fd, "). error = ", sys::error());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Truncate this fd to a specified length
|
/// \brief Truncate this fd to a specified length
|
||||||
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(*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(*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("failed: mmap(size = ", size, ", fd = ", *fd, "). error = ", sys::error());
|
log.error("failed: mmap(size = ", size, ", fd = ", *fd, "). error = ", sys::error());
|
||||||
@ -140,7 +140,7 @@ result<shm_t> shm_open(std::string name, std::size_t size, mode::type type) noex
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://man7.org/linux/man-pages/man2/mmap.2.html
|
* \see https://man7.org/linux/man-pages/man2/mmap.2.html
|
||||||
*/
|
*/
|
||||||
result_code shm_close(shm_t h) noexcept {
|
result_code shm_close(shm_t h) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -151,7 +151,7 @@ result_code shm_close(shm_t h) noexcept {
|
|||||||
log.error("failed: munmap(", shm->memp, ", ", shm->f_sz, "). error = ", err);
|
log.error("failed: munmap(", shm->memp, ", ", shm->f_sz, "). error = ", err);
|
||||||
return err.code();
|
return err.code();
|
||||||
}
|
}
|
||||||
/// @brief no unlink the file.
|
/// \brief no unlink the file.
|
||||||
delete shm;
|
delete shm;
|
||||||
return {posix::succ};
|
return {posix::succ};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/platform/win/get_sa.h
|
* \file libipc/platform/win/get_sa.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -15,8 +15,8 @@ LIBIPC_NAMESPACE_BEG_
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a SECURITY_ATTRIBUTES structure singleton
|
* \brief Create a SECURITY_ATTRIBUTES structure singleton
|
||||||
* @see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85)
|
* \see https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa379560(v=vs.85)
|
||||||
*/
|
*/
|
||||||
inline LPSECURITY_ATTRIBUTES get_sa() {
|
inline LPSECURITY_ATTRIBUTES get_sa() {
|
||||||
static struct initiator {
|
static struct initiator {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/platform/win/mmap_impl.h
|
* \file libipc/platform/win/mmap_impl.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@ -30,8 +30,8 @@ struct shm_handle {
|
|||||||
namespace {
|
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
|
||||||
*/
|
*/
|
||||||
result_code mmap_close(HANDLE h) {
|
result_code mmap_close(HANDLE h) {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -48,17 +48,17 @@ result_code mmap_close(HANDLE h) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates or opens a file mapping object for a specified file.
|
* \brief Creates or opens a file mapping object for a specified file.
|
||||||
*
|
*
|
||||||
* @see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfilemappinga
|
* \see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfilemappinga
|
||||||
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga
|
* https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga
|
||||||
*
|
*
|
||||||
* @param file Specifies the name of the file mapping object
|
* \param file Specifies the name of the file mapping object
|
||||||
* @param size Specifies the size required to create a file mapping object.
|
* \param size Specifies the size required to create a file mapping object.
|
||||||
* This size is ignored when opening an existing file mapping object
|
* This size is ignored when opening an existing file mapping object
|
||||||
* @param type Combinable open modes, create | open
|
* \param type Combinable open modes, create | open
|
||||||
*
|
*
|
||||||
* @return File mapping object HANDLE, NULL on error
|
* \return File mapping object HANDLE, NULL on error
|
||||||
*/
|
*/
|
||||||
result<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_();
|
||||||
@ -72,7 +72,7 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Opens a named file mapping object.
|
/// \brief Opens a named file mapping object.
|
||||||
auto try_open = [&]() -> result<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) {
|
||||||
@ -83,10 +83,10 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
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 = [&]() -> result<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) {
|
||||||
auto err = sys::error();
|
auto err = sys::error();
|
||||||
@ -99,8 +99,8 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
if (type == mode::open) {
|
if (type == mode::open) {
|
||||||
return try_open();
|
return try_open();
|
||||||
} else if ((type == (mode::create | mode::open)) && (size == 0)) {
|
} else if ((type == (mode::create | mode::open)) && (size == 0)) {
|
||||||
/// @remark CreateFileMapping may returns ERROR_INVALID_PARAMETER when dwMaximumSizeLow is zero.
|
/// \remark CreateFileMapping may returns ERROR_INVALID_PARAMETER when dwMaximumSizeLow is zero.
|
||||||
/// @see CreateFileMapping (Windows CE 5.0)
|
/// \see CreateFileMapping (Windows CE 5.0)
|
||||||
/// https://learn.microsoft.com/en-us/previous-versions/windows/embedded/aa517331(v=msdn.10)
|
/// https://learn.microsoft.com/en-us/previous-versions/windows/embedded/aa517331(v=msdn.10)
|
||||||
return try_open();
|
return try_open();
|
||||||
} else if (!(type & mode::create)) {
|
} else if (!(type & mode::create)) {
|
||||||
@ -109,7 +109,7 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
}
|
}
|
||||||
auto h = try_create();
|
auto h = try_create();
|
||||||
if (!h) return h;
|
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)) {
|
||||||
log.info("the file being created already exists. file = ", file, ", type = ", type);
|
log.info("the file being created already exists. file = ", file, ", type = ", type);
|
||||||
@ -120,8 +120,8 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
result<LPVOID> mmap_memof(HANDLE h) {
|
result<LPVOID> mmap_memof(HANDLE h) {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -139,8 +139,8 @@ result<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
|
||||||
*/
|
*/
|
||||||
result<SIZE_T> mmap_sizeof(LPCVOID mem) {
|
result<SIZE_T> mmap_sizeof(LPCVOID mem) {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -158,8 +158,8 @@ result<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
|
||||||
*/
|
*/
|
||||||
result_code mmap_release(HANDLE h, LPCVOID mem) {
|
result_code mmap_release(HANDLE h, LPCVOID mem) {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/platform/win/shm_impl.h
|
* \file libipc/platform/win/shm_impl.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file libipc/platform/win/to_tchar.h
|
* \file libipc/platform/win/to_tchar.h
|
||||||
* @author mutouyun (orz@orzz.org)
|
* \author mutouyun (orz@orzz.org)
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
LIBIPC_NAMESPACE_BEG_
|
LIBIPC_NAMESPACE_BEG_
|
||||||
|
|
||||||
/// @brief C style shared memory access interface implementation.
|
/// \brief C style shared memory access interface implementation.
|
||||||
|
|
||||||
void *shm_get(shm_t h) noexcept {
|
void *shm_get(shm_t h) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -44,7 +44,7 @@ std::string shm_name(shm_t h) noexcept {
|
|||||||
return shm->file;
|
return shm->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief The shared memory object.
|
/// \brief The shared memory object.
|
||||||
|
|
||||||
shared_memory::shared_memory() noexcept
|
shared_memory::shared_memory() noexcept
|
||||||
: shm_(nullptr) {}
|
: shm_(nullptr) {}
|
||||||
|
|||||||
@ -10,29 +10,29 @@ LIBIPC_NAMESPACE_BEG_
|
|||||||
#if defined(LIBIMP_CC_MSVC)
|
#if defined(LIBIMP_CC_MSVC)
|
||||||
# include <Windows.h> // YieldProcessor
|
# include <Windows.h> // YieldProcessor
|
||||||
/**
|
/**
|
||||||
* @brief Not for intel c++ compiler, so ignore http://software.intel.com/en-us/forums/topic/296168
|
* \brief Not for intel c++ compiler, so ignore http://software.intel.com/en-us/forums/topic/296168
|
||||||
* @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms687419(v=vs.85).aspx
|
* \see http://msdn.microsoft.com/en-us/library/windows/desktop/ms687419(v=vs.85).aspx
|
||||||
*/
|
*/
|
||||||
# define LIBIPC_LOCK_PAUSE_() YieldProcessor()
|
# define LIBIPC_LOCK_PAUSE_() YieldProcessor()
|
||||||
#elif defined(LIBIMP_CC_GNUC)
|
#elif defined(LIBIMP_CC_GNUC)
|
||||||
# if defined(LIBIMP_INSTR_X86_64)
|
# if defined(LIBIMP_INSTR_X86_64)
|
||||||
/**
|
/**
|
||||||
* @brief Intel(R) 64 and IA-32 Architectures Software Developer's Manual V2
|
* \brief Intel(R) 64 and IA-32 Architectures Software Developer's Manual V2
|
||||||
* PAUSE-Spin Loop Hint, 4-57
|
* PAUSE-Spin Loop Hint, 4-57
|
||||||
* @see http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.html?wapkw=instruction+set+reference
|
* \see http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.html?wapkw=instruction+set+reference
|
||||||
*/
|
*/
|
||||||
# define LIBIPC_LOCK_PAUSE_() __asm__ __volatile__("pause")
|
# define LIBIPC_LOCK_PAUSE_() __asm__ __volatile__("pause")
|
||||||
# elif defined(LIBIMP_INSTR_I64)
|
# elif defined(LIBIMP_INSTR_I64)
|
||||||
/**
|
/**
|
||||||
* @brief Intel(R) Itanium(R) Architecture Developer's Manual, Vol.3
|
* \brief Intel(R) Itanium(R) Architecture Developer's Manual, Vol.3
|
||||||
* hint - Performance Hint, 3:145
|
* hint - Performance Hint, 3:145
|
||||||
* @see http://www.intel.com/content/www/us/en/processors/itanium/itanium-architecture-vol-3-manual.html
|
* \see http://www.intel.com/content/www/us/en/processors/itanium/itanium-architecture-vol-3-manual.html
|
||||||
*/
|
*/
|
||||||
# define LIBIPC_LOCK_PAUSE_() __asm__ __volatile__ ("hint @pause")
|
# define LIBIPC_LOCK_PAUSE_() __asm__ __volatile__ ("hint @pause")
|
||||||
# elif defined(LIBIMP_INSTR_ARM)
|
# elif defined(LIBIMP_INSTR_ARM)
|
||||||
/**
|
/**
|
||||||
* @brief ARM Architecture Reference Manuals (YIELD)
|
* \brief ARM Architecture Reference Manuals (YIELD)
|
||||||
* @see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html
|
* \see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html
|
||||||
*/
|
*/
|
||||||
# define LIBIPC_LOCK_PAUSE_() __asm__ __volatile__ ("yield")
|
# define LIBIPC_LOCK_PAUSE_() __asm__ __volatile__ ("yield")
|
||||||
# endif
|
# endif
|
||||||
@ -40,20 +40,20 @@ LIBIPC_NAMESPACE_BEG_
|
|||||||
|
|
||||||
#if !defined(LIBIPC_LOCK_PAUSE_)
|
#if !defined(LIBIPC_LOCK_PAUSE_)
|
||||||
/**
|
/**
|
||||||
* @brief Just use a compiler fence, prevent compiler from optimizing loop
|
* \brief Just use a compiler fence, prevent compiler from optimizing loop
|
||||||
*/
|
*/
|
||||||
# define LIBIPC_LOCK_PAUSE_() std::atomic_signal_fence(std::memory_order_seq_cst)
|
# define LIBIPC_LOCK_PAUSE_() std::atomic_signal_fence(std::memory_order_seq_cst)
|
||||||
#endif /*!defined(LIBIPC_LOCK_PAUSE_)*/
|
#endif /*!defined(LIBIPC_LOCK_PAUSE_)*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gives hint to processor that improves performance of spin-wait loops.
|
* \brief Gives hint to processor that improves performance of spin-wait loops.
|
||||||
*/
|
*/
|
||||||
void pause() noexcept {
|
void pause() noexcept {
|
||||||
LIBIPC_LOCK_PAUSE_();
|
LIBIPC_LOCK_PAUSE_();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Basic spin lock
|
* \brief Basic spin lock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void spin_lock::lock() noexcept {
|
void spin_lock::lock() noexcept {
|
||||||
@ -66,14 +66,14 @@ void spin_lock::unlock() noexcept {
|
|||||||
lc_.store(0, std::memory_order_release);
|
lc_.store(0, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Constants for shared mode spin lock
|
/// \brief Constants for shared mode spin lock
|
||||||
enum : unsigned {
|
enum : unsigned {
|
||||||
w_mask = (std::numeric_limits<std::make_signed_t<unsigned>>::max)(), // b 0111 1111
|
w_mask = (std::numeric_limits<std::make_signed_t<unsigned>>::max)(), // b 0111 1111
|
||||||
w_flag = w_mask + 1, // b 1000 0000
|
w_flag = w_mask + 1, // b 1000 0000
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Support for shared mode spin lock
|
* \brief Support for shared mode spin lock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void rw_lock::lock() noexcept {
|
void rw_lock::lock() noexcept {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ LIBPMR_NAMESPACE_BEG_
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check that bytes is not 0 and that the alignment is a power of two.
|
* \brief Check that bytes is not 0 and that the alignment is a power of two.
|
||||||
*/
|
*/
|
||||||
bool verify_args(::LIBIMP::log::grip &log, std::size_t bytes, std::size_t alignment) noexcept {
|
bool verify_args(::LIBIMP::log::grip &log, std::size_t bytes, std::size_t alignment) noexcept {
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
@ -27,9 +27,9 @@ bool verify_args(::LIBIMP::log::grip &log, std::size_t bytes, std::size_t alignm
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a pointer to a new_delete_resource.
|
* \brief Returns a pointer to a new_delete_resource.
|
||||||
*
|
*
|
||||||
* @return new_delete_resource*
|
* \return new_delete_resource*
|
||||||
*/
|
*/
|
||||||
new_delete_resource *new_delete_resource::get() noexcept {
|
new_delete_resource *new_delete_resource::get() noexcept {
|
||||||
static new_delete_resource mem_res;
|
static new_delete_resource mem_res;
|
||||||
@ -37,13 +37,13 @@ new_delete_resource *new_delete_resource::get() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Allocates storage with a size of at least bytes bytes, aligned to the specified alignment.
|
* \brief Allocates storage with a size of at least bytes bytes, aligned to the specified alignment.
|
||||||
* @remark Alignment shall be a power of two.
|
* Alignment shall be a power of two.
|
||||||
*
|
*
|
||||||
* @see https://en.cppreference.com/w/cpp/memory/memory_resource/do_allocate
|
* \see https://en.cppreference.com/w/cpp/memory/memory_resource/do_allocate
|
||||||
* https://www.cppstories.com/2019/08/newnew-align/
|
* https://www.cppstories.com/2019/08/newnew-align/
|
||||||
*
|
*
|
||||||
* @return void * - nullptr if storage of the requested size and alignment cannot be obtained.
|
* \return void * - nullptr if storage of the requested size and alignment cannot be obtained.
|
||||||
*/
|
*/
|
||||||
void *new_delete_resource::allocate(std::size_t bytes, std::size_t alignment) noexcept {
|
void *new_delete_resource::allocate(std::size_t bytes, std::size_t alignment) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -51,18 +51,18 @@ void *new_delete_resource::allocate(std::size_t bytes, std::size_t alignment) no
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#if defined(LIBIMP_CPP_17)
|
#if defined(LIBIMP_CPP_17)
|
||||||
/// @see https://en.cppreference.com/w/cpp/memory/c/aligned_alloc
|
/// \see https://en.cppreference.com/w/cpp/memory/c/aligned_alloc
|
||||||
return std::aligned_alloc(alignment, bytes);
|
return std::aligned_alloc(alignment, bytes);
|
||||||
#else
|
#else
|
||||||
if (alignment <= alignof(std::max_align_t)) {
|
if (alignment <= alignof(std::max_align_t)) {
|
||||||
/// @see https://en.cppreference.com/w/cpp/memory/c/malloc
|
/// \see https://en.cppreference.com/w/cpp/memory/c/malloc
|
||||||
return std::malloc(bytes);
|
return std::malloc(bytes);
|
||||||
}
|
}
|
||||||
#if defined(LIBIMP_OS_WIN)
|
#if defined(LIBIMP_OS_WIN)
|
||||||
/// @see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc
|
/// \see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-malloc
|
||||||
return ::_aligned_malloc(bytes, alignment);
|
return ::_aligned_malloc(bytes, alignment);
|
||||||
#else // try posix
|
#else // try posix
|
||||||
/// @see https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_memalign.html
|
/// \see https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_memalign.html
|
||||||
void *p = nullptr;
|
void *p = nullptr;
|
||||||
int ret = ::posix_memalign(&p, alignment, bytes);
|
int ret = ::posix_memalign(&p, alignment, bytes);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -77,12 +77,12 @@ void *new_delete_resource::allocate(std::size_t bytes, std::size_t alignment) no
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Deallocates the storage pointed to by p.
|
* \brief Deallocates the storage pointed to by p.
|
||||||
* @remark The storage it points to must not yet have been deallocated, otherwise the behavior is undefined.
|
* The storage it points to must not yet have been deallocated, otherwise the behavior is undefined.
|
||||||
*
|
*
|
||||||
* @see https://en.cppreference.com/w/cpp/memory/memory_resource/do_deallocate
|
* \see https://en.cppreference.com/w/cpp/memory/memory_resource/do_deallocate
|
||||||
*
|
*
|
||||||
* @param p must have been returned by a prior call to new_delete_resource::do_allocate(bytes, alignment).
|
* \param p must have been returned by a prior call to new_delete_resource::do_allocate(bytes, alignment).
|
||||||
*/
|
*/
|
||||||
void new_delete_resource::deallocate(void *p, std::size_t bytes, std::size_t alignment) noexcept {
|
void new_delete_resource::deallocate(void *p, std::size_t bytes, std::size_t alignment) noexcept {
|
||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
@ -93,7 +93,7 @@ void new_delete_resource::deallocate(void *p, std::size_t bytes, std::size_t ali
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(LIBIMP_CPP_17)
|
#if defined(LIBIMP_CPP_17)
|
||||||
/// @see https://en.cppreference.com/w/cpp/memory/c/free
|
/// \see https://en.cppreference.com/w/cpp/memory/c/free
|
||||||
std::free(p);
|
std::free(p);
|
||||||
#else
|
#else
|
||||||
if (alignment <= alignof(std::max_align_t)) {
|
if (alignment <= alignof(std::max_align_t)) {
|
||||||
@ -101,7 +101,7 @@ void new_delete_resource::deallocate(void *p, std::size_t bytes, std::size_t ali
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#if defined(LIBIMP_OS_WIN)
|
#if defined(LIBIMP_OS_WIN)
|
||||||
/// @see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-free
|
/// \see https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/aligned-free
|
||||||
::_aligned_free(p);
|
::_aligned_free(p);
|
||||||
#else // try posix
|
#else // try posix
|
||||||
::free(p);
|
::free(p);
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
@ -75,8 +76,10 @@ TEST(result, fmt) {
|
|||||||
EXPECT_EQ(imp::fmt(r0), imp::fmt(imp::result_code()));
|
EXPECT_EQ(imp::fmt(r0), imp::fmt(imp::result_code()));
|
||||||
imp::result<int> r1 {false, -123};
|
imp::result<int> r1 {false, -123};
|
||||||
EXPECT_EQ(imp::fmt(r1), imp::fmt("[fail, value = ", -123, "]"));
|
EXPECT_EQ(imp::fmt(r1), imp::fmt("[fail, value = ", -123, "]"));
|
||||||
|
|
||||||
imp::result<void *> r2 {&r1};
|
imp::result<void *> r2 {&r1};
|
||||||
EXPECT_EQ(imp::fmt(r2), imp::fmt("[succ, value = ", (void *)&r1, "]"));
|
EXPECT_EQ(imp::fmt(r2), imp::fmt("[succ, value = ", (void *)&r1, "]"));
|
||||||
|
|
||||||
int aaa {};
|
int aaa {};
|
||||||
imp::result<int *> r3 {&aaa};
|
imp::result<int *> r3 {&aaa};
|
||||||
EXPECT_EQ(imp::fmt(r3), imp::fmt("[succ, value = ", (void *)&aaa, "]"));
|
EXPECT_EQ(imp::fmt(r3), imp::fmt("[succ, value = ", (void *)&aaa, "]"));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user