One obvious alternative is to create a SPSC queue backed by a std::vector<std::string>
and preallocate strings to a fixed size. As long as the copied string stays within this size, memory allocation never occurs.
const size_t QUEUE_CAPACITY = 1024;
// Create a vector with 10 default-constructed (empty) strings.
std::vector<std::string> shared_string_buffer(QUEUE_CAPACITY);
// Loop through each string in the vector to reserve its capacity to 128 bytes
const std::size_t string_default_capacity = 128;
for (std::string& str : shared_string_buffer) {
str.reserve(string_default_capacity);
}
// Create the SPSC queue manager, giving it a non-owning view of our buffer.
LockFreeSpscQueue<std::string> queue(shared_string_buffer);
Here's the full working example: (Run)
I have used my LockFreeSpscQueue
for this example.
Although nothing really prevents you from creating the queue, like:
std::vector<std::byte> buffer(1024);
LockFreeSpscQueue<std::byte> spsc_queue(buffer);`
and manually implement the (size, string) layout. However, if the consumer thread is not reading quickly enough or the string is too large, you may encounter a "full ring buffer" situation, in which case the producer thread would need to wait.