libfly  6.2.2
C++20 utility library for Linux, macOS, and Windows
concurrent_container.hpp
1 #pragma once
2 
3 #include <chrono>
4 #include <condition_variable>
5 #include <mutex>
6 
7 namespace fly::detail {
8 
15 template <typename T, typename Container>
17 {
18 public:
19  using size_type = typename Container::size_type;
20  using value_type = T;
21 
25  virtual ~ConcurrentContainer() = default;
26 
32  void push(T &&item);
33 
40  void pop(T &item);
41 
51  template <typename R, typename P>
52  bool pop(T &item, std::chrono::duration<R, P> duration);
53 
57  bool empty() const;
58 
62  size_type size() const;
63 
64 protected:
70  virtual void push_internal(T &&item) = 0;
71 
77  virtual void pop_internal(T &item) = 0;
78 
79  mutable std::mutex m_container_mutex;
80  Container m_container;
81 
82 private:
83  std::condition_variable m_push_condition;
84 };
85 
86 //==================================================================================================
87 template <typename T, typename Container>
89 {
90  {
91  std::unique_lock<std::mutex> lock(m_container_mutex);
92  push_internal(std::move(item));
93  }
94 
95  m_push_condition.notify_one();
96 }
97 
98 //==================================================================================================
99 template <typename T, typename Container>
101 {
102  std::unique_lock<std::mutex> lock(m_container_mutex);
103 
104  while (m_container.empty())
105  {
106  m_push_condition.wait(lock);
107  }
108 
109  pop_internal(item);
110 }
111 
112 //==================================================================================================
113 template <typename T, typename Container>
114 template <typename R, typename P>
115 bool ConcurrentContainer<T, Container>::pop(T &item, std::chrono::duration<R, P> wait_time)
116 {
117  std::unique_lock<std::mutex> lock(m_container_mutex);
118 
119  auto empty_test = [this] {
120  return !m_container.empty();
121  };
122 
123  bool item_popped = m_push_condition.wait_for(lock, wait_time, std::move(empty_test));
124 
125  if (item_popped)
126  {
127  pop_internal(item);
128  }
129 
130  return item_popped;
131 }
132 
133 //==================================================================================================
134 template <typename T, typename Container>
136 {
137  std::unique_lock<std::mutex> lock(m_container_mutex);
138  return m_container.empty();
139 }
140 
141 //==================================================================================================
142 template <typename T, typename Container>
144 {
145  std::unique_lock<std::mutex> lock(m_container_mutex);
146  return m_container.size();
147 }
148 
149 } // namespace fly::detail
Definition: concurrent_container.hpp:17
size_type size() const
Definition: concurrent_container.hpp:143
void push(T &&item)
Definition: concurrent_container.hpp:88
virtual ~ConcurrentContainer()=default
virtual void push_internal(T &&item)=0
virtual void pop_internal(T &item)=0
void pop(T &item)
Definition: concurrent_container.hpp:100
bool empty() const
Definition: concurrent_container.hpp:135
bool pop(T &item, std::chrono::duration< R, P > duration)
Definition: concurrent_container.hpp:115