Apache Log4cxx  Version 1.6.0
Loading...
Searching...
No Matches
asyncbuffer.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#ifndef LOG4CXX_ASYNC_BUFFER_H
19#define LOG4CXX_ASYNC_BUFFER_H
20
22#include <functional>
23#include <vector>
24#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
25#include <fmt/args.h>
26#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
27#include <fmt/xchar.h>
28#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
29#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
30
31#if defined(__cpp_concepts) && 202002 <= __cpp_concepts && defined(__GNUC__) && __GNUC__ <= 12
32// GCC 12 has broken concepts
33#define LOG4CXX_CONCEPTS 0
34#elif defined(__cpp_concepts) && 202002 <= __cpp_concepts
35#define LOG4CXX_CONCEPTS 1
36#else
37#define LOG4CXX_CONCEPTS 0
38#endif
39
40#if LOG4CXX_CONCEPTS
41#include <concepts>
42#endif
43
44namespace LOG4CXX_NS
45{
46
47namespace helpers
48{
49
55class LOG4CXX_EXPORT AsyncBuffer
56{
57public: // ...structors
61
65
69
70public: // Operators
75 template <typename T>
76 AsyncBuffer& operator<<(const T& value)
77 {
78#if LOG4CXX_CONCEPTS
79#if LOG4CXX_LOGCHAR_IS_UTF8
80 if constexpr (requires(std::ostream& buf, T v) { buf << v; })
81 {
82 append([value](CharMessageBuffer& msgBuf)
83 {
84 msgBuf << value;
85 });
86 }
87#if LOG4CXX_WCHAR_T_API
88 else if constexpr (requires(std::wostream& buf, T v) { buf << v; })
89 {
90 append([value](WideMessageBuffer& msgBuf)
91 {
92 msgBuf << value;
93 });
94 }
95#endif // LOG4CXX_WCHAR_T_API
96 else
97 static_assert(false, "operator<<(std::ostream&) overload must be provided");
98#else // !LOG4CXX_LOGCHAR_IS_UTF8
99 if constexpr (requires(std::wostream& buf, T v) { buf << v; })
100 {
101 append([value](WideMessageBuffer& msgBuf)
102 {
103 msgBuf << value;
104 });
105 }
106 else if constexpr (requires(std::ostream& buf, T v) { buf << v; })
107 {
108 append([value](CharMessageBuffer& msgBuf)
109 {
110 msgBuf << value;
111 });
112 }
113 else
114 static_assert(false, "operator<<(std::wostream&) overload must be provided");
115#endif // !LOG4CXX_LOGCHAR_IS_UTF8
116#else // !LOG4CXX_CONCEPTS
117 append([value](LogCharMessageBuffer& msgBuf)
118 {
119 msgBuf << value;
120 });
121#endif // !LOG4CXX_CONCEPTS
122 return *this;
123 }
124
125#ifdef __cpp_init_captures // C++ >= 14
130 template <typename T>
131 AsyncBuffer& operator<<(const T&& rvalue)
132 {
133#if LOG4CXX_CONCEPTS
134#if LOG4CXX_LOGCHAR_IS_UTF8
135 if constexpr (requires(std::ostream& buf, T v) { buf << v; })
136 {
137 append([value = std::move(rvalue)](CharMessageBuffer& msgBuf)
138 {
139 msgBuf << value;
140 });
141 }
142#if LOG4CXX_WCHAR_T_API
143 else if constexpr (requires(std::wostream& buf, T v) { buf << v; })
144 {
145 append([value = std::move(rvalue)](WideMessageBuffer& msgBuf)
146 {
147 msgBuf << value;
148 });
149 }
150#endif // LOG4CXX_WCHAR_T_API
151 else
152 static_assert(false, "operator<<(std::ostream&) overload must be provided");
153#else // !LOG4CXX_LOGCHAR_IS_UTF8
154 if constexpr (requires(std::wostream& buf, T v) { buf << v; })
155 {
156 append([value = std::move(rvalue)](WideMessageBuffer& msgBuf)
157 {
158 msgBuf << value;
159 });
160 }
161 else if constexpr (requires(std::ostream& buf, T v) { buf << v; })
162 {
163 append([value = std::move(rvalue)](CharMessageBuffer& msgBuf)
164 {
165 msgBuf << value;
166 });
167 }
168 else
169 static_assert(false, "operator<<(std::wostream&) overload must be provided");
170#endif // !LOG4CXX_LOGCHAR_IS_UTF8
171#else // !LOG4CXX_CONCEPTS
172 append([value = std::move(rvalue)](LogCharMessageBuffer& msgBuf)
173 {
174 msgBuf << value;
175 });
176#endif // !LOG4CXX_CONCEPTS
177 return *this;
178 }
179
180#endif // __cpp_init_captures
181
182public: // Accessors
186 bool empty() const;
187
191 void renderMessage(LogCharMessageBuffer& msg) const;
192
193public: // Modifiers
197 void clear();
198
199#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
200 using StringViewType = fmt::basic_string_view<char>;
201 using FmtArgStore = fmt::dynamic_format_arg_store<fmt::format_context>;
202 template <typename... Args>
203 void setMessage(fmt::format_string<Args...> fmt_str, Args&&... args)
204 {
205 auto store = FmtArgStore();
206 ( store.push_back(std::forward<Args>(args)), ...);
207 initializeForFmt(std::move(fmt_str), std::move(store));
208 }
209
210#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
211 using WideStringViewType = fmt::basic_string_view<wchar_t>;
212 using WideFmtArgStore = fmt::dynamic_format_arg_store<fmt::wformat_context>;
213 template <typename... Args>
214 void setMessage(fmt::wformat_string<Args...> fmt_str, Args&&... args)
215 {
216 auto store = WideFmtArgStore();
217 ( store.push_back(std::forward<Args>(args)), ...);
218 initializeForFmt(std::move(fmt_str), std::move(store));
219 }
220#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
221#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
222
223private:
224 AsyncBuffer(const AsyncBuffer&) = delete;
225 AsyncBuffer& operator=(const AsyncBuffer&) = delete;
226
227 LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(Private, m_priv)
228#if LOG4CXX_CONCEPTS
229 using MessageBufferAppender = std::function<void(CharMessageBuffer&)>;
230
234 void append(const MessageBufferAppender& f);
235
236#if LOG4CXX_WCHAR_T_API
237 using WideMessageBufferAppender = std::function<void(WideMessageBuffer&)>;
238
242 void append(const WideMessageBufferAppender& f);
243#endif // LOG4CXX_WCHAR_T_API
244#else // !LOG4CXX_CONCEPTS
245 using MessageBufferAppender = std::function<void(LogCharMessageBuffer&)>;
246
250 void append(const MessageBufferAppender& f);
251#endif // !LOG4CXX_CONCEPTS
252
253#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
254 void initializeForFmt(StringViewType&& format_string, FmtArgStore&& args);
255
256#if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
257 void initializeForFmt(WideStringViewType&& format_string, WideFmtArgStore&& args);
258#endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
259#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
260};
261
262} // namespace helpers
263} // namespace LOG4CXX_NS
264
268
269#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 10000
289#define LOG4CXX_DEBUG_ASYNC(logger, message) do { \
290 if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isDebugEnabledFor(logger))) {\
291 ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
292 logger->addDebugEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
293
294#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
314#define LOG4CXX_DEBUG_FMT_ASYNC(logger, fmt, ...) do { \
315 if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isDebugEnabledFor(logger))) {\
316 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
317 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
318 logger->addDebugEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
319#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
320#else
321#define LOG4CXX_DEBUG_ASYNC(logger, message)
322#define LOG4CXX_DEBUG_FMT_ASYNC(logger, message)
323#endif
324
325#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 5000
337#define LOG4CXX_TRACE_ASYNC(logger, message) do { \
338 if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isTraceEnabledFor(logger))) {\
339 ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
340 logger->addTraceEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
341
342#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
355#define LOG4CXX_TRACE_FMT_ASYNC(logger, fmt, ...) do { \
356 if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isTraceEnabledFor(logger))) {\
357 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
358 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
359 logger->addTraceEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
360#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
361
362#else
363#define LOG4CXX_TRACE_ASYNC(logger, message)
364#define LOG4CXX_TRACE_FMT_ASYNC(logger, message)
365#endif
366
367#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 20000
384#define LOG4CXX_INFO_ASYNC(logger, message) do { \
385 if (::LOG4CXX_NS::Logger::isInfoEnabledFor(logger)) {\
386 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
387 logger->addInfoEvent(std::move(buf << message), LOG4CXX_LOCATION);\
388 }} while (0)
389
390#endif
391
392#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
409#define LOG4CXX_INFO_FMT_ASYNC(logger, fmt, ...) do { \
410 if (::LOG4CXX_NS::Logger::isInfoEnabledFor(logger)) {\
411 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
412 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
413 logger->addInfoEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
414#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
415
416#else
417#define LOG4CXX_INFO_ASYNC(logger, message)
418#define LOG4CXX_INFO_FMT_ASYNC(logger, message)
419#endif
420
421#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 30000
436#define LOG4CXX_WARN_ASYNC(logger, message) do { \
437 if (::LOG4CXX_NS::Logger::isWarnEnabledFor(logger)) {\
438 ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
439 logger->addWarnEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
440
441#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
457#define LOG4CXX_WARN_FMT_ASYNC(logger, fmt, ...) do { \
458 if (::LOG4CXX_NS::Logger::isWarnEnabledFor(logger)) {\
459 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
460 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
461 logger->addWarnEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
462#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
463
464#else
465#define LOG4CXX_WARN_ASYNC(logger, message)
466#define LOG4CXX_WARN_FMT_ASYNC(logger, message)
467#endif
468
469#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 40000
484#define LOG4CXX_ERROR_ASYNC(logger, message) do { \
485 if (::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
486 ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
487 logger->addErrorEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
488
489#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
505#define LOG4CXX_ERROR_FMT_ASYNC(logger, fmt, ...) do { \
506 if (::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
507 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
508 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
509 logger->addErrorEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
510#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
511
519#define LOG4CXX_ASSERT_ASYNC(logger, condition, message) do { \
520 if (!(condition) && ::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
521 ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
522 LOG4CXX_STACKTRACE \
523 logger->addErrorEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
524
525#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
536#define LOG4CXX_ASSERT_FMT_ASYNC(logger, condition, fmt, ...) do { \
537 if (!(condition) && ::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
538 LOG4CXX_STACKTRACE \
539 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
540 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
541 logger->addErrorEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
542#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
543
544#else
545#define LOG4CXX_ERROR_ASYNC(logger, message)
546#define LOG4CXX_ERROR_FMT_ASYNC(logger, message)
547#define LOG4CXX_ASSERT_ASYNC(logger, condition, message)
548#define LOG4CXX_ASSERT_FMT_ASYNC(logger, condition, message)
549#endif
550
551#if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 50000
563#define LOG4CXX_FATAL_ASYNC(logger, message) do { \
564 if (::LOG4CXX_NS::Logger::isFatalEnabledFor(logger)) {\
565 ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
566 logger->addFatalEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
567
568#if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
581#define LOG4CXX_FATAL_FMT_ASYNC(logger, fmt, ...) do { \
582 if (::LOG4CXX_NS::Logger::isFatalEnabledFor(logger)) {\
583 ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
584 buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
585 logger->addFatalEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
586#endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
587
588#else
589#define LOG4CXX_FATAL_ASYNC(logger, message)
590#define LOG4CXX_FATAL_FMT_ASYNC(logger, message)
591#endif
592
This class is used by the LOG4CXX_INFO_ASYNC and similar macros to support insertion operators.
Definition asyncbuffer.h:56
bool empty() const
Has no item been added to this?
fmt::dynamic_format_arg_store< fmt::format_context > FmtArgStore
Definition asyncbuffer.h:201
~AsyncBuffer()
Release resources.
fmt::basic_string_view< wchar_t > WideStringViewType
Definition asyncbuffer.h:211
fmt::dynamic_format_arg_store< fmt::wformat_context > WideFmtArgStore
Definition asyncbuffer.h:212
AsyncBuffer(AsyncBuffer &&other)
A new buffer with the content of other.
void setMessage(fmt::format_string< Args... > fmt_str, Args &&... args)
Definition asyncbuffer.h:203
void renderMessage(LogCharMessageBuffer &msg) const
Add text version of buffered values to msg.
AsyncBuffer()
An empty buffer.
void setMessage(fmt::wformat_string< Args... > fmt_str, Args &&... args)
Definition asyncbuffer.h:214
AsyncBuffer & operator<<(const T &value)
Append a function to this buffer that will convert value to text.
Definition asyncbuffer.h:76
void clear()
Remove all message appenders.
fmt::basic_string_view< char > StringViewType
Definition asyncbuffer.h:200
This class is used by the LOG4CXX_INFO and similar macros to support insertion operators in the messa...
Definition log4cxx/helpers/messagebuffer.h:40
This class is designed to support insertion operations in the message argument to the LOG4CXX_INFO an...
Definition log4cxx/helpers/messagebuffer.h:405
log4cxx::helpers::UniCharMessageBuffer & operator<<(log4cxx::helpers::UniCharMessageBuffer &mb, const QString &msg)
Definition log4cxx-qt/messagebuffer.h:24