Apache Log4cxx  Version 1.8.0
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 
44 namespace LOG4CXX_NS
45 {
46 
47 namespace helpers
48 {
49 
55 class LOG4CXX_EXPORT AsyncBuffer
56 {
57 public: // ...structors
61 
65 
69 
70 public: // 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 
182 public: // Accessors
186  bool empty() const;
187 
191  void renderMessage(LogCharMessageBuffer& msg) const;
192 
193 public: // 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(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(fmt_str, std::move(store));
219  }
220 #endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
221 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
222 
223 private:
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(MessageBufferAppender&& f);
235 
236 #if LOG4CXX_WCHAR_T_API
237  using WideMessageBufferAppender = std::function<void(WideMessageBuffer&)>;
238 
242  void append(WideMessageBufferAppender&& f);
243 #endif // LOG4CXX_WCHAR_T_API
244 #else // !LOG4CXX_CONCEPTS
245  using MessageBufferAppender = std::function<void(LogCharMessageBuffer&)>;
246 
250  void append(MessageBufferAppender&& f);
251 #endif // !LOG4CXX_CONCEPTS
252 
253 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
254  void initializeForFmt(const StringViewType& format_string, FmtArgStore&& args);
255 
256 #if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
257  void initializeForFmt(const WideStringViewType& format_string, WideFmtArgStore&& args);
258 #endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
259 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
260 
261 #if LOG4CXX_ABI_VERSION <= 15
262 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
263  void initializeForFmt(StringViewType&& format_string, FmtArgStore&& args);
264 
265 #if LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
266  void initializeForFmt(WideStringViewType&& format_string, WideFmtArgStore&& args);
267 #endif // LOG4CXX_WCHAR_T_API || LOG4CXX_LOGCHAR_IS_WCHAR
268 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
269 #endif // LOG4CXX_ABI_VERSION <= 15
270 };
271 
272 } // namespace helpers
273 } // namespace LOG4CXX_NS
274 
279 #if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 10000
299 #define LOG4CXX_DEBUG_ASYNC(logger, message) do { \
300  if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isDebugEnabledFor(logger))) {\
301  ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
302  logger->addDebugEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
303 
304 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
324 #define LOG4CXX_DEBUG_FMT_ASYNC(logger, fmt, ...) do { \
325  if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isDebugEnabledFor(logger))) {\
326  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
327  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
328  logger->addDebugEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
329 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
330 #else
331 #define LOG4CXX_DEBUG_ASYNC(logger, message)
332 #define LOG4CXX_DEBUG_FMT_ASYNC(logger, message)
333 #endif
334 
335 #if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 5000
347 #define LOG4CXX_TRACE_ASYNC(logger, message) do { \
348  if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isTraceEnabledFor(logger))) {\
349  ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
350  logger->addTraceEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
351 
352 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
365 #define LOG4CXX_TRACE_FMT_ASYNC(logger, fmt, ...) do { \
366  if (LOG4CXX_UNLIKELY(::LOG4CXX_NS::Logger::isTraceEnabledFor(logger))) {\
367  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
368  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
369  logger->addTraceEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
370 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
371 
372 #else
373 #define LOG4CXX_TRACE_ASYNC(logger, message)
374 #define LOG4CXX_TRACE_FMT_ASYNC(logger, message)
375 #endif
376 
377 #if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 20000
394 #define LOG4CXX_INFO_ASYNC(logger, message) do { \
395  if (::LOG4CXX_NS::Logger::isInfoEnabledFor(logger)) {\
396  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
397  logger->addInfoEvent(std::move(buf << message), LOG4CXX_LOCATION);\
398  }} while (0)
399 
400 #endif
401 
402 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
419 #define LOG4CXX_INFO_FMT_ASYNC(logger, fmt, ...) do { \
420  if (::LOG4CXX_NS::Logger::isInfoEnabledFor(logger)) {\
421  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
422  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
423  logger->addInfoEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
424 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
425 
426 #else
427 #define LOG4CXX_INFO_ASYNC(logger, message)
428 #define LOG4CXX_INFO_FMT_ASYNC(logger, message)
429 #endif
430 
431 #if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 30000
446 #define LOG4CXX_WARN_ASYNC(logger, message) do { \
447  if (::LOG4CXX_NS::Logger::isWarnEnabledFor(logger)) {\
448  ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
449  logger->addWarnEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
450 
451 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
467 #define LOG4CXX_WARN_FMT_ASYNC(logger, fmt, ...) do { \
468  if (::LOG4CXX_NS::Logger::isWarnEnabledFor(logger)) {\
469  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
470  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
471  logger->addWarnEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
472 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
473 
474 #else
475 #define LOG4CXX_WARN_ASYNC(logger, message)
476 #define LOG4CXX_WARN_FMT_ASYNC(logger, message)
477 #endif
478 
479 #if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 40000
494 #define LOG4CXX_ERROR_ASYNC(logger, message) do { \
495  if (::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
496  ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
497  logger->addErrorEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
498 
499 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
515 #define LOG4CXX_ERROR_FMT_ASYNC(logger, fmt, ...) do { \
516  if (::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
517  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
518  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
519  logger->addErrorEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
520 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
521 
529 #define LOG4CXX_ASSERT_ASYNC(logger, condition, message) do { \
530  if (!(condition) && ::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
531  ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
532  LOG4CXX_STACKTRACE \
533  logger->addErrorEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
534 
535 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
546 #define LOG4CXX_ASSERT_FMT_ASYNC(logger, condition, fmt, ...) do { \
547  if (!(condition) && ::LOG4CXX_NS::Logger::isErrorEnabledFor(logger)) {\
548  LOG4CXX_STACKTRACE \
549  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
550  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
551  logger->addErrorEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
552 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
553 
554 #else
555 #define LOG4CXX_ERROR_ASYNC(logger, message)
556 #define LOG4CXX_ERROR_FMT_ASYNC(logger, message)
557 #define LOG4CXX_ASSERT_ASYNC(logger, condition, message)
558 #define LOG4CXX_ASSERT_FMT_ASYNC(logger, condition, message)
559 #endif
560 
561 #if !defined(LOG4CXX_THRESHOLD) || LOG4CXX_THRESHOLD <= 50000
573 #define LOG4CXX_FATAL_ASYNC(logger, message) do { \
574  if (::LOG4CXX_NS::Logger::isFatalEnabledFor(logger)) {\
575  ::LOG4CXX_NS::helpers::AsyncBuffer buf; \
576  logger->addFatalEvent(std::move(buf << message), LOG4CXX_LOCATION); }} while (0)
577 
578 #if LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
591 #define LOG4CXX_FATAL_FMT_ASYNC(logger, fmt, ...) do { \
592  if (::LOG4CXX_NS::Logger::isFatalEnabledFor(logger)) {\
593  ::LOG4CXX_NS::helpers::AsyncBuffer buf;\
594  buf.setMessage(fmt LOG4CXX_FMT_VA_ARG(__VA_ARGS__));\
595  logger->addFatalEvent(std::move(buf), LOG4CXX_LOCATION); }} while (0)
596 #endif // LOG4CXX_ASYNC_BUFFER_SUPPORTS_FMT
597 
598 #else
599 #define LOG4CXX_FATAL_ASYNC(logger, message)
600 #define LOG4CXX_FATAL_FMT_ASYNC(logger, message)
601 #endif
602 
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 & operator<<(const T &value)
Append a function to this buffer that will convert value to text.
Definition: asyncbuffer.h:76
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
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
std::basic_ostream< char > & operator<<(CharMessageBuffer &os, const V &val)
Definition: log4cxx/helpers/messagebuffer.h:208