packages.biu: enable other components

This commit is contained in:
2024-08-24 14:10:55 +08:00
parent 655e683b02
commit 0470c1041c
14 changed files with 121 additions and 139 deletions

View File

@@ -13,17 +13,22 @@ endif()
find_package(magic_enum REQUIRED)
find_package(fmt REQUIRED)
find_package(Boost REQUIRED COMPONENTS headers iostreams filesystem)
find_package(Boost REQUIRED COMPONENTS headers iostreams filesystem system)
find_package(range-v3 REQUIRED)
find_path(NAMEOF_INCLUDE_DIR nameof.hpp REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(HighFive REQUIRED)
find_path(ZPP_BITS_INCLUDE_DIR zpp_bits.h REQUIRED)
find_package(TgBot REQUIRED)
find_path(LIBBACKTRACE_INCLUDE_DIR backtrace.h REQUIRED)
find_library(LIBBACKTRACE_LIBRARY NAMES backtrace REQUIRED)
add_library(biu src/common.cpp src/hdf5.cpp)
add_library(biu src/common.cpp src/hdf5.cpp src/logger.cpp src/string.cpp)
target_include_directories(biu PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ${NAMEOF_INCLUDE_DIR} ${ZPP_BITS_INCLUDE_DIR})
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> ${NAMEOF_INCLUDE_DIR} ${ZPP_BITS_INCLUDE_DIR}
${LIBBACKTRACE_INCLUDE_DIR})
target_link_libraries(biu PUBLIC magic_enum::magic_enum fmt::fmt Boost::headers Boost::iostreams Boost::filesystem
range-v3::range-v3 Eigen3::Eigen HighFive_HighFive)
range-v3::range-v3 Eigen3::Eigen HighFive_HighFive TgBot::TgBot ${LIBBACKTRACE_LIBRARY})
set_property(TARGET biu PROPERTY CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON)
install(TARGETS biu EXPORT biuTargets LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

View File

@@ -1,8 +1,10 @@
include("${CMAKE_CURRENT_LIST_DIR}/biuTargets.cmake")
find_package(magic_enum REQUIRED)
find_package(fmt REQUIRED)
find_package(Boost REQUIRED COMPONENTS headers iostreams filesystem)
find_package(Boost REQUIRED COMPONENTS headers iostreams filesystem system)
find_package(Eigen3 REQUIRED)
find_package(range-v3 REQUIRED)
find_path(NAMEOF_INCLUDE_DIR nameof.hpp REQUIRED)
find_package(HighFive REQUIRED)
find_path(ZPP_BITS_INCLUDE_DIR zpp_bits.h REQUIRED)
find_package(TgBot REQUIRED)

View File

@@ -1,11 +1,11 @@
{
stdenv, cmake, lib,
magic-enum, fmt, boost, eigen, range-v3, nameof, zpp-bits, highfive
magic-enum, fmt, boost, eigen, range-v3, nameof, zpp-bits, highfive, tgbot-cpp, libbacktrace
}: stdenv.mkDerivation rec
{
name = "biu";
src = ./.;
buildInputs = [ magic-enum fmt boost range-v3 nameof zpp-bits eigen highfive ];
buildInputs = [ magic-enum fmt boost range-v3 nameof zpp-bits eigen highfive tgbot-cpp libbacktrace ];
propagatedBuildInputs = buildInputs;
nativeBuildInputs = [ cmake ];
doCheck = true;

View File

@@ -7,7 +7,5 @@
# include <biu/format.tpp>
# include <biu/eigen.tpp>
# include <biu/hdf5.tpp>
// # include <biu/logger.tpp>
// # include <biu/smartref.tpp>
# include <biu/logger.tpp>
# include <biu/smartref.tpp>

View File

@@ -59,9 +59,8 @@ namespace biu
if constexpr (Throw) throw std::runtime_error("Timeout");
else return std::optional<Guard<std::is_const_v<decltype(self)>>>();
}
else
return std::optional<Guard<std::is_const_v<decltype(self)>>>
(std::move(lock), std::experimental::make_observer(&self), {});
else return std::optional(Guard<std::is_const_v<decltype(self)>>
(std::move(lock), std::experimental::make_observer(&self), {}));
}
}
@@ -77,7 +76,7 @@ namespace biu
if (!lock)
if constexpr (std::is_void_v<function_return_type>) return false;
else return std::optional<function_return_type>();
// 否则,执行函数并返回
// 否则,执行函数
else
if constexpr (std::is_void_v<function_return_type>)
{
@@ -94,13 +93,17 @@ namespace biu
(std::forward<MoveQualifiers<decltype(self), ValueType>>(self.Value_));
return std::make_optional(std::forward<decltype(result)>(result));
}
// 否则,执行函数返回 *this
// 否则,说明不可能超时,返回函数返回值或者 *this
else
{
std::forward<decltype(function)>(function)
(std::forward<MoveQualifiers<decltype(self), ValueType>>(self.Value_));
return std::forward<decltype(self)>(self);
}
if constexpr (std::is_void_v<function_return_type>)
{
std::forward<decltype(function)>(function)
(std::forward<MoveQualifiers<decltype(self), ValueType>>(self.Value_));
return std::forward<decltype(self)>(self);
}
else
return std::forward<decltype(function)>(function)
(std::forward<MoveQualifiers<decltype(self), ValueType>>(self.Value_));
}
template <DecayedType ValueType> template <bool NoReturn> decltype(auto) Atomic<ValueType>::apply
(this auto&& self, auto&& function, auto&& condition_function)

