Don't abuse SFINAE to provide two classes in one.
It doesn't work for fields, and is generally clunky.Instead, either invest in private inheritance and judicious use of
using
, or write them separately.Your
operator=
deadlocks on self-assignment in the multithreaded case.If you do an early return, there's no use to writing an else-block.
if (boolean_expression) { some_code; return true; } else { some_other_code; return false; }
Better change that to:
if (boolean_expression) { some_code; return true; } some_other_code; return true;false;
You can return a
bool
directly, no need to put it into a condition:if (boolean_expression) return true; else return false;
Better change that to:
return boolean_expression;
buf_capacity_
has exactly two uses: Padding out your class-size and pessimizing code.
It's always exactlyCAPACITY + 1
.Most of your multithreaded code is of the form:
std::unique_lock<std::mutex> this_lock(this->mutex_); auto result = somecode(); //this_lock.unlock(); cv_.notify_one(); // or occassionally better cv_.notify_all(); return result;
Defining a simple private member-template helps clean it up:
template<bool all = false, class F> auto locked(F f) noexcept(noexcept(f())) { auto result = (std::unique_lock<std::mutex>(mutex_), f()); // minimal lock-duration all ? cv_.notify_all() : cv_.notify_one(); return result; } // Used like: return locked([&]{ return somecode(); });
Posted a rewrite using my suggestions for review here: (Optionally Concurrent) FIFO