Skip to content

Commit 1c2541b

Browse files
committed
Add custom queue example, more readme
1 parent 1948850 commit 1c2541b

5 files changed

Lines changed: 113 additions & 3 deletions

File tree

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,34 @@ Or alternatively spin up a `rtlog::LogProcessingThread`
120120
```c++
121121
rtlog::LogProcessingThread thread(logger, PrintMessage, std::chrono::milliseconds(10));
122122
```
123+
124+
## Customizing the queue type
125+
126+
If you don't want to use the SPSC moodycamel queue, you can provide your own queue type.
127+
128+
** IT IS UP TO YOU TO ENSURE THE QUEUE YOU PROVIDE IS LOCK-FREE AND REAL-TIME SAFE **
129+
130+
The queue must have the following:
131+
```c++
132+
template <typename T>
133+
class MyQueue
134+
{
135+
public:
136+
using value_type = T;
137+
138+
MyQueue(int capacity);
139+
bool try_dequeue(T& item); // MUST return false if the queue is empty
140+
141+
bool try_enqueue(T&& item);
142+
// OR
143+
bool try_enqueue(const T& item);
144+
};
145+
```
146+
147+
Then, when creating the logger, provide the queue type as a template parameter:
148+
149+
```c++
150+
using RealtimeLogger = rtlog::Logger<ExampleLogData, MAX_NUM_LOG_MESSAGES, MAX_LOG_MESSAGE_LENGTH, gSequenceNumber, MyQueue>;
151+
```
152+
153+
You can see an example of wrapping a known rt-safe queue in `examples/custom_queue_example`.

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
add_subdirectory(everlog)
2+
add_subdirectory(custom_queue_example)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
if (NOT TARGET farbot)
2+
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>
18+
)
19+
endif()
20+
21+
add_executable(custom_queue_example
22+
customqueuemain.cpp
23+
)
24+
25+
target_link_libraries(custom_queue_example
26+
PRIVATE
27+
rtlog::rtlog
28+
farbot::farbot
29+
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <farbot/fifo.hpp>
2+
#include <rtlog/rtlog.h>
3+
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
12+
13+
mQueue;
14+
15+
public:
16+
using value_type = T;
17+
18+
FarbotMPSCQueueWrapper(int capacity) : mQueue(capacity) {}
19+
20+
bool try_enqueue(T &&item) { return mQueue.push(std::move(item)); }
21+
bool try_dequeue(T &item) { return mQueue.pop(item); }
22+
};
23+
24+
struct LogData {};
25+
26+
std::atomic<size_t> gSequenceNumber{0};
27+
28+
int main() {
29+
rtlog::Logger<LogData, 128, 128, gSequenceNumber, FarbotMPSCQueueWrapper>
30+
logger;
31+
logger.Log({}, "Hello, World!");
32+
33+
logger.PrintAndClearLogQueue(
34+
[](const LogData &data, size_t sequenceNumber, const char *fstring, ...) {
35+
(void)data;
36+
std::array<char, 128> buffer;
37+
38+
va_list args;
39+
va_start(args, fstring);
40+
vsnprintf(buffer.data(), buffer.size(), fstring, args);
41+
va_end(args);
42+
43+
printf("{%zu} %s\n", sequenceNumber, buffer.data());
44+
});
45+
46+
return 0;
47+
}

include/rtlog/rtlog.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,10 @@ template <typename T> using rtlog_SPSC = moodycamel::ReaderWriterQueue<T, 512>;
147147
* Requirements on QType:
148148
* 1. Is real-time safe
149149
* 2. Accepts one type template paramter for the type to be queued
150-
* 3. Has a constructor that takes an integer which will be the queue's capacity
151-
* 4. Has methods `bool try_enqueue(T &&item)` and/or `bool try_enqueue(const T &item)` and `bool try_dequeue(T &item)`
150+
* 3. Has a constructor that takes an integer which will be the queue's
151+
* capacity
152+
* 4. Has methods `bool try_enqueue(T &&item)` and/or `bool
153+
* try_enqueue(const T &item)` and `bool try_dequeue(T &item)`
152154
*/
153155
template <typename LogData, size_t MaxNumMessages, size_t MaxMessageLength,
154156
std::atomic<std::size_t> &SequenceNumber,
@@ -338,7 +340,7 @@ class Logger {
338340
* @return int The number of log messages that were processed and printed.
339341
*/
340342
template <typename PrintLogFn>
341-
int PrintAndClearLogQueue(PrintLogFn &printLogFn) {
343+
int PrintAndClearLogQueue(PrintLogFn &&printLogFn) {
342344
int numProcessed = 0;
343345

344346
InternalLogData value;

0 commit comments

Comments
 (0)