View File

@@ -3,6 +3,7 @@
# include <fmt/ranges.h>
# include <fmt/std.h>
# include <fmt/ostream.h>
# include <fmt/chrono.h>
# include <fmt/xchar.h>
# include <nameof.hpp>
# include <biu/format.hpp>

View File

@@ -1,7 +1,7 @@
# pragma once
# include <map>
# include <boost/stacktrace.hpp>
# include <biu/atomic/nolog.hpp>
# include <biu/atomic.hpp>
namespace biu
{
@@ -17,7 +17,6 @@ namespace biu
{
None,
Error,
Access,
Info,
Debug
};
@@ -27,18 +26,17 @@ namespace biu
std::shared_ptr<std::ostream> StreamStorage;
Logger::Level Level;
};
protected: static Atomic<std::optional<LoggerConfigType_>, false> LoggerConfig_;
protected: static Atomic<std::optional<LoggerConfigType_>> LoggerConfig_;
public: static void init(std::experimental::observer_ptr<std::ostream> stream, Level level);
public: static void init(std::shared_ptr<std::ostream> stream, Level level);
// Send a telegram message if token and chat id are set, all the functions are thread-safe
protected: static Atomic<std::optional<std::pair<std::string, std::string>>, false> TelegramConfig_;
protected: static Atomic<std::optional<std::pair<std::string, std::string>>> TelegramConfig_;
public: static void telegram_init(const std::string& token, const std::string& chat_id);
public: static void telegram_notify(const std::string& message);
public: static void telegram_notify_async(const std::string& message);
public: static void telegram_notify(const std::string& message, bool async = false);
// Monitor the lifetime of an object
// usage: struct my_class : protected Logger::ObjectMonitor<my_class> {}
// usage: struct my_class : protected Logger::ObjectMonitor<my_class> { ... }
public: template <typename T> class ObjectMonitor
{
protected: const std::chrono::time_point<std::chrono::steady_clock> CreateTime_;
@@ -52,7 +50,7 @@ namespace biu
template <typename T> friend class ObjectMonitor;
// List of objects that is being monitored by ObjectMonitor, {address, type}
protected: static Atomic<std::multimap<const void*, std::string_view>, false> Objects_;
protected: static Atomic<std::multimap<const void*, std::string_view>> Objects_;
public: template <typename FinalException> class Exception : public std::exception
{
@@ -70,16 +68,18 @@ namespace biu
{
protected: thread_local static unsigned Indent_;
protected: const std::chrono::time_point<std::chrono::steady_clock> StartTime_;
protected: std::size_t get_time_ms() const;
protected: std::size_t get_thread_id() const;
// if sizeof...(Param) > 0, call log<Debug>("begin function with {arguments}.");
// else call log<Debug>("begin function.");
public: template <typename... Param> [[gnu::always_inline]] explicit Guard(Param&&... param);
// call log<Debug>("end function after {duration} ms.")
public: [[gnu::always_inline]] virtual ~Guard();
public: [[gnu::always_inline]] inline virtual ~Guard();
// call log<Debug>("reached after {duration} ms.")
public: [[gnu::always_inline]] void operator()() const;
public: [[gnu::always_inline]] inline void operator()() const;
// call log<Debug>("return {return} after {duration} ms.")
public: template <typename T> [[gnu::always_inline]] T rtn(T&& value) const;
@@ -88,6 +88,9 @@ namespace biu
// LoggerConfig_
// [ {time} {thread} {indent} {filename}:{line} {function_name} ] {message}
public: template <Level L> [[gnu::always_inline]] void log(const std::string& message) const;
public: [[gnu::always_inline]] inline void error(const std::string& message) const;
public: [[gnu::always_inline]] inline void info(const std::string& message) const;
public: [[gnu::always_inline]] inline void debug(const std::string& message) const;
public: template <typename FinalException> [[gnu::always_inline]] void print_exception
(
@@ -98,6 +101,6 @@ namespace biu
friend class Guard;
// list of threads which is being monitored by Guard and number of Guard created in this thread so far
protected: static Atomic<std::map<std::size_t, std::size_t>, false> Threads_;
protected: static Atomic<std::map<std::size_t, std::size_t>> Threads_;
};
}

View File

@@ -11,9 +11,8 @@ namespace biu
: CreateTime_{std::chrono::steady_clock::now()}
{
Guard guard;
guard.log<Level::Debug>("create {} at {}."_f(nameof::nameof_full_type<T>(), fmt::ptr(this)));
auto&& lock = Objects_.lock();
lock->emplace(this, nameof::nameof_full_type<T>());
Objects_.lock()->emplace(this, nameof::nameof_full_type<T>());
guard.debug("create {} at {}."_f(nameof::nameof_full_type<T>(), fmt::ptr(this)));
}
template <typename T> Logger::ObjectMonitor<T>::~ObjectMonitor()
{
@@ -26,80 +25,41 @@ namespace biu
));
auto&& lock = Objects_.lock();
auto range = lock->equal_range(this);
for (auto it = range.first; it != range.second; it++)
if (it->second == nameof::nameof_full_type<T>())
{
lock->erase(it);
return;
}
guard.log<Level::Error>
("{} {} not found in Logger::Objects."_f(fmt::ptr(this), nameof::nameof_full_type<T>()));
for (auto it = range.first; it != range.second; it++) if (it->second == nameof::nameof_full_type<T>())
{ lock->erase(it); return; }
guard.error("{} {} not found in Logger::Objects."_f(fmt::ptr(this), nameof::nameof_full_type<T>()));
}
template <typename FinalException> Logger::Exception<FinalException>::Exception(const std::string& message)
{
Logger::Guard log{message};
log.print_exception(nameof::nameof_full_type<FinalException>(), message, Stacktrace_);
Logger::Guard log(message);
log.print_exception(nameof::nameof_full_type<FinalException>(), message, Stacktrace_, {});
}
template <typename... Param> inline Logger::Guard::Guard(Param&&... param)
template <typename... Param> Logger::Guard::Guard(Param&&... param)
: StartTime_{std::chrono::steady_clock::now()}
{
Indent_++;
auto&& lock = Threads_.lock();
auto thread_id = std::hash<std::thread::id>{}(std::this_thread::get_id());
if (lock->contains(thread_id))
lock.value()[thread_id]++;
else
lock->emplace(thread_id, 1);
if (auto thread_id = get_thread_id(); lock->contains(thread_id)) lock.value()[thread_id]++;
else lock->emplace(thread_id, 1);
if constexpr (sizeof...(Param) > 0)
{
std::stringstream ss;
std::vector<std::string> params = {"{}"_f(std::forward<Param>(param))...};
ss << "begin function with {";
for (auto& param : params)
ss << param << ", ";
ss.seekp(-2, ss.cur);
ss << "}.";
log<Level::Debug>(ss.str());
}
else
log<Level::Debug>("begin function.");
debug("begin function with {{{}}}."_f(fmt::join({"{}"_f(std::forward<Param>(param))...}, ", ")));
else debug("begin function.");
}
inline Logger::Guard::~Guard()
Logger::Guard::~Guard()
{
log<Level::Debug>("end function after {} ms."_f(std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - StartTime_).count()));
debug("end function after {} ms."_f(get_time_ms()));
Indent_--;
auto&& lock = Threads_.lock();
auto thread_id = std::hash<std::thread::id>{}(std::this_thread::get_id());
if (lock->contains(thread_id))
{
lock.value()[thread_id]--;
if (lock.value()[thread_id] == 0)
lock->erase(thread_id);
}
if (auto thread_id = get_thread_id(); lock->contains(thread_id))
{ lock.value()[thread_id]--; if (lock.value()[thread_id] == 0) lock->erase(thread_id); }
else [[unlikely]]
log<Level::Debug>("{:08x} not found in Logger::Threads."_f
(std::hash<std::thread::id>{}(std::this_thread::get_id()) % std::numeric_limits<std::uint64_t>::max()));
error("{:08x} not found in Logger::Threads."_f(thread_id % std::numeric_limits<std::uint64_t>::max()));
}
inline void Logger::Guard::operator()() const
{
log<Level::Debug>("reached after {} ms."_f
(
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - StartTime_).count()
));
}
template <typename T> inline T Logger::Guard::rtn(T&& value) const
{
log<Level::Debug>("return {} after {} ms."_f
(
std::forward<T>(value),
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - StartTime_).count()
));
return std::forward<T>(value);
}
template <Logger::Level L> inline void Logger::Guard::log(const std::string& message) const
void Logger::Guard::operator()() const { debug("reached after {} ms."_f(get_time_ms())); }
template <Logger::Level L> void Logger::Guard::log(const std::string& message) const
{
if (auto&& lock = LoggerConfig_.lock(); *lock && lock.value()->Level >= L)
{
@@ -110,8 +70,7 @@ namespace biu
(
time,
std::chrono::time_point_cast<std::chrono::milliseconds>(time).time_since_epoch().count() % 1000,
std::hash<std::thread::id>{}(std::this_thread::get_id())
% std::numeric_limits<std::uint64_t>::max(),
get_thread_id() % std::numeric_limits<std::uint64_t>::max(),
Indent_,
stack[0].source_file().empty() ? "??"s : stack[0].source_file(),
stack[0].source_line() == 0 ? "??"s : "{}"_f(stack[0].source_line()),
@@ -120,6 +79,16 @@ namespace biu
) << std::flush;
}
}
void Logger::Guard::error(const std::string& message) const { log<Level::Error>(message); }
void Logger::Guard::info(const std::string& message) const { log<Level::Info>(message); }
void Logger::Guard::debug(const std::string& message) const { log<Level::Debug>(message); }
template <typename T> inline T Logger::Guard::rtn(T&& value) const
{
debug("return {} after {} ms."_f(std::forward<T>(value), get_time_ms()));
return std::forward<T>(value);
}
template <typename FinalException> inline void Logger::Guard::print_exception
(
const std::string& type, const std::string& message, const boost::stacktrace::stacktrace& stacktrace,

View File

@@ -4,7 +4,9 @@
# include <string>
# include <string_view>
# include <iostream>
# include <generator>
# include <biu/concepts.hpp>
# include <biu/smartref.hpp>
namespace biu
{
@@ -36,6 +38,13 @@ namespace biu
template <std::size_t M> requires (M<=N) constexpr BasicVariableString(const Char (&str)[M]);
};
template <std::size_t N> using VariableString = BasicVariableString<char, N>;
// Find specific content in a string. Return unmatched content before the match and the match result every
// time. If match reached the end, the second returned value will be std::sregex_iterator().
std::generator<std::pair<std::string_view, std::sregex_iterator>> find
(SmartRef<const std::string> data, SmartRef<const std::regex> regex);
std::string replace
(const std::string& data, const std::regex& regex, std::function<std::string(const std::smatch&)> function);
}
using string::BasicStaticString, string::StaticString, string::BasicFixedString, string::FixedString,
string::BasicVariableString, string::VariableString;
@@ -105,13 +114,3 @@ namespace biu
concepts::SpecializationOfBasicFixedString, concepts::SpecializationOfFixedString,
concepts::SpecializationOfBasicVariableString, concepts::SpecializationOfVariableString;
}
// namespace string
// {
// // Find specific content in a string. Return unmatched content before the match and the match result every
// // time. If match reached the end, the second returned value will be std::sregex_iterator().
// concurrencpp::generator<std::pair<std::string_view, std::sregex_iterator>> find
// (SmartRef<const std::string> data, SmartRef<const std::regex> regex);
// // Use a regex to find all matches and replace them with a callback function
// std::string replace
// (const std::string& data, const std::regex& regex, std::function<std::string(const std::smatch&)> function);
// }

