Summary
Add push(T&&) overload to SpscQueue to enable zero-copy insertion of moveable types.
Motivation
The current push(const T&) always copies the value into the buffer. For types with expensive copy constructors (large structs, types managing heap memory), this is unnecessary overhead when the caller no longer needs the original value.
Proposed API
// Existing (copy)
bool push(const T& value);
// New (move)
bool push(T&& value);
// Optionally, emplace (construct in-place)
template <typename... Args>
bool emplace(Args&&... args);
Implementation Notes
bool push(T&& value) {
auto write = write_idx_.load(std::memory_order_relaxed);
if (write - read_idx_cache_ == N) {
read_idx_cache_ = read_idx_.load(std::memory_order_acquire);
if (write - read_idx_cache_ == N)
return false;
}
data_[write % N] = std::move(value);
write_idx_.store(write + 1, std::memory_order_release);
return true;
}
For emplace, construct directly in the buffer slot:
template <typename... Args>
bool emplace(Args&&... args) {
auto write = write_idx_.load(std::memory_order_relaxed);
if (write - read_idx_cache_ == N) {
read_idx_cache_ = read_idx_.load(std::memory_order_acquire);
if (write - read_idx_cache_ == N)
return false;
}
new (&data_[write % N]) T(std::forward<Args>(args)...);
write_idx_.store(write + 1, std::memory_order_release);
return true;
}
Impact
- Zero overhead for trivially copyable types (compiler will optimize both paths identically)
- Significant win for types like
std::string, std::vector, or large POD structs
- Consistent with STL container conventions (
push_back vs emplace_back)
References
- rigtorp/SPSCQueue: provides
try_push(T&&) and try_emplace(Args&&...)
std::queue::push(T&&) — STL precedent
Summary
Add
push(T&&)overload toSpscQueueto enable zero-copy insertion of moveable types.Motivation
The current
push(const T&)always copies the value into the buffer. For types with expensive copy constructors (large structs, types managing heap memory), this is unnecessary overhead when the caller no longer needs the original value.Proposed API
Implementation Notes
For
emplace, construct directly in the buffer slot:Impact
std::string,std::vector, or large POD structspush_backvsemplace_back)References
try_push(T&&)andtry_emplace(Args&&...)std::queue::push(T&&)— STL precedent