mirror of
https://github.com/CHN-beta/nixos.git
synced 2026-01-12 02:09:26 +08:00
localPackages.biu: merge repo
This commit is contained in:
3
.clangd
Normal file
3
.clangd
Normal file
@@ -0,0 +1,3 @@
|
||||
CompileFlags:
|
||||
Add: [ -Wall, -Wextra, -std=c++23 ]
|
||||
Compiler: gcc
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
result
|
||||
result-man
|
||||
outputs
|
||||
.direnv
|
||||
|
||||
17
flake.lock
generated
17
flake.lock
generated
@@ -54,22 +54,6 @@
|
||||
"url": "https://flakehub.com/f/zhaofengli/attic/0.1.%2A.tar.gz"
|
||||
}
|
||||
},
|
||||
"biu": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1711969538,
|
||||
"narHash": "sha256-wGw+f7okXUDueWrUjRVqPb3Kx/OwIP8xrfvYRXbrAww=",
|
||||
"owner": "CHN-beta",
|
||||
"repo": "biu",
|
||||
"rev": "dbdc36394271f859f25cabaceed971898741a1c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "CHN-beta",
|
||||
"repo": "biu",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"blurred-wallpaper": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
@@ -1953,7 +1937,6 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"aagl": "aagl",
|
||||
"biu": "biu",
|
||||
"blurred-wallpaper": "blurred-wallpaper",
|
||||
"chaotic": "chaotic",
|
||||
"citation-style-language": "citation-style-language",
|
||||
|
||||
10
flake.nix
10
flake.nix
@@ -68,7 +68,6 @@
|
||||
lmod = { url = "github:TACC/Lmod"; flake = false; };
|
||||
mumax = { url = "github:CHN-beta/mumax"; flake = false; };
|
||||
kylin-virtual-keyboard = { url = "git+https://gitee.com/openkylin/kylin-virtual-keyboard.git"; flake = false; };
|
||||
biu = { url = "github:CHN-beta/biu"; flake = false; };
|
||||
};
|
||||
|
||||
outputs = inputs:
|
||||
@@ -175,5 +174,14 @@
|
||||
overlays.default = final: prev:
|
||||
{ localPackages = (import ./local/pkgs { inherit (inputs) lib; pkgs = final; topInputs = inputs; }); };
|
||||
config.archive = false;
|
||||
devShell.x86_64-linux = let inherit (inputs.self.nixosConfigurations.pc) pkgs; in pkgs.mkShell
|
||||
{
|
||||
packages = with pkgs; [ pkg-config cmake ninja clang-tools_17 ];
|
||||
buildInputs =
|
||||
(with pkgs; [ fmt boost magic-enum libbacktrace eigen range-v3 ])
|
||||
++ (with pkgs.localPackages; [ concurrencpp tgbot-cpp nameof ]);
|
||||
# hardeningDisable = [ "all" ];
|
||||
# NIX_DEBUG = "1";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
45
local/pkgs/biu/CMakeLists.txt
Normal file
45
local/pkgs/biu/CMakeLists.txt
Normal file
@@ -0,0 +1,45 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(biu LANGUAGES CXX)
|
||||
enable_testing()
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message("Setting build type to 'Release' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
find_package(magic_enum REQUIRED)
|
||||
find_package(fmt REQUIRED)
|
||||
find_package(Boost REQUIRED COMPONENTS headers iostreams)
|
||||
# find_package(concurrencpp REQUIRED)
|
||||
find_package(Eigen3 REQUIRED)
|
||||
find_package(range-v3 REQUIRED)
|
||||
find_path(NAMEOF_INCLUDE_DIR nameof.hpp REQUIRED)
|
||||
# find_path(TGBOTCPP_INCLUDE_DIR tgbot/tgbot.h REQUIRED)
|
||||
# find_library(TGBOTCPP_LIB libTgBot.a REQUIRED)
|
||||
# find_path(BACKTRACE_INCLUDE_DIR backtrace.h REQUIRED)
|
||||
# find_library(BACKTRACE_LIB backtrace REQUIRED)
|
||||
|
||||
# add_library(biu SHARED src/common.cpp src/logger.cpp src/string.cpp)
|
||||
add_library(biu SHARED src/common.cpp)
|
||||
target_include_directories(biu PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
${NAMEOF_INCLUDE_DIR} ${TGBOTCPP_INCLUDE_DIR})
|
||||
target_link_libraries(biu PUBLIC
|
||||
magic_enum::magic_enum
|
||||
fmt::fmt
|
||||
Boost::headers Boost::iostreams
|
||||
# concurrencpp::concurrencpp
|
||||
Eigen3::Eigen
|
||||
range-v3::range-v3)
|
||||
# ${TGBOTCPP_LIB} ${BACKTRACE_LIB})
|
||||
set_property(TARGET biu PROPERTY CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
|
||||
install(TARGETS biu EXPORT biuConfig)
|
||||
install(EXPORT biuConfig NAMESPACE ${PROJECT_NAME}:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/biu)
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
get_property(ImportedTargets DIRECTORY "${CMAKE_SOURCE_DIR}" PROPERTY IMPORTED_TARGETS)
|
||||
message("Imported targets: ${ImportedTargets}")
|
||||
message("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}")
|
||||
10
local/pkgs/biu/default.nix
Normal file
10
local/pkgs/biu/default.nix
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
stdenv, cmake,
|
||||
magic-enum, fmt, boost, eigen, range-v3, nameof
|
||||
}: stdenv.mkDerivation
|
||||
{
|
||||
name = "biu";
|
||||
src = ./.;
|
||||
buildInputs = [ magic-enum fmt boost eigen range-v3 nameof ];
|
||||
nativeBuildInputs = [ cmake ];
|
||||
}
|
||||
10
local/pkgs/biu/include/biu.hpp
Normal file
10
local/pkgs/biu/include/biu.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
# pragma once
|
||||
// # include <biu/atomic/atomic.tpp>
|
||||
// # include <biu/called_by.hpp>
|
||||
# include <biu/common.tpp>
|
||||
// # include <biu/concepts.tpp>
|
||||
// # include <biu/format.tpp>
|
||||
// # include <biu/logger.tpp>
|
||||
// # include <biu/smartref.tpp>
|
||||
// # include <biu/string.tpp>
|
||||
# include <biu/eigen.hpp>
|
||||
41
local/pkgs/biu/include/biu/atomic/atomic.hpp
Normal file
41
local/pkgs/biu/include/biu/atomic/atomic.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
# pragma once
|
||||
# include <biu/logger.hpp>
|
||||
|
||||
namespace biu::detail_
|
||||
{
|
||||
template <DecayedType ValueType> class AtomicBase<ValueType, true>
|
||||
: public Logger::ObjectMonitor<Atomic<ValueType, true>>, protected AtomicBase<ValueType, false>
|
||||
{
|
||||
using DeepBase_ = AtomicBase<ValueType, false>;
|
||||
using DeepBase_::AtomicBase;
|
||||
public: class TimeoutException : public Logger::Exception<TimeoutException>
|
||||
{
|
||||
using Logger::Exception<TimeoutException>::Exception;
|
||||
};
|
||||
|
||||
protected: template
|
||||
<
|
||||
bool ReturnFunctionResult,
|
||||
typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t, bool Nothrow = false
|
||||
> static auto apply_
|
||||
(
|
||||
auto&& atomic, auto&& function,
|
||||
ConditionFunction&& condition_function = nullptr, Duration timeout = nullptr
|
||||
) -> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(atomic), ReturnFunctionResult, ConditionFunction, Duration, Nothrow>
|
||||
requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(atomic), ConditionFunction, Duration>;
|
||||
|
||||
protected: template <bool Nothrow = false, typename Duration = std::nullptr_t> static auto wait_
|
||||
(auto&& atomic, auto&& condition_function, Duration timeout = nullptr)
|
||||
-> DeepBase_::template WaitReturnType_<decltype(atomic), decltype(condition_function), Duration, Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), Duration>;
|
||||
|
||||
protected: template
|
||||
<bool Nothrow = false, typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t>
|
||||
static auto lock_
|
||||
(auto&& atomic, ConditionFunction&& condition_function = nullptr, Duration timeout = nullptr)
|
||||
-> DeepBase_::template LockReturnType_<decltype(atomic), Duration, Nothrow>
|
||||
requires DeepBase_::template LockConstraint_<ConditionFunction, Duration>;
|
||||
};
|
||||
}
|
||||
0
local/pkgs/biu/include/biu/atomic/atomic.tpp
Normal file
0
local/pkgs/biu/include/biu/atomic/atomic.tpp
Normal file
267
local/pkgs/biu/include/biu/atomic/nolog.hpp
Normal file
267
local/pkgs/biu/include/biu/atomic/nolog.hpp
Normal file
@@ -0,0 +1,267 @@
|
||||
# pragma once
|
||||
# include <mutex>
|
||||
# include <optional>
|
||||
# include <condition_variable>
|
||||
# include <cstddef>
|
||||
# include <experimental/memory>
|
||||
# include <biu/common.hpp>
|
||||
# include <biu/concepts.hpp>
|
||||
# include <biu/called_by.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <DecayedType ValueType, bool UseLogger = true> class Atomic;
|
||||
namespace detail_
|
||||
{
|
||||
template <DecayedType ValueType, bool UseLogger> class AtomicBase;
|
||||
template <DecayedType ValueType> class AtomicBase<ValueType, false>
|
||||
{
|
||||
protected: mutable std::recursive_mutex Mutex_;
|
||||
protected: mutable std::condition_variable_any ConditionVariable_;
|
||||
protected: ValueType Value_;
|
||||
|
||||
AtomicBase() = default;
|
||||
AtomicBase(const ValueType& value);
|
||||
AtomicBase(ValueType&& value);
|
||||
|
||||
public: class TimeoutException : public std::exception
|
||||
{
|
||||
protected: std::string Message_;
|
||||
public: explicit TimeoutException(std::string message);
|
||||
public: const char* what() const noexcept override;
|
||||
};
|
||||
|
||||
// Apply a function to stored value.
|
||||
// Wait for some time (if provided) until condition funciton returns true (if provided)
|
||||
// before applying the function.
|
||||
protected: template
|
||||
<
|
||||
typename Function, typename Atomic,
|
||||
typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t
|
||||
>
|
||||
constexpr static bool ApplyConstraint_ =
|
||||
(
|
||||
(std::invocable<Function, MoveQualifiers<Atomic, ValueType>> && std::is_null_pointer_v<ConditionFunction>)
|
||||
|| (
|
||||
InvocableWithResult<ConditionFunction, bool, const ValueType&>
|
||||
&& (std::is_null_pointer_v<Duration> || SpecializationOf<Duration, std::chrono::duration>)
|
||||
)
|
||||
);
|
||||
protected: template
|
||||
<
|
||||
typename Function, typename Atomic, bool ReturnFunctionResult,
|
||||
typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t,
|
||||
bool Nothrow = false
|
||||
> using ApplyReturnType_ = std::conditional_t
|
||||
<
|
||||
Nothrow,
|
||||
std::conditional_t
|
||||
<
|
||||
ReturnFunctionResult && !std::is_void_v<std::invoke_result<Function, ValueType>>,
|
||||
std::optional<std::remove_cvref_t<FallbackIfNoTypeDeclared<std::invoke_result
|
||||
<Function, MoveQualifiers<Atomic, ValueType>, int>>>>,
|
||||
bool
|
||||
>,
|
||||
std::conditional_t
|
||||
<
|
||||
ReturnFunctionResult,
|
||||
std::invoke_result_t<Function, MoveQualifiers<Atomic, ValueType>>,
|
||||
Atomic&&
|
||||
>
|
||||
>;
|
||||
protected: template
|
||||
<
|
||||
bool ReturnFunctionResult,
|
||||
typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t,
|
||||
bool Nothrow = false
|
||||
> static auto apply_
|
||||
(
|
||||
auto&& atomic, auto&& function,
|
||||
ConditionFunction&& condition_function = nullptr, Duration timeout = nullptr
|
||||
) -> ApplyReturnType_
|
||||
<decltype(function), decltype(atomic), ReturnFunctionResult, ConditionFunction, Duration, Nothrow>
|
||||
requires ApplyConstraint_<decltype(function), decltype(atomic), ConditionFunction, Duration>;
|
||||
|
||||
// Wait until condition funciton returns true, with an optional timeout
|
||||
protected: template <typename ConditionFunction, typename Duration = std::nullptr_t>
|
||||
constexpr static bool WaitConstraint_
|
||||
= (InvocableWithResult<ConditionFunction, bool, const ValueType&>
|
||||
&& (std::is_null_pointer_v<Duration> || SpecializationOf<Duration, std::chrono::duration>));
|
||||
protected: template
|
||||
<typename Atomic, typename ConditionFunction, typename Duration = std::nullptr_t, bool Nothrow = false>
|
||||
using WaitReturnType_
|
||||
= std::conditional_t<Nothrow && !std::is_null_pointer_v<Duration>, bool, Atomic&&>;
|
||||
protected: template <bool Nothrow = false, typename Duration = std::nullptr_t> static auto wait_
|
||||
(auto&& atomic, auto&& condition_function, Duration timeout = nullptr)
|
||||
-> WaitReturnType_<decltype(atomic), decltype(condition_function), Duration, Nothrow>
|
||||
requires WaitConstraint_<decltype(condition_function), Duration>;
|
||||
|
||||
protected: template <typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t>
|
||||
constexpr static bool LockConstraint_
|
||||
= std::is_null_pointer_v<ConditionFunction> ||
|
||||
(
|
||||
InvocableWithResult<ConditionFunction, bool, const ValueType&>
|
||||
&& (std::is_null_pointer_v<Duration> || SpecializationOf<Duration, std::chrono::duration>)
|
||||
);
|
||||
protected: template <typename Atomic, typename Duration = std::nullptr_t, bool Nothrow = false>
|
||||
using LockReturnType_
|
||||
= std::conditional_t
|
||||
<
|
||||
Nothrow && !std::is_null_pointer_v<Duration>,
|
||||
std::optional<std::conditional_t
|
||||
<
|
||||
std::is_const_v<Atomic>,
|
||||
typename std::remove_reference_t<Atomic>::template Guard<true>,
|
||||
typename std::remove_reference_t<Atomic>::template Guard<false>
|
||||
>>,
|
||||
std::conditional_t
|
||||
<
|
||||
std::is_const_v<Atomic>,
|
||||
typename std::remove_reference_t<Atomic>::template Guard<true>,
|
||||
typename std::remove_reference_t<Atomic>::template Guard<false>
|
||||
>
|
||||
>;
|
||||
protected: template
|
||||
<bool Nothrow = false, typename ConditionFunction = std::nullptr_t, typename Duration = std::nullptr_t>
|
||||
static auto lock_
|
||||
(auto&& atomic, ConditionFunction&& condition_function = nullptr, Duration timeout = nullptr)
|
||||
-> LockReturnType_<decltype(atomic), Duration, Nothrow>
|
||||
requires LockConstraint_<ConditionFunction, Duration>;
|
||||
};
|
||||
}
|
||||
|
||||
// Thread safe wrapper of custom class
|
||||
template <DecayedType ValueType, bool UseLogger> class Atomic : public detail_::AtomicBase<ValueType, UseLogger>
|
||||
{
|
||||
public: Atomic() = default;
|
||||
public: Atomic(const ValueType& value);
|
||||
public: Atomic(ValueType&& value);
|
||||
public: template <bool OtherUseLogger> Atomic(const Atomic<ValueType, OtherUseLogger>& other);
|
||||
public: template <bool OtherUseLogger> Atomic(Atomic<ValueType, OtherUseLogger>&& other);
|
||||
public: Atomic<ValueType, UseLogger>& operator=(const ValueType& value);
|
||||
public: Atomic<ValueType, UseLogger>& operator=(ValueType&& value);
|
||||
public: template <bool OtherUseLogger>
|
||||
Atomic<ValueType, UseLogger>& operator=(const Atomic<ValueType, OtherUseLogger>& other);
|
||||
public: template <bool OtherUseLogger>
|
||||
Atomic<ValueType, UseLogger>& operator=(Atomic<ValueType, OtherUseLogger>&& other);
|
||||
public: ValueType get() const&;
|
||||
public: ValueType get() &&;
|
||||
public: operator ValueType() const&;
|
||||
public: operator ValueType() &&;
|
||||
|
||||
protected: using DeepBase_ = detail_::AtomicBase<ValueType, false>;
|
||||
|
||||
public: template <bool ReturnFunctionResult = false> auto apply(auto&& function) const&
|
||||
-> DeepBase_::template ApplyReturnType_<decltype(function), decltype(*this), ReturnFunctionResult>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this)>;
|
||||
public: template <bool ReturnFunctionResult = false> auto apply(auto&& function) &
|
||||
-> DeepBase_::template ApplyReturnType_<decltype(function), decltype(*this), ReturnFunctionResult>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this)>;
|
||||
public: template <bool ReturnFunctionResult = false> auto apply(auto&& function) &&
|
||||
-> DeepBase_::template ApplyReturnType_<decltype(function), decltype(*this), ReturnFunctionResult>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this)>;
|
||||
public: template <bool ReturnFunctionResult = false>
|
||||
auto apply(auto&& function, auto&& condition_function) const&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(*this), ReturnFunctionResult, decltype(condition_function)>
|
||||
requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function)>;
|
||||
public: template <bool ReturnFunctionResult = false> auto apply(auto&& function, auto&& condition_function) &
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(*this), ReturnFunctionResult, decltype(condition_function)>
|
||||
requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function)>;
|
||||
public: template <bool ReturnFunctionResult = false> auto apply(auto&& function, auto&& condition_function) &&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(*this), ReturnFunctionResult, decltype(condition_function)>
|
||||
requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function)>;
|
||||
public: template <bool ReturnFunctionResult = false, bool Nothrow = false>
|
||||
auto apply(auto&& function, auto&& condition_function, auto timeout) const&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<
|
||||
decltype(function), decltype(*this), ReturnFunctionResult,
|
||||
decltype(condition_function), decltype(timeout), Nothrow
|
||||
> requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function), decltype(timeout)>;
|
||||
public: template <bool ReturnFunctionResult = false, bool Nothrow = false>
|
||||
auto apply(auto&& function, auto&& condition_function, auto timeout) &
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<
|
||||
decltype(function), decltype(*this), ReturnFunctionResult,
|
||||
decltype(condition_function), decltype(timeout), Nothrow
|
||||
> requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function), decltype(timeout)>;
|
||||
public: template <bool ReturnFunctionResult = false, bool Nothrow = false>
|
||||
auto apply(auto&& function, auto&& condition_function, auto timeout) &&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<
|
||||
decltype(function), decltype(*this), ReturnFunctionResult,
|
||||
decltype(condition_function), decltype(timeout), Nothrow
|
||||
> requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function), decltype(timeout)>;
|
||||
|
||||
public: auto wait(auto&& condition_function) const&
|
||||
-> DeepBase_::template WaitReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function)>;
|
||||
public: auto wait(auto&& condition_function) &
|
||||
-> DeepBase_::template WaitReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function)>;
|
||||
public: auto wait(auto&& condition_function) &&
|
||||
-> DeepBase_::template WaitReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function)>;
|
||||
public: template <bool Nothrow = false> auto wait(auto&& condition_function, auto timeout) const&
|
||||
-> DeepBase_::template WaitReturnType_
|
||||
<decltype(*this), decltype(condition_function), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), decltype(timeout)>;
|
||||
public: template <bool Nothrow = false> auto wait(auto&& condition_function, auto timeout) &
|
||||
-> DeepBase_::template WaitReturnType_
|
||||
<decltype(*this), decltype(condition_function), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), decltype(timeout)>;
|
||||
public: template <bool Nothrow = false> auto wait(auto&& condition_function, auto timeout) &&
|
||||
-> DeepBase_::template WaitReturnType_
|
||||
<decltype(*this), decltype(condition_function), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), decltype(timeout)>;
|
||||
|
||||
// Attain lock from outside when constructing, and release when destructing.
|
||||
// For non-const variant, When destructing, ConditionVariable_.notify_all() is called.
|
||||
public: template <bool Const> class Guard
|
||||
{
|
||||
protected: std::unique_lock<std::recursive_mutex> Lock_;
|
||||
protected: std::experimental::observer_ptr
|
||||
<std::conditional_t<Const, const Atomic<ValueType, UseLogger>, Atomic<ValueType, UseLogger>>> Value_;
|
||||
|
||||
public: template <bool OtherConst> Guard(const Guard<OtherConst>& other) requires (Const || !OtherConst);
|
||||
public: Guard
|
||||
(decltype(Lock_)&& lock, decltype(Value_) value, CalledBy<detail_::AtomicBase<ValueType, UseLogger>>);
|
||||
public: ~Guard();
|
||||
|
||||
public: std::conditional_t<Const, const ValueType&, ValueType&> operator*() const&;
|
||||
public: std::conditional_t<Const, const ValueType*, ValueType*> operator->() const&;
|
||||
public: std::conditional_t<Const, const ValueType&, ValueType&> value() const&;
|
||||
public: auto operator*() const&& = delete;
|
||||
public: auto operator->() const&& = delete;
|
||||
public: auto value() const&& = delete;
|
||||
};
|
||||
|
||||
public: auto lock() const& -> DeepBase_::template LockReturnType_<decltype(*this)>
|
||||
requires DeepBase_::template LockConstraint_<>;
|
||||
public: auto lock() & -> DeepBase_::template LockReturnType_<decltype(*this)>
|
||||
requires DeepBase_::template LockConstraint_<>;
|
||||
public: auto lock() const&& = delete;
|
||||
public: auto lock(auto&& condition_function) const&
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function)>;
|
||||
public: auto lock(auto&& condition_function) &
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function)>;
|
||||
public: auto lock(auto&& condition_function) const&& = delete;
|
||||
public: template <bool Nothrow = false> auto lock(auto&& condition_function, auto timeout) const&
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function), decltype(timeout)>;
|
||||
public: template <bool Nothrow = false> auto lock(auto&& condition_function, auto timeout) &
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function), decltype(timeout)>;
|
||||
public: template <bool Nothrow = false> auto lock(auto&& condition_function, auto timeout) const&& = delete;
|
||||
};
|
||||
}
|
||||
366
local/pkgs/biu/include/biu/atomic/nolog.tpp
Normal file
366
local/pkgs/biu/include/biu/atomic/nolog.tpp
Normal file
@@ -0,0 +1,366 @@
|
||||
# pragma once
|
||||
# include <biu/atomic/nolog.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <DecayedType ValueType> detail_::AtomicBase<ValueType, false>::AtomicBase(const ValueType& value)
|
||||
: Value_{value} {}
|
||||
template <DecayedType ValueType> detail_::AtomicBase<ValueType, false>::AtomicBase(ValueType&& value)
|
||||
: Value_{std::move(value)} {}
|
||||
|
||||
template <DecayedType ValueType>
|
||||
detail_::AtomicBase<ValueType, false>::TimeoutException::TimeoutException(std::string)
|
||||
: Message_{"TimeoutException"} {}
|
||||
template <DecayedType ValueType>
|
||||
const char* detail_::AtomicBase<ValueType, false>::TimeoutException::what() const noexcept
|
||||
{return Message_.c_str();}
|
||||
|
||||
template <DecayedType ValueType>
|
||||
template <bool ReturnFunctionResult, typename ConditionFunction, typename Duration, bool Nothrow>
|
||||
auto detail_::AtomicBase<ValueType, false>::apply_
|
||||
(auto&& atomic, auto&& function, ConditionFunction&& condition_function, Duration timeout)
|
||||
-> ApplyReturnType_
|
||||
<decltype(function), decltype(atomic), ReturnFunctionResult, ConditionFunction, Duration, Nothrow>
|
||||
requires ApplyConstraint_<decltype(function), decltype(atomic), ConditionFunction, Duration>
|
||||
{
|
||||
std::unique_lock lock{atomic.Mutex_};
|
||||
|
||||
// try to meet the condition
|
||||
if constexpr (!std::is_null_pointer_v<ConditionFunction>)
|
||||
{
|
||||
if constexpr (std::is_null_pointer_v<Duration>)
|
||||
atomic.ConditionVariable_.wait(lock, [&]
|
||||
{return std::forward<ConditionFunction>(condition_function)(std::as_const(atomic.Value_));});
|
||||
else if (!atomic.ConditionVariable_.wait_for(lock, timeout, [&]
|
||||
{return std::forward<ConditionFunction>(condition_function)(std::as_const(atomic.Value_));}))
|
||||
{
|
||||
if constexpr (Nothrow)
|
||||
{
|
||||
if constexpr
|
||||
(ReturnFunctionResult && !std::is_void_v<std::invoke_result_t<decltype(function), ValueType>>)
|
||||
return std::nullopt;
|
||||
else return false;
|
||||
}
|
||||
else throw TimeoutException{};
|
||||
}
|
||||
}
|
||||
|
||||
// apply the function and return
|
||||
if constexpr (ReturnFunctionResult && !std::is_void_v<std::invoke_result_t<decltype(function), ValueType>>)
|
||||
{
|
||||
auto&& result = std::forward<decltype(function)>(function)
|
||||
(static_cast<MoveQualifiers<decltype(atomic), ValueType>&&>(atomic.Value_));
|
||||
if constexpr (!std::is_const_v<decltype(atomic)>) atomic.ConditionVariable_.notify_all();
|
||||
return std::forward<decltype(result)>(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::forward<decltype(function)>(function)
|
||||
(static_cast<MoveQualifiers<decltype(atomic), ValueType>&&>(atomic.Value_));
|
||||
if constexpr (!std::is_const_v<decltype(atomic)>) atomic.ConditionVariable_.notify_all();
|
||||
if constexpr (ReturnFunctionResult && std::is_void_v<std::invoke_result_t<decltype(function), ValueType>>)
|
||||
return;
|
||||
else return std::forward<decltype(atomic)>(atomic);
|
||||
}
|
||||
}
|
||||
|
||||
template <DecayedType ValueType> template <bool Nothrow, typename Duration>
|
||||
auto detail_::AtomicBase<ValueType, false>::wait_(auto&& atomic, auto&& condition_function, Duration timeout)
|
||||
-> WaitReturnType_<decltype(atomic), decltype(condition_function), Duration, Nothrow>
|
||||
requires WaitConstraint_<decltype(condition_function), Duration>
|
||||
{
|
||||
std::unique_lock lock{atomic.Mutex_};
|
||||
|
||||
if constexpr (std::is_null_pointer_v<Duration>)
|
||||
{
|
||||
atomic.ConditionVariable_.wait(lock, [&]
|
||||
{return std::forward<decltype(condition_function)>(condition_function)(std::as_const(atomic.Value_));});
|
||||
return std::forward<decltype(atomic)>(atomic);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!atomic.ConditionVariable_.wait_for(lock, timeout, [&]
|
||||
{return std::forward<decltype(condition_function)>(condition_function)(std::as_const(atomic.Value_));}))
|
||||
{
|
||||
if constexpr (Nothrow) return false;
|
||||
else throw TimeoutException{};
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (Nothrow) return true;
|
||||
else return std::forward<decltype(atomic)>(atomic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <DecayedType ValueType> template <bool Nothrow, typename ConditionFunction, typename Duration>
|
||||
auto detail_::AtomicBase<ValueType, false>::lock_
|
||||
(auto&& atomic, ConditionFunction&& condition_function, Duration timeout)
|
||||
-> LockReturnType_<decltype(atomic), Duration, Nothrow> requires LockConstraint_<ConditionFunction, Duration>
|
||||
{
|
||||
if constexpr (std::is_null_pointer_v<ConditionFunction>)
|
||||
return {std::unique_lock{atomic.Mutex_}, std::experimental::make_observer(&atomic), {}};
|
||||
else if constexpr (std::is_null_pointer_v<Duration>)
|
||||
{
|
||||
std::unique_lock lock{atomic.Mutex_};
|
||||
atomic.ConditionVariable_.wait(lock, [&]
|
||||
{return std::forward<ConditionFunction>(condition_function)(std::as_const(atomic.Value_));});
|
||||
return {std::move(lock), std::experimental::make_observer(&atomic), {}};
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_lock lock{atomic.Mutex_};
|
||||
if (!atomic.ConditionVariable_.wait_for(lock, timeout, [&]
|
||||
{return std::forward<ConditionFunction>(condition_function)(std::as_const(atomic.Value_));}))
|
||||
{
|
||||
if constexpr (Nothrow) return std::nullopt;
|
||||
else throw TimeoutException{};
|
||||
}
|
||||
else
|
||||
return {{std::move(lock), std::experimental::make_observer(&atomic), {}}};
|
||||
}
|
||||
}
|
||||
|
||||
template <DecayedType ValueType, bool UseLogger> Atomic<ValueType, UseLogger>::Atomic(const ValueType& value)
|
||||
: detail_::AtomicBase<ValueType, UseLogger>{value} {}
|
||||
template <DecayedType ValueType, bool UseLogger> Atomic<ValueType, UseLogger>::Atomic(ValueType&& value)
|
||||
: detail_::AtomicBase<ValueType, UseLogger>{std::move(value)} {}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool OtherUseLogger>
|
||||
Atomic<ValueType, UseLogger>::Atomic(const Atomic<ValueType, OtherUseLogger>& other)
|
||||
: detail_::AtomicBase<ValueType, UseLogger>{other} {}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool OtherUseLogger>
|
||||
Atomic<ValueType, UseLogger>::Atomic(Atomic<ValueType, OtherUseLogger>&& other)
|
||||
: detail_::AtomicBase<ValueType, UseLogger>{std::move(other)} {}
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
Atomic<ValueType, UseLogger>& Atomic<ValueType, UseLogger>::operator=(const ValueType& value)
|
||||
{
|
||||
std::scoped_lock lock{DeepBase_::Mutex_};
|
||||
DeepBase_::Value_ = value;
|
||||
DeepBase_::ConditionVariable_.notify_all();
|
||||
return *this;
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
Atomic<ValueType, UseLogger>& Atomic<ValueType, UseLogger>::operator=(ValueType&& value)
|
||||
{
|
||||
std::scoped_lock lock{DeepBase_::Mutex_};
|
||||
DeepBase_::Value_ = std::move(value);
|
||||
DeepBase_::ConditionVariable_.notify_all();
|
||||
return *this;
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool OtherUseLogger>
|
||||
Atomic<ValueType, UseLogger>& operator=(const Atomic<ValueType, OtherUseLogger>& other)
|
||||
{
|
||||
std::scoped_lock lock{DeepBase_::Mutex_};
|
||||
DeepBase_::Value_ = value;
|
||||
DeepBase_::ConditionVariable_.notify_all();
|
||||
return *this;
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool OtherUseLogger>
|
||||
Atomic<ValueType, UseLogger>& operator=(Atomic<ValueType, OtherUseLogger>&& other)
|
||||
{
|
||||
std::scoped_lock lock{DeepBase_::Mutex_};
|
||||
DeepBase_::Value_ = std::move(value);
|
||||
DeepBase_::ConditionVariable_.notify_all();
|
||||
return *this;
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> ValueType Atomic<ValueType, UseLogger>::get() const&
|
||||
{
|
||||
std::scoped_lock lock{DeepBase_::Mutex_};
|
||||
return DeepBase_::Value_;
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> ValueType Atomic<ValueType, UseLogger>::get() &&
|
||||
{
|
||||
std::scoped_lock lock{DeepBase_::Mutex_};
|
||||
return std::move(DeepBase_::Value_);
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> Atomic<ValueType, UseLogger>::operator ValueType() const&
|
||||
{return get();}
|
||||
template <DecayedType ValueType, bool UseLogger> Atomic<ValueType, UseLogger>::operator ValueType() &&
|
||||
{return std::move(*this).get();}
|
||||
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function) const&
|
||||
-> DeepBase_::template ApplyReturnType_<decltype(function), decltype(*this), ReturnFunctionResult>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this)>
|
||||
{return apply_<ReturnFunctionResult>(*this, std::forward<decltype(function)>(function));}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function) &
|
||||
-> DeepBase_::template ApplyReturnType_<decltype(function), decltype(*this), ReturnFunctionResult>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this)>
|
||||
{return apply_<ReturnFunctionResult>(*this, std::forward<decltype(function)>(function));}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function) &&
|
||||
-> DeepBase_::template ApplyReturnType_<decltype(function), decltype(*this), ReturnFunctionResult>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this)>
|
||||
{return apply_<ReturnFunctionResult>(std::move(*this), std::forward<decltype(function)>(function));}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function, auto&& condition_function) const&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(*this), ReturnFunctionResult, decltype(condition_function)>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this), decltype(condition_function)>
|
||||
{
|
||||
return apply_<ReturnFunctionResult>
|
||||
(
|
||||
*this, std::forward<decltype(function)>(function),
|
||||
std::forward<decltype(condition_function)>(condition_function)
|
||||
);
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function, auto&& condition_function) &
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(*this), ReturnFunctionResult, decltype(condition_function)>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this), decltype(condition_function)>
|
||||
{
|
||||
return apply_<ReturnFunctionResult>
|
||||
(
|
||||
*this, std::forward<decltype(function)>(function),
|
||||
std::forward<decltype(condition_function)>(condition_function)
|
||||
);
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function, auto&& condition_function) &&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<decltype(function), decltype(*this), ReturnFunctionResult, decltype(condition_function)>
|
||||
requires DeepBase_::template ApplyConstraint_<decltype(function), decltype(*this), decltype(condition_function)>
|
||||
{
|
||||
return apply_<ReturnFunctionResult>
|
||||
(
|
||||
std::move(*this), std::forward<decltype(function)>(function),
|
||||
std::forward<decltype(condition_function)>(condition_function)
|
||||
);
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult, bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function, auto&& condition_function, auto timeout) const&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<
|
||||
decltype(function), decltype(*this), ReturnFunctionResult,
|
||||
decltype(condition_function), decltype(timeout), Nothrow
|
||||
> requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function), decltype(timeout)>
|
||||
{
|
||||
return apply_<ReturnFunctionResult, Nothrow>
|
||||
(
|
||||
*this, std::forward<decltype(function)>(function),
|
||||
std::forward<decltype(condition_function)>(condition_function), timeout
|
||||
);
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult, bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function, auto&& condition_function, auto timeout) &
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<
|
||||
decltype(function), decltype(*this), ReturnFunctionResult,
|
||||
decltype(condition_function), decltype(timeout), Nothrow
|
||||
> requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function), decltype(timeout)>
|
||||
{
|
||||
return apply_<ReturnFunctionResult, Nothrow>
|
||||
(
|
||||
*this, std::forward<decltype(function)>(function),
|
||||
std::forward<decltype(condition_function)>(condition_function), timeout
|
||||
);
|
||||
}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool ReturnFunctionResult, bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::apply(auto&& function, auto&& condition_function, auto timeout) &&
|
||||
-> DeepBase_::template ApplyReturnType_
|
||||
<
|
||||
decltype(function), decltype(*this), ReturnFunctionResult,
|
||||
decltype(condition_function), decltype(timeout), Nothrow
|
||||
> requires DeepBase_::template ApplyConstraint_
|
||||
<decltype(function), decltype(*this), decltype(condition_function), decltype(timeout)>
|
||||
{
|
||||
return apply_<ReturnFunctionResult, Nothrow>
|
||||
(
|
||||
std::move(*this), std::forward<decltype(function)>(function),
|
||||
std::forward<decltype(condition_function)>(condition_function), timeout
|
||||
);
|
||||
}
|
||||
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
auto Atomic<ValueType, UseLogger>::wait(auto&& condition_function) const&
|
||||
-> DeepBase_::template WaitReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function)>
|
||||
{return wait_(*this, std::forward<decltype(condition_function)>(condition_function));}
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
auto Atomic<ValueType, UseLogger>::wait(auto&& condition_function) &
|
||||
-> DeepBase_::template WaitReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function)>
|
||||
{return wait_(*this, std::forward<decltype(condition_function)>(condition_function));}
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
auto Atomic<ValueType, UseLogger>::wait(auto&& condition_function) &&
|
||||
-> DeepBase_::template WaitReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function)>
|
||||
{return wait_(std::move(*this), std::forward<decltype(condition_function)>(condition_function));}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::wait(auto&& condition_function, auto timeout) const&
|
||||
-> DeepBase_::template WaitReturnType_
|
||||
<decltype(*this), decltype(condition_function), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), decltype(timeout)>
|
||||
{return wait_<Nothrow>(*this, std::forward<decltype(condition_function)>(condition_function), timeout);}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::wait(auto&& condition_function, auto timeout) &
|
||||
-> DeepBase_::template WaitReturnType_
|
||||
<decltype(*this), decltype(condition_function), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), decltype(timeout)>
|
||||
{return wait_<Nothrow>(*this, std::forward<decltype(condition_function)>(condition_function), timeout);}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::wait(auto&& condition_function, auto timeout) &&
|
||||
-> DeepBase_::template WaitReturnType_
|
||||
<decltype(*this), decltype(condition_function), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template WaitConstraint_<decltype(condition_function), decltype(timeout)>
|
||||
{
|
||||
return wait_<Nothrow>
|
||||
(std::move(*this), std::forward<decltype(condition_function)>(condition_function), timeout);
|
||||
}
|
||||
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Const> template <bool OtherConst>
|
||||
Atomic<ValueType, UseLogger>::Guard<Const>::Guard(const Guard<OtherConst>& other)
|
||||
requires (Const || !OtherConst)
|
||||
: Lock_{other.Lock_}, Value_{other.Value_} {}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Const>
|
||||
Atomic<ValueType, UseLogger>::Guard<Const>::Guard
|
||||
(decltype(Lock_)&& lock, decltype(Value_) value, CalledBy<detail_::AtomicBase<ValueType, UseLogger>>)
|
||||
: Lock_{std::move(lock)}, Value_{value} {}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Const>
|
||||
Atomic<ValueType, UseLogger>::Guard<Const>::~Guard()
|
||||
{Value_->ConditionVariable_.notify_all();}
|
||||
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Const>
|
||||
std::conditional_t<Const, const ValueType&, ValueType&>
|
||||
Atomic<ValueType, UseLogger>::Guard<Const>::operator*() const&
|
||||
{return Value_->Value_;}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Const>
|
||||
std::conditional_t<Const, const ValueType*, ValueType*>
|
||||
Atomic<ValueType, UseLogger>::Guard<Const>::operator->() const&
|
||||
{return &Value_->Value_;}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Const>
|
||||
std::conditional_t<Const, const ValueType&, ValueType&>
|
||||
Atomic<ValueType, UseLogger>::Guard<Const>::value() const&
|
||||
{return Value_->Value_;}
|
||||
|
||||
template <DecayedType ValueType, bool UseLogger> auto Atomic<ValueType, UseLogger>::lock() const&
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this)> requires DeepBase_::template LockConstraint_<>
|
||||
{return lock_(*this);}
|
||||
template <DecayedType ValueType, bool UseLogger> auto Atomic<ValueType, UseLogger>::lock() &
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this)> requires DeepBase_::template LockConstraint_<>
|
||||
{return lock_(*this);}
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
auto Atomic<ValueType, UseLogger>::lock(auto&& condition_function) const&
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function)>
|
||||
{return lock_(*this, condition_function);}
|
||||
template <DecayedType ValueType, bool UseLogger>
|
||||
auto Atomic<ValueType, UseLogger>::lock(auto&& condition_function) &
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(condition_function)>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function)>
|
||||
{return lock_(*this, condition_function);}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::lock(auto&& condition_function, auto timeout) const&
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function), decltype(timeout)>
|
||||
{return lock_<Nothrow>(*this, condition_function, timeout);}
|
||||
template <DecayedType ValueType, bool UseLogger> template <bool Nothrow>
|
||||
auto Atomic<ValueType, UseLogger>::lock(auto&& condition_function, auto timeout) &
|
||||
-> DeepBase_::template LockReturnType_<decltype(*this), decltype(timeout), Nothrow>
|
||||
requires DeepBase_::template LockConstraint_<decltype(condition_function), decltype(timeout)>
|
||||
{return lock_<Nothrow>(*this, condition_function, timeout);}
|
||||
}
|
||||
10
local/pkgs/biu/include/biu/called_by.hpp
Normal file
10
local/pkgs/biu/include/biu/called_by.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
# pragma once
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename AllowedType> class CalledBy
|
||||
{
|
||||
protected: CalledBy() = default;
|
||||
friend AllowedType;
|
||||
};
|
||||
}
|
||||
66
local/pkgs/biu/include/biu/common.hpp
Normal file
66
local/pkgs/biu/include/biu/common.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
# pragma once
|
||||
# include <regex>
|
||||
# include <fmt/format.h>
|
||||
# include <magic_enum.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
std::size_t hash(auto&&... objs);
|
||||
[[gnu::always_inline]] void unused(auto&&...);
|
||||
|
||||
using uint128_t = __uint128_t;
|
||||
|
||||
inline namespace literals
|
||||
{
|
||||
using namespace std::literals;
|
||||
using namespace fmt::literals;
|
||||
std::regex operator""_re(const char* str, std::size_t len);
|
||||
}
|
||||
|
||||
inline namespace stream_operators { using namespace magic_enum::iostream_operators; }
|
||||
|
||||
struct CaseInsensitiveStringLessComparator
|
||||
{
|
||||
template <typename String> constexpr bool operator()(const String& s1, const String& s2) const;
|
||||
};
|
||||
|
||||
namespace detail_
|
||||
{
|
||||
template <typename T> struct RemoveMemberPointerHelper { using Type = T; };
|
||||
template <typename Class, typename Member> struct RemoveMemberPointerHelper<Member Class::*>
|
||||
{ using Type = Member; };
|
||||
}
|
||||
template <typename MemberPointer> using RemoveMemberPointer
|
||||
= typename detail_::RemoveMemberPointerHelper<MemberPointer>::Type;
|
||||
|
||||
[[noreturn]] void block_forever();
|
||||
|
||||
namespace detail_
|
||||
{
|
||||
template <typename From, typename To> struct MoveQualifiersHelper
|
||||
{
|
||||
protected: static constexpr bool Const_ = std::is_const_v<From>;
|
||||
protected: static constexpr bool Volatile_ = std::is_volatile_v<From>;
|
||||
protected: static constexpr bool Reference_ = std::is_reference_v<From>;
|
||||
protected: static constexpr bool Lvalue_ = std::is_lvalue_reference_v<From>;
|
||||
protected: using NoCvrefType_ = std::remove_cvref_t<To>;
|
||||
protected: using NoCvType_
|
||||
= std::conditional_t<Reference_, std::conditional_t<Lvalue_, NoCvrefType_&, NoCvrefType_&&>, NoCvrefType_>;
|
||||
protected: using NoConstType_ = std::conditional_t<Volatile_, volatile NoCvType_, NoCvType_>;
|
||||
public: using Type = std::conditional_t<Const_, const NoConstType_, NoConstType_>;
|
||||
};
|
||||
}
|
||||
template <typename From, typename To> using MoveQualifiers
|
||||
= typename detail_::MoveQualifiersHelper<From, To>::Type;
|
||||
|
||||
namespace detail_
|
||||
{
|
||||
template <typename T, typename Fallback = void> struct FallbackIfNoTypeDeclaredHelper { using Type = Fallback; };
|
||||
template <typename T, typename Fallback> requires requires { typename T::Type; }
|
||||
struct FallbackIfNoTypeDeclaredHelper<T, Fallback> { using Type = typename T::Type; };
|
||||
template <typename T, typename Fallback> requires requires {typename T::type;}
|
||||
struct FallbackIfNoTypeDeclaredHelper<T, Fallback> { using Type = typename T::type; };
|
||||
}
|
||||
template <typename T, typename Fallback = void> using FallbackIfNoTypeDeclared
|
||||
= typename detail_::FallbackIfNoTypeDeclaredHelper<T, Fallback>::Type;
|
||||
}
|
||||
24
local/pkgs/biu/include/biu/common.tpp
Normal file
24
local/pkgs/biu/include/biu/common.tpp
Normal file
@@ -0,0 +1,24 @@
|
||||
# pragma once
|
||||
# include <boost/functional/hash.hpp>
|
||||
# include <biu/common.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
inline void unused(auto&&...) {}
|
||||
inline std::size_t hash(auto&&... objs)
|
||||
{
|
||||
std::size_t result = 0;
|
||||
(boost::hash_combine(result, objs), ...);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename String> inline constexpr bool CaseInsensitiveStringLessComparator::operator()
|
||||
(const String& s1, const String& s2) const
|
||||
{
|
||||
return std::lexicographical_compare
|
||||
(
|
||||
s1.begin(), s1.end(), s2.begin(), s2.end(),
|
||||
[](char c1, char c2){return std::tolower(c1) < std::tolower(c2);}
|
||||
);
|
||||
}
|
||||
}
|
||||
47
local/pkgs/biu/include/biu/concepts.hpp
Normal file
47
local/pkgs/biu/include/biu/concepts.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
# pragma once
|
||||
# include <concepts>
|
||||
# include <tuple>
|
||||
# include <type_traits>
|
||||
# include <complex>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename T> concept DecayedType = std::same_as<std::decay_t<T>, T>;
|
||||
|
||||
namespace detail_::specialization_of_detail_
|
||||
{
|
||||
template <typename Tuple> struct DropFirstMemberOfTupleHelper;
|
||||
template <typename First, typename... Others> struct DropFirstMemberOfTupleHelper<std::tuple<First, Others...>>
|
||||
{using Type = std::tuple<Others...>;};
|
||||
template <typename ProvidedArgs, typename ActualArgs> consteval bool check_provided_args();
|
||||
template <typename Class, template <typename...> typename Template> struct SpecializationOfHelper
|
||||
{template <typename... ProvidedArgs> consteval static bool check_provided_args();};
|
||||
template <template <typename...> typename Template, typename... ActualArgs>
|
||||
struct SpecializationOfHelper<Template<ActualArgs...>, Template>
|
||||
{template <typename... ProvidedArgs> consteval static bool check_provided_args();};
|
||||
}
|
||||
template <typename Class, template <typename...> typename Template, typename... ProvidedArgs>
|
||||
concept SpecializationOf
|
||||
= detail_::specialization_of_detail_::SpecializationOfHelper<std::decay_t<Class>, Template>
|
||||
::template check_provided_args<ProvidedArgs...>();
|
||||
|
||||
template <typename T> concept CompletedType = sizeof(T) == sizeof(T);
|
||||
|
||||
template <typename From, typename To> concept ImplicitlyConvertibleTo = std::is_convertible<From, To>::value;
|
||||
template <typename To, typename From> concept ImplicitlyConvertibleFrom = std::is_convertible<From, To>::value;
|
||||
template <typename From, typename To> concept ExplicitlyConvertibleTo = std::is_constructible<To, From>::value;
|
||||
template <typename To, typename From> concept ExplicitlyConvertibleFrom = std::is_constructible<To, From>::value;
|
||||
template <typename From, typename To> concept ConvertibleTo
|
||||
= ImplicitlyConvertibleTo<From, To> || ExplicitlyConvertibleTo<From, To>;
|
||||
template <typename From, typename To> concept ConvertibleFrom = ConvertibleTo<From, To>;
|
||||
|
||||
template <typename Function, auto... Args> concept ConstevalInvokable
|
||||
= requires() {typename std::type_identity_t<int[(Function()(Args...), 1)]>;};
|
||||
|
||||
template <typename T> concept Enumerable = std::is_enum_v<T>;
|
||||
|
||||
template <typename Function, typename Result, typename... Args> concept InvocableWithResult
|
||||
= std::is_invocable_r_v<Result, Function, Args...>;
|
||||
|
||||
template <typename T> concept Arithmetic = std::is_arithmetic<T>::value || SpecializationOf<T, std::complex>;
|
||||
}
|
||||
34
local/pkgs/biu/include/biu/concepts.tpp
Normal file
34
local/pkgs/biu/include/biu/concepts.tpp
Normal file
@@ -0,0 +1,34 @@
|
||||
# pragma once
|
||||
# include <tuple>
|
||||
# include <biu/concepts.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename ProvidedArgs, typename ActualArgs> consteval bool
|
||||
detail_::specialization_of_detail_::check_provided_args()
|
||||
{
|
||||
if constexpr (std::tuple_size_v<ProvidedArgs> == 0)
|
||||
return true;
|
||||
else if constexpr (std::tuple_size_v<ActualArgs> == 0)
|
||||
return false;
|
||||
else if constexpr
|
||||
(std::same_as<std::tuple_element_t<0, ProvidedArgs>, std::tuple_element_t<0, ActualArgs>>)
|
||||
return check_provided_args
|
||||
<
|
||||
typename DropFirstMemberOfTupleHelper<ProvidedArgs>::Type,
|
||||
typename DropFirstMemberOfTupleHelper<ActualArgs>::Type
|
||||
>();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
template <typename Class, template <typename...> typename Template> template <typename... ProvidedArgs> consteval
|
||||
bool detail_::specialization_of_detail_::SpecializationOfHelper<Class, Template>::check_provided_args()
|
||||
{ return false; }
|
||||
template <template <typename...> typename Template, typename... ActualArgs> template <typename... ProvidedArgs>
|
||||
consteval bool detail_::specialization_of_detail_::SpecializationOfHelper
|
||||
<Template<ActualArgs...>, Template>::check_provided_args()
|
||||
{
|
||||
return specialization_of_detail_::check_provided_args
|
||||
<std::tuple<ProvidedArgs...>, std::tuple<ActualArgs...>>();
|
||||
}
|
||||
}
|
||||
24
local/pkgs/biu/include/biu/eigen.hpp
Normal file
24
local/pkgs/biu/include/biu/eigen.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
# pragma once
|
||||
# include <vector>
|
||||
# include <Eigen/Dense>
|
||||
# include <biu/concepts.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
namespace detail_
|
||||
{
|
||||
template <std::size_t M, std::size_t N = 1> struct ToEigenHelper {};
|
||||
struct FromEigenHelper {};
|
||||
consteval int eigen_size(std::size_t n);
|
||||
}
|
||||
template <std::size_t M, std::size_t N = 1> inline constexpr detail_::ToEigenHelper<M, N> toEigen;
|
||||
inline constexpr detail_::FromEigenHelper fromEigen;
|
||||
|
||||
template <Arithmetic T, std::size_t N> Eigen::Vector<T, detail_::eigen_size(N)> operator|
|
||||
(const std::vector<T>& input, const detail_::ToEigenHelper<N>&);
|
||||
template <Arithmetic T, std::size_t M, std::size_t N>
|
||||
Eigen::Matrix<T, detail_::eigen_size(M), detail_::eigen_size(N)> operator|
|
||||
(const std::vector<std::vector<T>>& input, const detail_::ToEigenHelper<M, N>&);
|
||||
template <Arithmetic T, int M, int N> std::conditional_t<N == 1, std::vector<T>, std::vector<std::vector<T>>>
|
||||
operator|(const Eigen::Matrix<T, M, N>& input, const detail_::FromEigenHelper&);
|
||||
}
|
||||
58
local/pkgs/biu/include/biu/eigen.tpp
Normal file
58
local/pkgs/biu/include/biu/eigen.tpp
Normal file
@@ -0,0 +1,58 @@
|
||||
# pragma once
|
||||
# include <span>
|
||||
# include <ranges>
|
||||
# include <biu/eigen.hpp>
|
||||
// # include <biu/logger.hpp>
|
||||
# include <range/v3/view.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
consteval int detail_::eigen_size(std::size_t n)
|
||||
{ return n == std::dynamic_extent ? Eigen::Dynamic : static_cast<int>(n); }
|
||||
template <Arithmetic T, std::size_t N> inline Eigen::Vector<T, detail_::eigen_size(N)> operator|
|
||||
(const std::vector<T>& input, const detail_::ToEigenHelper<N>&)
|
||||
{
|
||||
if constexpr (N == std::dynamic_extent)
|
||||
return { input.data(), input.size() };
|
||||
else
|
||||
return { input.data() };
|
||||
}
|
||||
template <Arithmetic T, std::size_t M, std::size_t N>
|
||||
inline Eigen::Matrix<T, detail_::eigen_size(M), detail_::eigen_size(N)> operator|
|
||||
(const std::vector<std::vector<T>>& input, const detail_::ToEigenHelper<M, N>&)
|
||||
{
|
||||
Eigen::Matrix<T, detail_::eigen_size(M), detail_::eigen_size(N)> output;
|
||||
if constexpr (M == std::dynamic_extent || N == std::dynamic_extent)
|
||||
{
|
||||
if constexpr (M != std::dynamic_extent)
|
||||
output.resize(M, input.size() > 0 ? input[0].size() : 0);
|
||||
else if constexpr (N != std::dynamic_extent)
|
||||
output.resize(input.size(), N);
|
||||
else
|
||||
output.resize(input.size(), input.size() > 0 ? input[0].size() : 0);
|
||||
}
|
||||
// 如果列是动态的,那么就要检查每一行的列数是否相同
|
||||
/*
|
||||
if constexpr (N == std::dynamic_extent)
|
||||
if ((input | std::views::transform([](const auto& row) { return row.size(); }) | std::ranges::unique).size() > 1)
|
||||
Logger::Guard().log<Logger::Level::Error>("The number of columns is not the same in each row.");
|
||||
*/
|
||||
for (unsigned i = 0; i < M; i++)
|
||||
for (unsigned j = 0; j < N; j++)
|
||||
output(i, j) = input[i][j];
|
||||
return output;
|
||||
}
|
||||
template <Arithmetic T, int M, int N> inline std::conditional_t<N == 1, std::vector<T>, std::vector<std::vector<T>>>
|
||||
operator|(const Eigen::Matrix<T, M, N>& input, const detail_::FromEigenHelper&)
|
||||
{
|
||||
if constexpr (N == 1)
|
||||
return { input.data(), input.data() + input.size() };
|
||||
else
|
||||
{
|
||||
std::vector<std::vector<T>> output(input.rows());
|
||||
for (unsigned i = 0; i < input.rows(); i++)
|
||||
output[i] = { input.row(i).data(), input.row(i).data() + input.cols() };
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
72
local/pkgs/biu/include/biu/format.hpp
Normal file
72
local/pkgs/biu/include/biu/format.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
# pragma once
|
||||
# include <variant>
|
||||
# include <experimental/memory>
|
||||
# include <fmt/ostream.h>
|
||||
# include <biu/string.hpp>
|
||||
# include <biu/concepts.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename T, typename Char = char> concept Formattable = fmt::is_formattable<T, Char>::value;
|
||||
|
||||
namespace detail_
|
||||
{
|
||||
template <typename Char, Char... c> struct FormatLiteralHelper : protected BasicStaticString<Char, c...>
|
||||
{template <typename... Param> std::basic_string<Char> operator()(Param&&... param) const;};
|
||||
}
|
||||
namespace literals
|
||||
{template <typename Char, Char... c> consteval detail_::FormatLiteralHelper<Char, c...> operator""_f();}
|
||||
|
||||
namespace detail_
|
||||
{
|
||||
template <typename T> concept OptionalWrap
|
||||
= SpecializationOf<T, std::optional> || SpecializationOf<T, std::shared_ptr>
|
||||
|| SpecializationOf<T, std::weak_ptr> || SpecializationOf<T, std::unique_ptr>
|
||||
|| SpecializationOf<T, std::experimental::observer_ptr>;
|
||||
template <typename Wrap> struct UnderlyingTypeOfOptionalWrap;
|
||||
template <typename Wrap> requires requires() {typename Wrap::value_type;}
|
||||
struct UnderlyingTypeOfOptionalWrap<Wrap>
|
||||
{using Type = std::remove_cvref_t<typename Wrap::value_type>;};
|
||||
template <typename Wrap> requires requires() {typename Wrap::element_type;}
|
||||
struct UnderlyingTypeOfOptionalWrap<Wrap>
|
||||
{using Type = std::remove_cvref_t<typename Wrap::element_type>;};
|
||||
template <typename T> struct FormatterReuseProxy
|
||||
{
|
||||
constexpr auto parse(fmt::format_parse_context& ctx)
|
||||
-> std::invoke_result_t<decltype(&fmt::format_parse_context::begin), fmt::format_parse_context>;
|
||||
};
|
||||
template <typename T>
|
||||
requires (!SpecializationOf<T, std::weak_ptr> && std::default_initializable<fmt::formatter<T>>)
|
||||
struct FormatterReuseProxy<T> : fmt::formatter<T> {};
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename Char, typename... Ts> requires (sizeof...(Ts) > 0) basic_ostream<Char>& operator<<
|
||||
(basic_ostream<Char>& os, const variant<Ts...>& value);
|
||||
}
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
using namespace biu::stream_operators;
|
||||
|
||||
template <typename Char, biu::detail_::OptionalWrap Wrap> struct formatter<Wrap, Char>
|
||||
: biu::detail_::FormatterReuseProxy<typename biu::detail_::UnderlyingTypeOfOptionalWrap<Wrap>::Type>
|
||||
{
|
||||
template <typename FormatContext> auto format(const Wrap& wrap, FormatContext& ctx)
|
||||
-> std::invoke_result_t<decltype(&FormatContext::out), FormatContext>;
|
||||
};
|
||||
|
||||
template <typename Char, biu::Enumerable T> struct formatter<T, Char>
|
||||
{
|
||||
bool full = false;
|
||||
constexpr auto parse(fmt::format_parse_context& ctx)
|
||||
-> std::invoke_result_t<decltype(&fmt::format_parse_context::begin), fmt::format_parse_context>;
|
||||
template <typename FormatContext> auto format(const T& value, FormatContext& ctx)
|
||||
-> std::invoke_result_t<decltype(&FormatContext::out), FormatContext>;
|
||||
};
|
||||
|
||||
template <typename Char, typename... Ts> struct formatter<std::variant<Ts...>, Char>
|
||||
: basic_ostream_formatter<Char> {};
|
||||
}
|
||||
122
local/pkgs/biu/include/biu/format.tpp
Normal file
122
local/pkgs/biu/include/biu/format.tpp
Normal file
@@ -0,0 +1,122 @@
|
||||
# pragma once
|
||||
# include <nameof.hpp>
|
||||
# include <biu/format.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename Char, Char... c> template <typename... Param>
|
||||
std::basic_string<Char> detail_::FormatLiteralHelper<Char, c...>::operator() (Param&&... param) const
|
||||
{return fmt::format(BasicStaticString<Char, c...>::StringView, std::forward<Param>(param)...);}
|
||||
template <typename Char, Char... c> consteval
|
||||
detail_::FormatLiteralHelper<Char, c...> literals::operator""_f()
|
||||
{return {};}
|
||||
|
||||
template <typename T> constexpr
|
||||
auto detail_::FormatterReuseProxy<T>::parse(fmt::format_parse_context& ctx)
|
||||
-> std::invoke_result_t<decltype(&fmt::format_parse_context::begin), fmt::format_parse_context>
|
||||
{
|
||||
if (ctx.begin() != ctx.end() && *ctx.begin() != '}')
|
||||
throw fmt::format_error
|
||||
(
|
||||
"{} do not support to be format, so the wrapper should not have any format syntax."_f
|
||||
(nameof::nameof_full_type<T>())
|
||||
);
|
||||
return ctx.begin();
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename Char, typename... Ts> requires (sizeof...(Ts) > 0)
|
||||
basic_ostream<Char>& operator<<(basic_ostream<Char>& os, const variant<Ts...>& value)
|
||||
{
|
||||
using namespace biu::literals;
|
||||
auto try_print = [&]<typename T>
|
||||
{
|
||||
if (holds_alternative<T>(value))
|
||||
{
|
||||
if constexpr (biu::Formattable<T, Char>)
|
||||
os << "({}: {})"_f(nameof::nameof_full_type<T>(), get<T>(value));
|
||||
else
|
||||
os << "({}: {})"_f(nameof::nameof_full_type<T>(), "non-null unformattable value");
|
||||
}
|
||||
};
|
||||
(try_print.template operator()<Ts>(), ...);
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
template <typename Char, biu::detail_::OptionalWrap Wrap> template <typename FormatContext>
|
||||
auto formatter<Wrap, Char>::format(const Wrap& wrap, FormatContext& ctx)
|
||||
-> std::invoke_result_t<decltype(&FormatContext::out), FormatContext>
|
||||
{
|
||||
using namespace biu::literals;
|
||||
using namespace biu::stream_operators;
|
||||
using value_t = biu::detail_::UnderlyingTypeOfOptionalWrap<Wrap>::Type;
|
||||
auto format_value_type = [&, this](const value_t& value)
|
||||
{
|
||||
if constexpr (!biu::Formattable<value_t, Char>)
|
||||
return format_to(ctx.out(), "non-null unformattable value");
|
||||
else if constexpr (std::default_initializable<formatter<value_t>>)
|
||||
biu::detail_::FormatterReuseProxy<value_t>::format(value, ctx);
|
||||
else
|
||||
format_to(ctx.out(), "{}", value);
|
||||
};
|
||||
format_to(ctx.out(), "(");
|
||||
if constexpr (biu::SpecializationOf<Wrap, std::optional>)
|
||||
{
|
||||
if (wrap)
|
||||
format_value_type(*wrap);
|
||||
else
|
||||
format_to(ctx.out(), "null");
|
||||
}
|
||||
else if constexpr (biu::SpecializationOf<Wrap, std::weak_ptr>)
|
||||
{
|
||||
if (auto shared = wrap.lock())
|
||||
{
|
||||
format_to(ctx.out(), "{} ", ptr(shared.get()));
|
||||
format_value_type(*shared);
|
||||
}
|
||||
else
|
||||
format_to(ctx.out(), "null");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wrap)
|
||||
{
|
||||
format_to(ctx.out(), "{} ", ptr(wrap.get()));
|
||||
format_value_type(*wrap);
|
||||
}
|
||||
else
|
||||
format_to(ctx.out(), "null");
|
||||
}
|
||||
return format_to(ctx.out(), ")");
|
||||
}
|
||||
|
||||
template <typename Char, biu::Enumerable T> constexpr
|
||||
auto formatter<T, Char>::parse(format_parse_context& ctx)
|
||||
-> std::invoke_result_t<decltype(&format_parse_context::begin), format_parse_context>
|
||||
{
|
||||
auto it = ctx.begin();
|
||||
if (it != ctx.end() && *it == 'f')
|
||||
{
|
||||
full = true;
|
||||
it++;
|
||||
}
|
||||
if (it != ctx.end() && *it != '}')
|
||||
throw format_error{"syntax error."};
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename Char, biu::Enumerable T> template <typename FormatContext>
|
||||
auto formatter<T, Char>::format(const T& value, FormatContext& ctx)
|
||||
-> std::invoke_result_t<decltype(&FormatContext::out), FormatContext>
|
||||
{
|
||||
if (full)
|
||||
return format_to(ctx.out(), "{}::{}", nameof::nameof_type<T>(), nameof::nameof_enum(value));
|
||||
else
|
||||
return format_to(ctx.out(), "{}", nameof::nameof_enum(value));
|
||||
}
|
||||
}
|
||||
103
local/pkgs/biu/include/biu/logger.hpp
Normal file
103
local/pkgs/biu/include/biu/logger.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
# pragma once
|
||||
# include <map>
|
||||
# include <boost/stacktrace.hpp>
|
||||
# include <biu/atomic/nolog.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
class Logger
|
||||
{
|
||||
// All the member function corresponding to stacktrace should be inlined
|
||||
// All the public function (including public function of member class) should be thread safe.
|
||||
|
||||
public: Logger() = delete;
|
||||
|
||||
// Setup output stream and log level in a thread-safe way
|
||||
public: enum class Level
|
||||
{
|
||||
None,
|
||||
Error,
|
||||
Access,
|
||||
Info,
|
||||
Debug
|
||||
};
|
||||
protected: struct LoggerConfigType_
|
||||
{
|
||||
std::experimental::observer_ptr<std::ostream> Stream;
|
||||
std::shared_ptr<std::ostream> StreamStorage;
|
||||
Logger::Level Level;
|
||||
};
|
||||
protected: static Atomic<std::optional<LoggerConfigType_>, false> 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_;
|
||||
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);
|
||||
|
||||
// Monitor the lifetime of an object
|
||||
// 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_;
|
||||
|
||||
// call log<Debug>("create {type} at {address}.");
|
||||
protected: [[gnu::always_inline]] ObjectMonitor();
|
||||
|
||||
// call log<Debug>("destroy {type} at {address} after {duration} ms.");
|
||||
protected: [[gnu::always_inline]] virtual ~ObjectMonitor();
|
||||
};
|
||||
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_;
|
||||
|
||||
public: template <typename FinalException> class Exception : public std::exception
|
||||
{
|
||||
protected: const std::string Message_;
|
||||
protected: const boost::stacktrace::stacktrace Stacktrace_;
|
||||
|
||||
public: explicit Exception(const std::string& message);
|
||||
public: const char* what() const noexcept final {return Message_.c_str();}
|
||||
};
|
||||
|
||||
// Monitor the start and end of a function, as well as corresponding thread.
|
||||
// This object should be construct at the beginning of the function, and should never be passed to another
|
||||
// function or thread.
|
||||
public: class Guard
|
||||
{
|
||||
protected: thread_local static unsigned Indent_;
|
||||
protected: const std::chrono::time_point<std::chrono::steady_clock> StartTime_;
|
||||
|
||||
// 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();
|
||||
|
||||
// call log<Debug>("reached after {duration} ms.")
|
||||
public: [[gnu::always_inline]] void operator()() const;
|
||||
|
||||
// call log<Debug>("return {return} after {duration} ms.")
|
||||
public: template <typename T> [[gnu::always_inline]] T rtn(T&& value) const;
|
||||
|
||||
// print the following message if LoggerConfig_ is set and the level is higher than the level of the
|
||||
// LoggerConfig_
|
||||
// [ {time} {thread} {indent} {filename}:{line} {function_name} ] {message}
|
||||
public: template <Level L> [[gnu::always_inline]] void log(const std::string& message) const;
|
||||
|
||||
public: template <typename FinalException> [[gnu::always_inline]] void print_exception
|
||||
(
|
||||
const std::string& type, const std::string& message, const boost::stacktrace::stacktrace& stacktrace,
|
||||
CalledBy<Exception<FinalException>>
|
||||
) const;
|
||||
};
|
||||
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_;
|
||||
};
|
||||
}
|
||||
143
local/pkgs/biu/include/biu/logger.tpp
Normal file
143
local/pkgs/biu/include/biu/logger.tpp
Normal file
@@ -0,0 +1,143 @@
|
||||
# pragma once
|
||||
# define BOOST_STACKTRACE_USE_BACKTRACE
|
||||
# include <fmt/chrono.h>
|
||||
# include <biu/logger.hpp>
|
||||
# include <biu/common.hpp>
|
||||
# include <biu/format.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename T> Logger::ObjectMonitor<T>::ObjectMonitor()
|
||||
: 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>());
|
||||
}
|
||||
template <typename T> Logger::ObjectMonitor<T>::~ObjectMonitor()
|
||||
{
|
||||
Guard guard;
|
||||
guard.log<Level::Debug>("destroy {} at {} after {} ms."_f
|
||||
(
|
||||
nameof::nameof_full_type<T>(), fmt::ptr(this),
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>
|
||||
(std::chrono::steady_clock::now() - CreateTime_).count()
|
||||
));
|
||||
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>()));
|
||||
}
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
template <typename... Param> inline 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 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.");
|
||||
}
|
||||
inline 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()));
|
||||
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);
|
||||
}
|
||||
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()));
|
||||
}
|
||||
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
|
||||
{
|
||||
if (auto&& lock = LoggerConfig_.lock(); *lock && lock.value()->Level >= L)
|
||||
{
|
||||
static_assert(std::same_as<std::size_t, std::uint64_t>);
|
||||
auto time = std::chrono::system_clock::now();
|
||||
boost::stacktrace::stacktrace stack;
|
||||
*lock.value()->Stream << "[ {:%Y-%m-%d %H:%M:%S}:{:03} {:08x} {:04} {}:{} {} ] {}\n"_f
|
||||
(
|
||||
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(),
|
||||
Indent_,
|
||||
stack[0].source_file().empty() ? "??"s : stack[0].source_file(),
|
||||
stack[0].source_line() == 0 ? "??"s : "{}"_f(stack[0].source_line()),
|
||||
stack[0].name(),
|
||||
message
|
||||
) << std::flush;
|
||||
}
|
||||
}
|
||||
template <typename FinalException> inline void Logger::Guard::print_exception
|
||||
(
|
||||
const std::string& type, const std::string& message, const boost::stacktrace::stacktrace& stacktrace,
|
||||
CalledBy<Exception<FinalException>>
|
||||
) const
|
||||
{
|
||||
log<Level::Error>("{}: {}"_f(type, message));
|
||||
if (auto&& lock = LoggerConfig_.lock(); *lock && lock.value()->Level >= Logger::Level::Error)
|
||||
{
|
||||
static_assert(std::same_as<std::size_t, std::uint64_t>);
|
||||
for (auto frame : stacktrace)
|
||||
*lock.value()->Stream << "\tfrom {}:{} {}\n"_f
|
||||
(
|
||||
frame.source_file().empty() ? "??"s : frame.source_file(),
|
||||
frame.source_line() == 0 ? "??"s : "{}"_f(frame.source_line()),
|
||||
frame.name()
|
||||
);
|
||||
*lock.value()->Stream << std::flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
local/pkgs/biu/include/biu/smartref.hpp
Normal file
18
local/pkgs/biu/include/biu/smartref.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
# pragma once
|
||||
# include <memory>
|
||||
# include <type_traits>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
// store a reference to an lvalue, or a value (instead of a reference) copy or moved from an rvalue
|
||||
template <typename T> class SmartRef
|
||||
{
|
||||
protected: std::unique_ptr<T> Ptr_;
|
||||
protected: T& Ref_;
|
||||
|
||||
public: SmartRef(T& val);
|
||||
public: template <typename... Us> requires (std::is_constructible_v<T, Us...>) SmartRef(Us&&... val);
|
||||
public: T& operator*();
|
||||
public: T* operator->();
|
||||
};
|
||||
}
|
||||
13
local/pkgs/biu/include/biu/smartref.tpp
Normal file
13
local/pkgs/biu/include/biu/smartref.tpp
Normal file
@@ -0,0 +1,13 @@
|
||||
# pragma once
|
||||
# include <utility>
|
||||
# include <biu/smartref.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename T> inline SmartRef<T>::SmartRef(T& val) : Ref_(val) {}
|
||||
template <typename T> template <typename... Us> requires (std::is_constructible_v<T, Us...>)
|
||||
inline SmartRef<T>::SmartRef(Us&&... val)
|
||||
: Ptr_(std::make_unique<T>(std::forward<Us>(val)...)), Ref_(*Ptr_) {}
|
||||
template <typename T> inline T& SmartRef<T>::operator*() {return Ref_;}
|
||||
template <typename T> inline T* SmartRef<T>::operator->() {return &Ref_;}
|
||||
}
|
||||
111
local/pkgs/biu/include/biu/string.hpp
Normal file
111
local/pkgs/biu/include/biu/string.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
# pragma once
|
||||
# include <regex>
|
||||
# include <array>
|
||||
# include <string>
|
||||
# include <string_view>
|
||||
# include <iostream>
|
||||
# include <concurrencpp/concurrencpp.h>
|
||||
# include <biu/concepts.hpp>
|
||||
# include <biu/smartref.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
// Store a string in a static member of a class; or, use a class to represent a string.
|
||||
template <DecayedType Char, Char... c> struct BasicStaticString
|
||||
{
|
||||
static constexpr std::array<Char, sizeof...(c)> Array{c...};
|
||||
static constexpr std::basic_string_view<Char> StringView{Array.data(), sizeof...(c)};
|
||||
};
|
||||
template <char... c> using StaticString = BasicStaticString<char, c...>;
|
||||
inline namespace stream_operators
|
||||
{
|
||||
template <typename Char, Char... c>
|
||||
std::basic_ostream<Char>& operator<<(std::basic_ostream<Char>& os, BasicStaticString<Char, c...>);
|
||||
}
|
||||
inline namespace literals
|
||||
{ template <typename Char, Char... c> consteval BasicStaticString<Char, c...> operator""_ss(); }
|
||||
namespace detail_
|
||||
{
|
||||
template <typename C, typename T> struct SpecializationOfBasicStaticStringHelper : std::false_type {};
|
||||
template <typename C, C... c>
|
||||
struct SpecializationOfBasicStaticStringHelper<C, BasicStaticString<C, c...>> : std::true_type {};
|
||||
template <typename C, C... c>
|
||||
struct SpecializationOfBasicStaticStringHelper<void, BasicStaticString<C, c...>> : std::true_type {};
|
||||
template <typename T, typename C> concept SpecializationOfBasicStaticString
|
||||
= SpecializationOfBasicStaticStringHelper<std::decay_t<C>, std::decay_t<T>>::value;
|
||||
}
|
||||
template <typename T, typename C = void> concept SpecializationOfBasicStaticString
|
||||
= detail_::SpecializationOfBasicStaticString<T, C>
|
||||
&& detail_::SpecializationOfBasicStaticString<T, void>;
|
||||
template <typename T> concept SpecializationOfStaticString = SpecializationOfBasicStaticString<T, char>;
|
||||
|
||||
// Store a string in a fixed-size array
|
||||
template <DecayedType Char, std::size_t N> struct BasicFixedString
|
||||
{
|
||||
Char Data[N];
|
||||
constexpr static const std::size_t Size = N - 1;
|
||||
constexpr BasicFixedString(const Char (&str)[N]);
|
||||
};
|
||||
template <std::size_t N> using FixedString = BasicFixedString<char, N>;
|
||||
inline namespace stream_operators
|
||||
{
|
||||
template <typename Char, std::size_t N> std::basic_ostream<Char>& operator<<
|
||||
(std::basic_ostream<Char>& os, const BasicFixedString<Char, N>& str);
|
||||
}
|
||||
inline namespace literals { template <BasicFixedString FS> constexpr decltype(FS) operator""_fs(); }
|
||||
namespace detail_
|
||||
{
|
||||
template <typename C, typename T> struct SpecializationOfBasicFixedStringHelper : std::false_type {};
|
||||
template <typename C, std::size_t N>
|
||||
struct SpecializationOfBasicFixedStringHelper<C, BasicFixedString<C, N>> : std::true_type {};
|
||||
template <typename C, std::size_t N>
|
||||
struct SpecializationOfBasicFixedStringHelper<void, BasicFixedString<C, N>> : std::true_type {};
|
||||
template <typename T, typename C> concept SpecializationOfBasicFixedString
|
||||
= SpecializationOfBasicFixedStringHelper<std::decay_t<C>, std::decay_t<T>>::value;
|
||||
}
|
||||
template <typename T, typename C = void> concept SpecializationOfBasicFixedString
|
||||
= detail_::SpecializationOfBasicFixedString<T, C>
|
||||
&& detail_::SpecializationOfBasicFixedString<T, void>;
|
||||
template <typename T> concept SpecializationOfFixedString = SpecializationOfBasicFixedString<T, char>;
|
||||
|
||||
// Store a string with at most N characters
|
||||
template <DecayedType Char, std::size_t N> struct BasicVariableString
|
||||
{
|
||||
Char Data[N];
|
||||
std::size_t Size;
|
||||
constexpr static const std::size_t MaxSize = N - 1;
|
||||
template <std::size_t M> requires (M<=N) constexpr BasicVariableString(const Char (&str)[M]);
|
||||
};
|
||||
template <std::size_t N> using VariableString = BasicVariableString<char, N>;
|
||||
inline namespace stream_operators
|
||||
{
|
||||
template <typename Char, std::size_t N> std::basic_ostream<Char>& operator<<
|
||||
(std::basic_ostream<Char>& os, const BasicVariableString<Char, N>& str);
|
||||
}
|
||||
|
||||
namespace detail_
|
||||
{
|
||||
template <typename C, typename T> struct SpecializationOfBasicVariableStringHelper : std::false_type {};
|
||||
template <typename C, std::size_t N>
|
||||
struct SpecializationOfBasicVariableStringHelper<C, BasicVariableString<C, N>> : std::true_type {};
|
||||
template <typename C, std::size_t N>
|
||||
struct SpecializationOfBasicVariableStringHelper<void, BasicVariableString<C, N>> : std::true_type {};
|
||||
template <typename T, typename C> concept SpecializationOfBasicVariableString
|
||||
= SpecializationOfBasicVariableStringHelper<std::decay_t<C>, std::decay_t<T>>::value;
|
||||
}
|
||||
template <typename T, typename C = void> concept SpecializationOfBasicVariableString
|
||||
= detail_::SpecializationOfBasicVariableString<T, C>
|
||||
&& detail_::SpecializationOfBasicVariableString<T, void>;
|
||||
template <typename T> concept SpecializationOfVariableString = SpecializationOfBasicVariableString<T, char>;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
30
local/pkgs/biu/include/biu/string.tpp
Normal file
30
local/pkgs/biu/include/biu/string.tpp
Normal file
@@ -0,0 +1,30 @@
|
||||
# pragma once
|
||||
# include <biu/string.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
template <typename Char, Char... c> inline std::basic_ostream<Char>& stream_operators::operator<<
|
||||
(std::basic_ostream<Char>& os, BasicStaticString<Char, c...>)
|
||||
{ return os << std::basic_string_view{c...}; }
|
||||
template <typename Char, Char... c> consteval BasicStaticString<Char, c...> literals::operator""_ss()
|
||||
{ return {}; }
|
||||
|
||||
template <DecayedType Char, std::size_t N> constexpr
|
||||
BasicFixedString<Char, N>::BasicFixedString(const Char (&str)[N])
|
||||
{ std::copy_n(str, N, Data); }
|
||||
template <typename Char, std::size_t N> std::basic_ostream<Char>& stream_operators::operator<<
|
||||
(std::basic_ostream<Char>& os, const BasicFixedString<Char, N>& str)
|
||||
{ return os << std::basic_string_view<Char>(str.Data, str.Size); }
|
||||
template <BasicFixedString FS> constexpr decltype(FS) literals::operator""_fs()
|
||||
{ return FS; }
|
||||
|
||||
template <DecayedType Char, std::size_t N> template <std::size_t M> requires (M<=N) constexpr
|
||||
BasicVariableString<Char, N>::BasicVariableString(const Char (&str)[M]) : Size(M)
|
||||
{
|
||||
std::fill(Data, Data + N, '\0');
|
||||
std::copy_n(str, M, Data);
|
||||
}
|
||||
template <typename Char, std::size_t N> std::basic_ostream<Char>& stream_operators::operator<<
|
||||
(std::basic_ostream<Char>& os, const BasicVariableString<Char, N>& str)
|
||||
{ return os << std::basic_string_view<Char>(str.Data, str.Size); }
|
||||
}
|
||||
14
local/pkgs/biu/src/common.cpp
Normal file
14
local/pkgs/biu/src/common.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
# include <future>
|
||||
# include <utility>
|
||||
# include <biu.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
std::regex literals::operator""_re(const char* str, std::size_t len)
|
||||
{ return std::regex{str, len}; }
|
||||
void block_forever()
|
||||
{
|
||||
std::promise<void>().get_future().wait();
|
||||
std::unreachable();
|
||||
}
|
||||
}
|
||||
36
local/pkgs/biu/src/logger.cpp
Normal file
36
local/pkgs/biu/src/logger.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
# include <tgbot/tgbot.h>
|
||||
# include <biu.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
Atomic<std::optional<typename Logger::LoggerConfigType_>, false> Logger::LoggerConfig_;
|
||||
void Logger::init(std::experimental::observer_ptr<std::ostream> stream, Level level)
|
||||
{
|
||||
auto&& lock = LoggerConfig_.lock();
|
||||
lock->emplace(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);
|
||||
}
|
||||
|
||||
Atomic<std::optional<std::pair<std::string, std::string>>, false> 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)
|
||||
{
|
||||
if (auto&& lock = TelegramConfig_.lock(); *lock)
|
||||
{
|
||||
TgBot::Bot bot{lock.value()->first};
|
||||
bot.getApi().sendMessage(lock.value()->first, 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_;
|
||||
|
||||
thread_local unsigned Logger::Guard::Indent_ = 0;
|
||||
Atomic<std::map<std::size_t, std::size_t>, false> Logger::Threads_;
|
||||
}
|
||||
53
local/pkgs/biu/src/string.cpp
Normal file
53
local/pkgs/biu/src/string.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
# include <fmt/chrono.h>
|
||||
# include <biu.hpp>
|
||||
|
||||
namespace biu
|
||||
{
|
||||
concurrencpp::generator<std::pair<std::string_view, std::sregex_iterator>> string::find
|
||||
(SmartRef<const std::string> data, SmartRef<const std::regex> regex)
|
||||
{
|
||||
Logger::Guard log;
|
||||
std::string::const_iterator unmatched_prefix_begin = data->cbegin(), unmatched_prefix_end;
|
||||
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{})
|
||||
{
|
||||
unmatched_prefix_end = data->cend();
|
||||
log.log<Logger::Level::Debug>("distance: {}"_f(std::distance(unmatched_prefix_begin, unmatched_prefix_end)));
|
||||
}
|
||||
else
|
||||
unmatched_prefix_end = (*regit)[0].first;
|
||||
co_yield
|
||||
{
|
||||
std::string_view
|
||||
{
|
||||
&*unmatched_prefix_begin,
|
||||
static_cast<std::size_t>(std::distance(unmatched_prefix_begin, unmatched_prefix_end))
|
||||
},
|
||||
regit
|
||||
};
|
||||
if (regit == std::sregex_iterator{})
|
||||
break;
|
||||
unmatched_prefix_begin = (*regit)[0].second;
|
||||
}
|
||||
}
|
||||
|
||||
std::string string::replace
|
||||
(const std::string& data, const std::regex& regex, std::function<std::string(const std::smatch&)> function)
|
||||
{
|
||||
Logger::Guard log;
|
||||
std::string result;
|
||||
for (auto matched : find(data, regex))
|
||||
{
|
||||
result.append(matched.first);
|
||||
if (matched.second != std::sregex_iterator{})
|
||||
result.append(function(*matched.second));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ inputs: rec
|
||||
aocl = inputs.pkgs.callPackage ./aocl {};
|
||||
kylin-virtual-keyboard = inputs.pkgs.libsForQt5.callPackage ./kylin-virtual-keyboard
|
||||
{ src = inputs.topInputs.kylin-virtual-keyboard; };
|
||||
biu = inputs.pkgs.callPackage inputs.topInputs.biu { inherit nameof; };
|
||||
biu = inputs.pkgs.callPackage ./biu { inherit nameof; };
|
||||
|
||||
fromYaml = content: builtins.fromJSON (builtins.readFile
|
||||
(inputs.pkgs.runCommand "toJSON" {}
|
||||
|
||||
Reference in New Issue
Block a user