View File

@@ -1,4 +1,4 @@
# include <biu/hdf5.hpp>
# include <biu.hpp>
namespace biu::hdf5
{

View File

@@ -3,34 +3,37 @@
namespace biu
{
Atomic<std::optional<typename Logger::LoggerConfigType_>, false> Logger::LoggerConfig_;
Atomic<std::optional<Logger::LoggerConfigType_>> Logger::LoggerConfig_;
void Logger::init(std::experimental::observer_ptr<std::ostream> stream, Level level)
{
auto&& lock = LoggerConfig_.lock();
lock->emplace(stream, nullptr, level);
}
{ LoggerConfig_ = LoggerConfigType_{stream, nullptr, level}; }
void Logger::init(std::shared_ptr<std::ostream> stream, Level level)
{
auto&& lock = LoggerConfig_.lock();
lock->emplace(std::experimental::make_observer(stream.get()), stream, level);
}
{ LoggerConfig_ = LoggerConfigType_{std::experimental::make_observer(stream.get()), stream, level}; }
Atomic<std::optional<std::pair<std::string, std::string>>, false> Logger::TelegramConfig_;
Atomic<std::optional<std::pair<std::string, std::string>>> Logger::TelegramConfig_;
void Logger::telegram_init(const std::string& token, const std::string& chat_id)
{TelegramConfig_ = std::make_pair(token, chat_id);}
void Logger::telegram_notify(const std::string& message)
{ TelegramConfig_ = std::make_pair(token, chat_id); }
void Logger::telegram_notify(const std::string& message, bool async)
{
if (auto&& lock = TelegramConfig_.lock(); *lock)
auto notify = [](const std::string& message)
{
TgBot::Bot bot{lock.value()->first};
auto&& lock = TelegramConfig_.lock();
TgBot::Bot bot(lock.value()->first);
bot.getApi().sendMessage(lock.value()->first, message);
}
};
if (async) std::thread(notify, message).detach();
else notify(message);
}
void Logger::telegram_notify_async(const std::string& message)
{std::thread{Logger::telegram_notify, message}.detach();}
Atomic<std::multimap<const void*, std::string_view>, false> Logger::Objects_;
Atomic<std::multimap<const void*, std::string_view>> Logger::Objects_;
thread_local unsigned Logger::Guard::Indent_ = 0;
Atomic<std::map<std::size_t, std::size_t>, false> Logger::Threads_;
std::size_t Logger::Guard::get_time_ms() const
{
return std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - StartTime_).count();
}
std::size_t Logger::Guard::get_thread_id() const
{ return std::hash<std::thread::id>{}(std::this_thread::get_id()); }
Atomic<std::map<std::size_t, std::size_t>> Logger::Threads_;
}

