diff --git a/include/spdlog/details/circular_q.h b/include/spdlog/details/circular_q.h new file mode 100644 index 00000000..ed272bad --- /dev/null +++ b/include/spdlog/details/circular_q.h @@ -0,0 +1,61 @@ +// +// Copyright(c) 2018 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +// cirucal q view of std::vector. +#pragma once + +namespace spdlog { +namespace details { +template +class circular_q +{ +public: + using item_type = T; + + explicit circular_q(size_t max_items) + : max_items_(max_items + 1) + , v_(max_items_) + { + } + + // push back, overrun last item if no room left + void push_back(T &&item) + { + v_[head_] = std::move(item); + head_ = (head_ + 1) % max_items_; + + if (head_ == tail_) + { + tail_ = (tail_ + 1) % max_items_; + } + } + + // Pop item from front. + // 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_; + } + + bool empty() + { + return head_ == tail_; + } + + bool full() + { + // tail is ahead of the head by 1 + return ((head_ + 1) % max_items_) == tail_; + } + +private: + size_t max_items_; + typename std::vector::size_type head_ = 0; + typename std::vector::size_type tail_ = 0; + std::vector v_; +}; +} // namespace details +} // namespace spdlog \ No newline at end of file diff --git a/include/spdlog/details/fmt_helper.h b/include/spdlog/details/fmt_helper.h index ddfea6c5..5206eb9f 100644 --- a/include/spdlog/details/fmt_helper.h +++ b/include/spdlog/details/fmt_helper.h @@ -24,9 +24,10 @@ inline void append_c_str(const char *c_str, fmt::memory_buffer &dest) } } -inline void append_buf(const fmt::memory_buffer &buf, fmt::memory_buffer &dest) +template +inline void append_buf(const fmt::basic_memory_buffer &buf, fmt::basic_memory_buffer &dest) { - const char *buf_ptr = buf.data(); + auto *buf_ptr = buf.data(); dest.append(buf_ptr, buf_ptr + buf.size()); } diff --git a/include/spdlog/details/mpmc_blocking_q.h b/include/spdlog/details/mpmc_blocking_q.h index 860fdc67..215a4fa3 100644 --- a/include/spdlog/details/mpmc_blocking_q.h +++ b/include/spdlog/details/mpmc_blocking_q.h @@ -5,15 +5,15 @@ // Distributed under the MIT License (http://opensource.org/licenses/MIT) // -// async log helper : -// multi producer-multi consumer blocking queue -// enqueue(..) - will block until room found to put the new message -// enqueue_nowait(..) - will return immediatly with false if no room left in the queue -// dequeue_for(..) - will block until the queue is not empty or timeout passed +// multi producer-multi consumer blocking queue. +// enqueue(..) - will block until room found to put the new message. +// enqueue_nowait(..) - will return immediately with false if no room left in the queue. +// dequeue_for(..) - will block until the queue is not empty or timeout have passed. + +#include "spdlog/details/circular_q.h" #include #include -#include namespace spdlog { namespace details { @@ -24,7 +24,7 @@ class mpmc_blocking_queue public: using item_type = T; explicit mpmc_blocking_queue(size_t max_items) - : max_items_(max_items) + : q_(max_items) { } @@ -33,22 +33,22 @@ public: { { std::unique_lock lock(queue_mutex_); - pop_cv_.wait(lock, [this] { return this->q_.size() < this->max_items_; }); - q_.push(std::move(item)); + pop_cv_.wait(lock, [this] { return !this->q_.full(); }); + q_.push_back(std::move(item)); } push_cv_.notify_one(); } - // try to enqueue and return immdeialty false if no room left + // try to enqueue and return immediately false if no room left bool enqueue_nowait(T &&item) { { std::unique_lock lock(queue_mutex_); - if (q_.size() == this->max_items_) + if (q_.full()) { return false; } - q_.push(std::forward(item)); + q_.push_back(std::forward(item)); } push_cv_.notify_one(); return true; @@ -60,25 +60,23 @@ public: { { std::unique_lock lock(queue_mutex_); - if (!push_cv_.wait_for(lock, wait_duration, [this] { return this->q_.size() > 0; })) + if (!push_cv_.wait_for(lock, wait_duration, [this] { return !this->q_.empty(); })) { return false; } - popped_item = std::move(q_.front()); - q_.pop(); + q_.pop_front(popped_item); } pop_cv_.notify_one(); return true; } private: - size_t max_items_; std::mutex queue_mutex_; std::condition_variable push_cv_; std::condition_variable pop_cv_; - std::queue q_; + spdlog::details::circular_q q_; }; } // namespace details } // namespace spdlog diff --git a/include/spdlog/formatter.h b/include/spdlog/formatter.h index b9cea727..ec343f83 100644 --- a/include/spdlog/formatter.h +++ b/include/spdlog/formatter.h @@ -8,7 +8,6 @@ #include "fmt/fmt.h" #include "spdlog/details/log_msg.h" - namespace spdlog { class formatter