Apache Log4cxx  Version 1.7.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(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 
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(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 
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 & 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