View File

@@ -1,9 +1,8 @@
# include <fmt/chrono.h>
# include <biu.hpp>
namespace biu
{
concurrencpp::generator<std::pair<std::string_view, std::sregex_iterator>> string::find
std::generator<std::pair<std::string_view, std::sregex_iterator>> string::find
(SmartRef<const std::string> data, SmartRef<const std::regex> regex)
{
Logger::Guard log;
@@ -11,17 +10,14 @@ namespace biu
std::sregex_iterator regit;
while (true)
{
if (regit == std::sregex_iterator{})
regit = std::sregex_iterator{data->begin(), data->end(), *regex};
else
regit++;
if (regit == std::sregex_iterator{}) regit = std::sregex_iterator{data->begin(), data->end(), *regex};
else regit++;
if (regit == std::sregex_iterator{})
{
unmatched_prefix_end = data->cend();
log.log<Logger::Level::Debug>("distance: {}"_f(std::distance(unmatched_prefix_begin, unmatched_prefix_end)));
log.debug("distance: {}"_f(std::distance(unmatched_prefix_begin, unmatched_prefix_end)));
}
else
unmatched_prefix_end = (*regit)[0].first;
else unmatched_prefix_end = (*regit)[0].first;
co_yield
{
std::string_view
@@ -31,8 +27,7 @@ namespace biu
},
regit
};
if (regit == std::sregex_iterator{})
break;
if (regit == std::sregex_iterator{}) break;
unmatched_prefix_begin = (*regit)[0].second;
}
}
@@ -45,8 +40,7 @@ namespace biu
for (auto matched : find(data, regex))
{
result.append(matched.first);
if (matched.second != std::sregex_iterator{})
result.append(function(*matched.second));
if (matched.second != std::sregex_iterator{}) result.append(function(*matched.second));
}
return result;
}

View File

@@ -6,6 +6,11 @@ int main()
a = "world";
a.apply([](auto& value) { value += "!"; });
auto b = a.get();
auto lock = a.lock(nullptr, nullptr);
auto lock = a.lock();
*lock = "!";
static_assert(std::same_as<decltype(a.apply([](auto& value) { value += "!"; })), biu::Atomic<std::string>&>);
static_assert(std::same_as<decltype(a.apply([](auto&) { return 3; })), int>);
static_assert(std::same_as<decltype(a.apply([](auto&) {}, [](auto&){ return true; }, 1s)), bool>);
static_assert
(std::same_as<decltype(a.apply([](auto&) { return 3; }, [](auto&){ return true; }, 1s)), std::optional<int>>);
}

View File

@@ -60,7 +60,7 @@ inputs: rec
{ src = inputs.topInputs.kylin-virtual-keyboard; };
biu = inputs.pkgs.callPackage ./biu
{
inherit nameof zpp-bits;
inherit nameof zpp-bits tgbot-cpp;
stdenv = inputs.pkgs.gcc14Stdenv;
fmt = inputs.pkgs.fmt_11.overrideAttrs (prev: { patches = prev.patches or [] ++ [ ./biu/fmt.patch ]; });
};