From 94a7152afc7ba38249ba204be9dfd388010bb505 Mon Sep 17 00:00:00 2001 From: gabime Date: Wed, 4 Jul 2018 01:24:52 +0300 Subject: [PATCH] async queue - overrun oldsest policy option --- include/spdlog/common.h | 4 ++-- include/spdlog/details/circular_q.h | 23 ++++++++++++----------- include/spdlog/details/mpmc_blocking_q.h | 11 +++-------- tests/test_async.cpp | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/include/spdlog/common.h b/include/spdlog/common.h index a6c505df..5e7e1f78 100644 --- a/include/spdlog/common.h +++ b/include/spdlog/common.h @@ -126,8 +126,8 @@ using level_hasher = std::hash; // enum class async_overflow_policy { - block_retry, // Block / yield / sleep until message can be enqueued - discard_log_msg // Discard the message it enqueue fails + block_retry, // Block until message can be enqueued + overrun_oldeset // Discard oldest message in the queue if full when trying to add new item. }; // diff --git a/include/spdlog/details/circular_q.h b/include/spdlog/details/circular_q.h index ed272bad..48f9a8fa 100644 --- a/include/spdlog/details/circular_q.h +++ b/include/spdlog/details/circular_q.h @@ -15,20 +15,20 @@ public: using item_type = T; explicit circular_q(size_t max_items) - : max_items_(max_items + 1) + : max_items_(max_items + 1) // one item is reserved as marker for full q , v_(max_items_) { } - // push back, overrun last item if no room left + // push back, overrun (oldest) item if no room left void push_back(T &&item) { - v_[head_] = std::move(item); - head_ = (head_ + 1) % max_items_; + v_[tail_] = std::move(item); + tail_ = (tail_ + 1) % max_items_; - if (head_ == tail_) + if (tail_ == head_) // overrun last item if full { - tail_ = (tail_ + 1) % max_items_; + head_ = (head_ + 1) % max_items_; } } @@ -36,25 +36,26 @@ public: // If there are no elements in the container, the behavior is undefined. void pop_front(T &popped_item) { - popped_item = std::move(v_[tail_]); - tail_ = (tail_ + 1) % max_items_; + popped_item = std::move(v_[head_]); + head_ = (head_ + 1) % max_items_; } bool empty() { - return head_ == tail_; + return tail_ == head_; } bool full() { - // tail is ahead of the head by 1 - return ((head_ + 1) % max_items_) == tail_; + // head is ahead of the tail by 1 + return ((tail_ + 1) % max_items_) == head_; } private: size_t max_items_; typename std::vector::size_type head_ = 0; typename std::vector::size_type tail_ = 0; + std::vector v_; }; } // namespace details diff --git a/include/spdlog/details/mpmc_blocking_q.h b/include/spdlog/details/mpmc_blocking_q.h index 215a4fa3..f34297ef 100644 --- a/include/spdlog/details/mpmc_blocking_q.h +++ b/include/spdlog/details/mpmc_blocking_q.h @@ -39,19 +39,14 @@ public: push_cv_.notify_one(); } - // try to enqueue and return immediately false if no room left - bool enqueue_nowait(T &&item) + // enqueue immediately. overrun oldest message in the queue if no room left. + void enqueue_nowait(T &&item) { { std::unique_lock lock(queue_mutex_); - if (q_.full()) - { - return false; - } - q_.push_back(std::forward(item)); + q_.push_back(std::move(item)); } push_cv_.notify_one(); - return true; } // try to dequeue item. if no item found. wait upto timeout and try again diff --git a/tests/test_async.cpp b/tests/test_async.cpp index 1c0c8567..7ade2676 100644 --- a/tests/test_async.cpp +++ b/tests/test_async.cpp @@ -30,7 +30,7 @@ TEST_CASE("discard policy ", "[async]") size_t messages = 1024; { auto tp = std::make_shared(queue_size, 1); - auto logger = std::make_shared("as", test_sink, tp, async_overflow_policy::discard_log_msg); + auto logger = std::make_shared("as", test_sink, tp, async_overflow_policy::overrun_oldeset); for (size_t i = 0; i < messages; i++) { logger->info("Hello message #{}", i);