RingBuffer - buffer on heap instead of stack

Summary: RingBuffer - buffer in vector

Reviewers: mislav.bradac, buda, dgleich

Reviewed By: mislav.bradac

Differential Revision: https://phabricator.memgraph.io/D952
This commit is contained in:
florijan 2017-11-02 12:02:23 +01:00
parent 196b17417a
commit f2aad117cf
3 changed files with 12 additions and 10 deletions

View File

@ -6,6 +6,7 @@
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <utility> #include <utility>
#include <vector>
#include "glog/logging.h" #include "glog/logging.h"
@ -17,10 +18,11 @@
* *
* @tparam TElement - type of element the buffer tracks. * @tparam TElement - type of element the buffer tracks.
*/ */
template <typename TElement, int capacity> template <typename TElement>
class RingBuffer { class RingBuffer {
public: public:
RingBuffer() = default; RingBuffer(int capacity) : buffer_(capacity) {}
RingBuffer(const RingBuffer &) = delete; RingBuffer(const RingBuffer &) = delete;
RingBuffer(RingBuffer &&) = delete; RingBuffer(RingBuffer &&) = delete;
RingBuffer &operator=(const RingBuffer &) = delete; RingBuffer &operator=(const RingBuffer &) = delete;
@ -31,9 +33,9 @@ class RingBuffer {
while (true) { while (true) {
{ {
std::lock_guard<SpinLock> guard(lock_); std::lock_guard<SpinLock> guard(lock_);
if (size_ < capacity) { if (size_ < buffer_.size()) {
buffer_[write_pos_++] = TElement(std::forward<TArgs>(args)...); buffer_[write_pos_++] = TElement(std::forward<TArgs>(args)...);
write_pos_ %= capacity; write_pos_ %= buffer_.size();
size_++; size_++;
return; return;
} }
@ -52,12 +54,12 @@ class RingBuffer {
size_--; size_--;
std::experimental::optional<TElement> result( std::experimental::optional<TElement> result(
std::move(buffer_[read_pos_++])); std::move(buffer_[read_pos_++]));
read_pos_ %= capacity; read_pos_ %= buffer_.size();
return result; return result;
} }
private: private:
TElement buffer_[capacity]; std::vector<TElement> buffer_;
SpinLock lock_; SpinLock lock_;
int read_pos_{0}; int read_pos_{0};
int write_pos_{0}; int write_pos_{0};

View File

@ -7,7 +7,7 @@
class RingBufferMultiThreaded : public benchmark::Fixture { class RingBufferMultiThreaded : public benchmark::Fixture {
protected: protected:
RingBuffer<int, 1024> buffer; RingBuffer<int> buffer{1024};
}; };
BENCHMARK_DEFINE_F(RingBufferMultiThreaded, MT)(benchmark::State &st) { BENCHMARK_DEFINE_F(RingBufferMultiThreaded, MT)(benchmark::State &st) {

View File

@ -13,7 +13,7 @@ TEST(RingBuffer, MultithreadedUsage) {
std::unordered_set<int> consumed; std::unordered_set<int> consumed;
SpinLock consumed_lock; SpinLock consumed_lock;
RingBuffer<int, 20> buffer; RingBuffer<int> buffer{20};
std::vector<std::thread> producers; std::vector<std::thread> producers;
for (int i = 0; i < producer_count; i++) for (int i = 0; i < producer_count; i++)
@ -61,7 +61,7 @@ TEST(RingBuffer, MultithreadedUsage) {
} }
TEST(RingBuffer, ComplexValues) { TEST(RingBuffer, ComplexValues) {
RingBuffer<std::vector<int>, 10> buffer; RingBuffer<std::vector<int>> buffer{10};
std::vector<int> element; std::vector<int> element;
for (int i = 0 ; i < 5 ; i++) { for (int i = 0 ; i < 5 ; i++) {
element.emplace_back(i); element.emplace_back(i);
@ -78,7 +78,7 @@ TEST(RingBuffer, ComplexValues) {
} }
TEST(RingBuffer, NonCopyable) { TEST(RingBuffer, NonCopyable) {
RingBuffer<std::unique_ptr<std::string>, 10> buffer; RingBuffer<std::unique_ptr<std::string>> buffer{10};
buffer.emplace(new std::string("string")); buffer.emplace(new std::string("string"));
buffer.emplace(new std::string("kifla")); buffer.emplace(new std::string("kifla"));