bux API Reference 1.11.0
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
Loading...
Searching...
No Matches
ParaLog.h
Go to the documentation of this file.
1#pragma once
2
3#include "SyncLog.h" // bux::I_SyncLog, bux::I_ReenterableLog, bux::C_ReenterableOstream
4#include <concepts> // std::derived_from<>, std::convertible_to<>
5#include <functional> // std::function<>
6#include <list> // std::list<>
7#include <memory> // std::unique_ptr<>
8#include <sstream> // std::ostringstream
9#include <string_view> // std::string_view
10#include <vector> // std::vector<>
11
12namespace bux {
13
14//
15// Types
16//
17class C_ParaLog: public I_SyncLog
22{
23public:
24
25 // Data
26 class C_NodeProxy;
27 class C_NodeArrayProxy;
28
29 // Nonvirtuals
30 explicit C_ParaLog(T_LocalZone tz_ = T_LocalZone()): I_SyncLog(tz_) {}
31#ifndef _LIBCPP_HAS_NO_TIME_ZONE_DATABASE
32 explicit C_ParaLog(bool use_local_time): C_ParaLog(use_local_time? local_zone(): T_LocalZone()) {}
33#endif
34 template<class...T_Args>
35 bool addChild(T_Args&&...args);
36 template<class C_LogImpl, class C_Holder = typename C_AutoSinkHolderT<C_LogImpl>::type, class...T_Args>
37 bool addChildT(std::function<void(C_LogImpl&)> post_ctor = {}, E_LogLevel ll = LL_VERBOSE, T_Args&&...args);
38 template<typename F>
39 [[nodiscard]]C_NodeArrayProxy partitionBy(F f);
40
41 // Implement I_SyncLog
42 std::ostream *lockLog() override;
43 std::ostream *lockLog(E_LogLevel ll) override;
44 void unlockLog(bool flush) override;
45
46private:
47
48 // Types
49 struct C_Node;
50
51 using FC_Accept = std::function<bool(std::string_view)>;
52 using C_NodePtr = std::unique_ptr<C_Node>;
53
54 struct C_NodePartition
55 {
56 std::vector<std::pair<FC_Accept,C_NodePtr>> m_filteredNodes;
57 C_NodePtr m_elseNode;
58 };
59
60 struct C_Node
61 {
62 std::vector<std::unique_ptr<I_ReenterableLog>> m_loggers;
63 std::list<C_NodePartition> m_partitions;
64 };
65 friend class C_NodeProxy;
66
67 struct C_LockedNodePartition;
68
69 struct C_LockedNode
70 {
71 std::vector<std::pair<I_ReenterableLog*,std::ostream*>> m_loggers;
72 std::vector<C_LockedNodePartition> m_partitions;
73
74 void create_from(const C_Node &node, const std::function<std::ostream*(I_ReenterableLog&)> &to_log);
75 bool empty() const { return m_loggers.empty() && m_partitions.empty(); }
76 void log(std::string_view s, bool flush) const;
77 };
78
79 struct C_LockedNodePartition
80 {
81 std::vector<std::pair<const FC_Accept&,C_LockedNode>> m_filteredNodes;
82 C_LockedNode m_elseNode;
83
84 bool empty() const { return m_filteredNodes.empty() && m_elseNode.empty(); }
85 };
86
87 // Data
88 std::recursive_mutex m_lock;
89 C_Node m_root;
90 std::list<std::pair<C_LockedNode,std::ostringstream>> m_lockedStack;
91
92 // Nonvirtuals
93 std::ostream *lockLog(const std::function<std::ostream*(I_ReenterableLog&)> &to_log);
94};
95
97{
98public:
99
100 // Nonvirtuals
101 C_NodeArrayProxy(std::recursive_mutex &lock, C_NodePartition &nodePart): m_lock(&lock), m_nodePart(&nodePart) {}
102 [[nodiscard]]C_NodeProxy operator[](size_t i) const;
103 [[nodiscard]]C_NodeProxy matchedNone() const;
104 size_t sizeOfFilters() const { return m_nodePart->m_filteredNodes.size(); }
105
106private:
107
108 // Data
109 std::recursive_mutex *m_lock;
110 C_NodePartition *m_nodePart;
111
112 // Nonvirtuals
113 C_NodeProxy create_proxy(C_NodePtr &holder) const;
114};
115
117{
118public:
119
120 // Nonvirtuals
121 C_NodeProxy(std::recursive_mutex &lock, C_Node &node): m_lock(&lock), m_node(&node) {}
122 template<std::derived_from<I_ReenterableLog> T>
123 bool addChild(std::unique_ptr<T> &&snap) const
124 {
125 std::lock_guard _{*m_lock};
126 if (snap)
127 {
128 m_node->m_loggers.emplace_back(std::move(snap));
129 return true;
130 }
131 return false;
132 }
133 bool addChild(std::ostream &out, E_LogLevel ll = LL_VERBOSE) const
134 {
135 return addChild(std::make_unique<C_ReenterableOstream>(out, ll));
136 }
138 {
139 return addChild(std::make_unique<C_ReenterableOstreamSnap>(snap, ll));
140 }
141 template<class C_LogImpl, class C_Holder = typename C_AutoSinkHolderT<C_LogImpl>::type, class...T_Args>
142 bool addChildT(std::function<void(C_LogImpl&)> post_ctor = {}, E_LogLevel ll = LL_VERBOSE, T_Args&&...args) const
143 {
144 auto child = std::make_unique<C_ReenterableLoggerInside<C_LogImpl,C_Holder>>(ll, std::forward<T_Args>(args)...);
145 if (post_ctor)
146 post_ctor(child->impl());
147
148 return addChild(std::move(child));
149 }
150 [[nodiscard]]C_NodeArrayProxy partitionBy(std::convertible_to<FC_Accept> auto f) const
151 {
152 std::lock_guard _{*m_lock};
153 auto &dst = m_node->m_partitions.emplace_back();
154 dst.m_filteredNodes.emplace_back(std::piecewise_construct, std::forward_as_tuple(f), std::forward_as_tuple());
155 return {*m_lock, dst};
156 }
157 template<typename Filters>
158 [[nodiscard]]C_NodeArrayProxy partitionBy(Filters fs) const requires requires {
159 { *std::begin(fs) }-> std::convertible_to<FC_Accept>;
160 { std::size(fs) }-> std::convertible_to<size_t>;
161 std::end(fs);
162 }
163 {
164 std::lock_guard _{*m_lock};
165 auto &dst = m_node->m_partitions.emplace_back();
166 dst.m_filteredNodes.reserve(std::size(fs));
167 for (auto &&i: fs)
168 dst.m_filteredNodes.emplace_back(std::piecewise_construct, std::forward_as_tuple(i), std::forward_as_tuple());
169
170 return {*m_lock, dst};
171 }
172
173private:
174
175 // Data
176 std::recursive_mutex *m_lock;
177 C_Node *m_node;
178};
179
180//
181// Implement Class Member Templates
182//
183template<class...T_Args>
184bool C_ParaLog::addChild(T_Args&&...args)
185{
186 return C_NodeProxy{m_lock,m_root}.addChild(std::forward<T_Args>(args)...);
187}
188
189template<class C_LogImpl, class C_Holder, class...T_Args>
190bool C_ParaLog::addChildT(std::function<void(C_LogImpl&)> post_ctor, E_LogLevel ll, T_Args&&...args)
191{
192 return C_NodeProxy{m_lock,m_root}.addChildT<C_LogImpl,C_Holder>(post_ctor, ll, std::forward<T_Args>(args)...);
193}
194
195template<typename F>
197{
198 return C_NodeProxy{m_lock,m_root}.partitionBy(f);
199}
200
201} // namespace bux
@ LL_VERBOSE
More detailed or advanced information probably considered too much by some.
Definition LogLevel.h:14
C_NodeArrayProxy(std::recursive_mutex &lock, C_NodePartition &nodePart)
Definition ParaLog.h:101
C_NodeProxy operator[](size_t i) const
Definition ParaLog.cpp:8
C_NodeProxy matchedNone() const
Definition ParaLog.cpp:24
bool addChild(I_SnapT< std::ostream * > &snap, E_LogLevel ll=LL_VERBOSE) const
Definition ParaLog.h:137
bool addChild(std::unique_ptr< T > &&snap) const
Definition ParaLog.h:123
bool addChildT(std::function< void(C_LogImpl &)> post_ctor={}, E_LogLevel ll=LL_VERBOSE, T_Args &&...args) const
Definition ParaLog.h:142
C_NodeProxy(std::recursive_mutex &lock, C_Node &node)
Definition ParaLog.h:121
C_NodeArrayProxy partitionBy(Filters fs) const
Definition ParaLog.h:158
C_NodeArrayProxy partitionBy(std::convertible_to< FC_Accept > auto f) const
Definition ParaLog.h:150
bool addChild(std::ostream &out, E_LogLevel ll=LL_VERBOSE) const
Definition ParaLog.h:133
bool addChild(T_Args &&...args)
Definition ParaLog.h:184
C_ParaLog(bool use_local_time)
Definition ParaLog.h:32
C_NodeArrayProxy partitionBy(F f)
void unlockLog(bool flush) override
If the previous call to lockLog() returned null, the behavior is undefined.
Definition ParaLog.cpp:104
bool addChildT(std::function< void(C_LogImpl &)> post_ctor={}, E_LogLevel ll=LL_VERBOSE, T_Args &&...args)
Definition ParaLog.h:190
C_ParaLog(T_LocalZone tz_=T_LocalZone())
Definition ParaLog.h:30
std::ostream * lockLog() override
Return non-null pointer if possible.
Definition ParaLog.cpp:94
I_SyncLog(T_LocalZone tz_)
Definition SyncLog.h:29
THE common namespace of bux library.
Definition AtomiX.cpp:3
E_LogLevel
Definition LogLevel.h:9
@ LL_VERBOSE
More detailed or advanced information probably considered too much by some.
Definition LogLevel.h:14
const std::chrono::time_zone * T_LocalZone
Definition XPlatform.h:18
T_LocalZone local_zone()
Definition XPlatform.h:19
Thread-unsafe implementation is preferred for performance.
Definition SyncLog.h:35
< Parasitic Type
Definition SyncLog.h:169