|
23 | 23 |
|
24 | 24 | #include <stb_sprintf.h> |
25 | 25 |
|
| 26 | +#if defined(__has_feature) |
| 27 | +#if __has_feature(realtime_sanitizer) |
| 28 | +#define RTLOG_NONBLOCKING [[clang::nonblocking]] |
| 29 | +#endif |
| 30 | +#endif |
| 31 | + |
| 32 | +#ifndef RTLOG_NONBLOCKING |
| 33 | +#define RTLOG_NONBLOCKING |
| 34 | +#endif |
| 35 | + |
| 36 | +#ifndef __MSC_VER__ |
| 37 | +#define RTLOG_ATTRIBUTE_FORMAT __attribute__((format(printf, 3, 4))) |
| 38 | +#else |
| 39 | +#define RTLOG_ATTRIBUTE_FORMAT |
| 40 | +#endif |
| 41 | + |
26 | 42 | namespace rtlog { |
27 | 43 |
|
28 | 44 | enum class Status { |
@@ -94,7 +110,8 @@ class Logger { |
94 | 110 | * message was truncated, the function returns |
95 | 111 | * `Status::Error_MessageTruncated`. Otherwise, it returns `Status::Success`. |
96 | 112 | */ |
97 | | - Status Logv(LogData &&inputData, const char *format, va_list args) { |
| 113 | + Status Logv(LogData &&inputData, const char *format, |
| 114 | + va_list args) RTLOG_NONBLOCKING { |
98 | 115 | auto retVal = Status::Success; |
99 | 116 |
|
100 | 117 | InternalLogData dataToQueue; |
@@ -144,11 +161,8 @@ class Logger { |
144 | 161 | * message was truncated, the function returns |
145 | 162 | * `Status::Error_MessageTruncated`. Otherwise, it returns `Status::Success`. |
146 | 163 | */ |
147 | | - Status Log(LogData &&inputData, const char *format, ...) |
148 | | -#ifndef __MSC_VER__ |
149 | | - __attribute__((format(printf, 3, 4))) |
150 | | -#endif |
151 | | - { |
| 164 | + Status Log(LogData &&inputData, const char *format, |
| 165 | + ...) RTLOG_NONBLOCKING RTLOG_ATTRIBUTE_FORMAT { |
152 | 166 | va_list args; |
153 | 167 | va_start(args, format); |
154 | 168 | auto retVal = Logv(std::move(inputData), format, args); |
@@ -187,7 +201,7 @@ class Logger { |
187 | 201 | */ |
188 | 202 | template <typename... T> |
189 | 203 | Status LogFmt(LogData &&inputData, fmt::format_string<T...> fmtString, |
190 | | - T &&...args) { |
| 204 | + T &&...args) RTLOG_NONBLOCKING { |
191 | 205 | auto retVal = Status::Success; |
192 | 206 |
|
193 | 207 | InternalLogData dataToQueue; |
@@ -277,15 +291,19 @@ class Logger { |
277 | 291 | class InternalQueueMPSC : public InternalQueue { |
278 | 292 | farbot::fifo<InternalLogData, farbot::fifo_options::concurrency::single, |
279 | 293 | farbot::fifo_options::concurrency::multiple, |
280 | | - farbot::fifo_options::full_empty_failure_mode::return_false_on_full_or_empty, |
281 | | - farbot::fifo_options::full_empty_failure_mode::overwrite_or_return_default> |
| 294 | + farbot::fifo_options::full_empty_failure_mode:: |
| 295 | + return_false_on_full_or_empty, |
| 296 | + farbot::fifo_options::full_empty_failure_mode:: |
| 297 | + overwrite_or_return_default> |
282 | 298 | mQueue{MaxNumMessages}; |
283 | 299 |
|
284 | 300 | public: |
285 | 301 | InternalQueueMPSC() { |
286 | | - static_assert((MaxNumMessages & (MaxNumMessages - 1)) == 0 || |
287 | | - Concurrency != QueueConcurrency::Multi_Producer_Single_Consumer, |
288 | | - "you have to assign 2^n to MaxNumMessages (farbot backend restriction)"); |
| 302 | + static_assert((MaxNumMessages & (MaxNumMessages - 1)) == 0 || |
| 303 | + Concurrency != |
| 304 | + QueueConcurrency::Multi_Producer_Single_Consumer, |
| 305 | + "you have to assign 2^n to MaxNumMessages (farbot backend " |
| 306 | + "restriction)"); |
289 | 307 | } |
290 | 308 | bool tryEnqueue(InternalLogData &&value) override { |
291 | 309 | return mQueue.push(std::move(value)); |
@@ -378,4 +396,8 @@ template <typename LoggerType, typename PrintLogFn> class LogProcessingThread { |
378 | 396 | std::chrono::milliseconds mWaitTime{}; |
379 | 397 | }; |
380 | 398 |
|
| 399 | +template <typename LoggerType, typename PrintLogFn> |
| 400 | +LogProcessingThread(LoggerType &, PrintLogFn) |
| 401 | + -> LogProcessingThread<LoggerType, PrintLogFn>; |
| 402 | + |
381 | 403 | } // namespace rtlog |
0 commit comments