Skip to content

Commit 36381f9

Browse files
authored
Changed default queue to farbot, added Multi and Single Writer variants (#33)
1 parent 710abba commit 36381f9

File tree

6 files changed

+178
-106
lines changed

6 files changed

+178
-106
lines changed

CMakeLists.txt

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,24 @@ target_include_directories(${PROJECT_NAME} INTERFACE
4343
$<INSTALL_INTERFACE:include>
4444
)
4545

46-
# Try to find the package ReaderWriterQueue, if not found fetch with FetchContent
47-
find_package(ReaderWriterQueue QUIET)
48-
if(NOT TARGET readerwriterqueue)
46+
if (NOT TARGET farbot)
4947
include(FetchContent)
50-
FetchContent_Declare(ReaderWriterQueue
51-
GIT_REPOSITORY https://github.com/cameron314/readerwriterqueue
48+
49+
FetchContent_Declare(farbot
50+
GIT_REPOSITORY https://github.com/hogliux/farbot
51+
GIT_TAG 0416705394720c12f0d02e55c144e4f69bb06912
52+
)
53+
# Note we do not "MakeAvailable" here, because farbot does not fully work via FetchContent
54+
if(NOT farbot_POPULATED)
55+
FetchContent_Populate(farbot)
56+
endif()
57+
add_library(farbot INTERFACE)
58+
add_library(farbot::farbot ALIAS farbot)
59+
60+
target_include_directories(farbot INTERFACE
61+
$<BUILD_INTERFACE:${farbot_SOURCE_DIR}/include>
62+
$<INSTALL_INTERFACE:include>
5263
)
53-
FetchContent_MakeAvailable(ReaderWriterQueue)
5464
endif()
5565

5666
if(NOT RTSAN_USE_FMTLIB AND NOT TARGET stb::stb)
@@ -89,7 +99,7 @@ endif()
8999

90100
target_link_libraries(rtlog
91101
INTERFACE
92-
readerwriterqueue
102+
farbot::farbot
93103
stb::stb
94104
$<$<BOOL:${RTLOG_USE_FMTLIB}>:fmt::fmt>
95105
)

README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ Slides:
1616
- Ability to log messages of any type and size from the real-time thread
1717
- Statically allocated memory at compile time, no allocations in the real-time thread
1818
- Support for printf-style format specifiers (using [a version of the printf family](https://github.com/nothings/stb/blob/master/stb_sprintf.h) that doesn't hit the `localeconv` lock) OR support for modern libfmt formatting.
19-
- Efficient thread-safe logging using a [lock free queue](https://github.com/cameron314/readerwriterqueue).
19+
- Efficient thread-safe logging using a [lock free queue](https://github.com/hogliux/farbot).
2020

2121
## Requirements
2222

2323
- A C++17 compatible compiler
2424
- The C++17 standard library
25-
- moodycamel::ReaderWriterQueue (will be downloaded via cmake if not provided)
25+
- farbot::fifo (will be downloaded via cmake if not provided)
2626
- stb's vsnprintf (will be downloaded via cmake if not provided) OR libfmt if cmake is run with the `RTSAN_USE_FMTLIB` option
2727

2828
## Installation via CMake
@@ -130,7 +130,23 @@ Or alternatively spin up a `rtlog::LogProcessingThread`
130130
131131
## Customizing the queue type
132132
133-
If you don't want to use the SPSC moodycamel queue, you can provide your own queue type.
133+
rtlog provides two queue type variants: `rtlog::SingleRealtimeWriterQueueType` (SPSC - default) and `rtlog::MultiRealtimeWriterQueueType` (MPSC). It is always assummed that you have one log printing thread. These may be used by specifying them:
134+
135+
```cpp
136+
using SingleWriterRtLoggerType = rtlog::Logger<ExampleLogData, MAX_NUM_LOG_MESSAGES, MAX_LOG_MESSAGE_LENGTH, gSequenceNumber, SingleRealtimeWriterQueueType>;
137+
138+
SingleWriterRtLoggerType logger;
139+
logger.Log({ExampleLogLevel::Debug, ExampleLogRegion::Audio}, "Hello, world! %i", 42);
140+
141+
...
142+
143+
using MultiWriterRtLoggerType = rtlog::Logger<ExampleLogData, MAX_NUM_LOG_MESSAGES, MAX_LOG_MESSAGE_LENGTH, gSequenceNumber, MultiRealtimeWriterQueueType>;
144+
145+
MultiWriterRtLoggerType logger;
146+
logger.Log({ExampleLogLevel::Debug, ExampleLogRegion::Audio}, "Hello, world! %i", 42);
147+
```
148+
149+
If you don't want to use either of these defaults, you may provide your own queue.
134150

135151
** IT IS UP TO YOU TO ENSURE THE QUEUE YOU PROVIDE IS LOCK-FREE AND REAL-TIME SAFE **
136152

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
1-
if (NOT TARGET farbot)
1+
find_package(ReaderWriterQueue QUIET)
2+
if(NOT TARGET readerwriterqueue)
23
include(FetchContent)
3-
4-
FetchContent_Declare(farbot
5-
GIT_REPOSITORY https://github.com/hogliux/farbot
6-
GIT_TAG 0416705394720c12f0d02e55c144e4f69bb06912
7-
)
8-
# Note we do not "MakeAvailable" here, because farbot does not fully work via FetchContent
9-
if(NOT farbot_POPULATED)
10-
FetchContent_Populate(farbot)
11-
endif()
12-
add_library(farbot INTERFACE)
13-
add_library(farbot::farbot ALIAS farbot)
14-
15-
target_include_directories(farbot INTERFACE
16-
$<BUILD_INTERFACE:${farbot_SOURCE_DIR}/include>
17-
$<INSTALL_INTERFACE:include>
4+
FetchContent_Declare(ReaderWriterQueue
5+
GIT_REPOSITORY https://github.com/cameron314/readerwriterqueue
186
)
7+
FetchContent_MakeAvailable(ReaderWriterQueue)
198
endif()
209

2110
add_executable(custom_queue_example
@@ -25,5 +14,5 @@ add_executable(custom_queue_example
2514
target_link_libraries(custom_queue_example
2615
PRIVATE
2716
rtlog::rtlog
28-
farbot::farbot
17+
readerwriterqueue
2918
)

examples/custom_queue_example/customqueuemain.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,28 @@
1-
#include <farbot/fifo.hpp>
21
#include <rtlog/rtlog.h>
32

4-
template <typename T> class FarbotMPSCQueueWrapper {
5-
farbot::fifo<T,
6-
farbot::fifo_options::concurrency::single, // Consumer
7-
farbot::fifo_options::concurrency::multiple, // Producer
8-
farbot::fifo_options::full_empty_failure_mode::
9-
return_false_on_full_or_empty, // consumer_failure_mode
10-
farbot::fifo_options::full_empty_failure_mode::
11-
overwrite_or_return_default> // producer_failure_mode
3+
#include <readerwriterqueue.h>
124

13-
mQueue;
5+
template <typename T> class CustomQueue {
6+
7+
// technically we could use readerwriterqueue "unwrapped" but showing this off
8+
// in the CustomQueue wrapper for documentation purposes
9+
moodycamel::ReaderWriterQueue<T> mQueue;
1410

1511
public:
1612
using value_type = T;
1713

18-
FarbotMPSCQueueWrapper(int capacity) : mQueue(capacity) {}
14+
CustomQueue(int capacity) : mQueue(capacity) {}
1915

20-
bool try_enqueue(T &&item) { return mQueue.push(std::move(item)); }
21-
bool try_dequeue(T &item) { return mQueue.pop(item); }
16+
bool try_enqueue(T &&item) { return mQueue.try_enqueue(std::move(item)); }
17+
bool try_dequeue(T &item) { return mQueue.try_dequeue(item); }
2218
};
2319

2420
struct LogData {};
2521

2622
std::atomic<size_t> gSequenceNumber{0};
2723

2824
int main() {
29-
rtlog::Logger<LogData, 128, 128, gSequenceNumber, FarbotMPSCQueueWrapper>
30-
logger;
25+
rtlog::Logger<LogData, 128, 128, gSequenceNumber, CustomQueue> logger;
3126
logger.Log({}, "Hello, World!");
3227

3328
logger.PrintAndClearLogQueue(

include/rtlog/rtlog.h

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <fmt/format.h>
1818
#endif // RTLOG_USE_FMTLIB
1919

20-
#include <readerwriterqueue.h>
20+
#include <farbot/fifo.hpp>
2121

2222
#ifdef RTLOG_USE_STB
2323
#ifndef STB_SPRINTF_IMPLEMENTATION
@@ -125,12 +125,40 @@ template <typename T>
125125
inline constexpr bool has_int_constructor_v = has_int_constructor<T>::value;
126126
} // namespace detail
127127

128-
// On earlier versions of compilers (especially clang) you cannot
129-
// rely on defaulted template template parameters working as intended
130-
// This overload explicitly has 1 template paramter which is what
131-
// `Logger` expects, it uses the default 512 from ReaderWriterQueue as
132-
// the hardcoded MaxBlockSize
133-
template <typename T> using rtlog_SPSC = moodycamel::ReaderWriterQueue<T, 512>;
128+
template <typename T, farbot::fifo_options::concurrency producer_concurrency,
129+
farbot::fifo_options::full_empty_failure_mode producer_failure_mode>
130+
class FarbotFifoType {
131+
farbot::fifo<T,
132+
farbot::fifo_options::concurrency::single, // Consumer
133+
producer_concurrency, // Producer
134+
farbot::fifo_options::full_empty_failure_mode::
135+
return_false_on_full_or_empty, // consumer_failure_mode
136+
producer_failure_mode> // producer_failure_mode
137+
138+
mQueue;
139+
140+
public:
141+
using value_type = T;
142+
143+
FarbotFifoType(int capacity) : mQueue(capacity) {}
144+
145+
bool try_enqueue(T &&item) { return mQueue.push(std::move(item)); }
146+
bool try_dequeue(T &item) { return mQueue.pop(item); }
147+
};
148+
149+
template <typename T>
150+
using SingleRealtimeWriterQueueType =
151+
FarbotFifoType<T, farbot::fifo_options::concurrency::single,
152+
farbot::fifo_options::full_empty_failure_mode::
153+
return_false_on_full_or_empty>;
154+
155+
// NOTE: This version overwrites on full, which is a requirement to make writing
156+
// real-time safe.
157+
// This means it will never report Error_QueueFull.
158+
template <typename T>
159+
using MultiRealtimeWriterQueueType = FarbotFifoType<
160+
T, farbot::fifo_options::concurrency::multiple,
161+
farbot::fifo_options::full_empty_failure_mode::overwrite_or_return_default>;
134162

135163
/**
136164
* @brief A logger class for logging messages.
@@ -161,12 +189,15 @@ template <typename T> using rtlog_SPSC = moodycamel::ReaderWriterQueue<T, 512>;
161189
*/
162190
template <typename LogData, size_t MaxNumMessages, size_t MaxMessageLength,
163191
std::atomic<std::size_t> &SequenceNumber,
164-
template <typename> class QType = rtlog_SPSC>
192+
template <typename> class QType = SingleRealtimeWriterQueueType>
165193
class Logger {
166194
public:
167195
using InternalLogData = detail::BasicLogData<LogData, MaxMessageLength>;
168196
using InternalQType = QType<InternalLogData>;
169197

198+
static_assert(MaxNumMessages > 0);
199+
static_assert((MaxNumMessages & (MaxNumMessages - 1)) == 0,
200+
"MaxNumMessages must be a power of 2");
170201
static_assert(
171202
detail::has_int_constructor_v<InternalQType>,
172203
"QType must have a constructor that takes an int - `QType(int)`");

0 commit comments

Comments
 (0)