yat  0.18.2pre
BasicQueue.h
1 #ifndef theplu_yat_utility_basic_queue
2 #define theplu_yat_utility_basic_queue
3 
4 // $Id: BasicQueue.h 3999 2020-10-08 23:22:32Z peter $
5 //
6 // Copyright (C) 2017, 2018, 2020 Peter Johansson
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with yat. If not, see <http://www.gnu.org/licenses/>.
20 
21 #include "config_public.h"
22 
23 #include <condition_variable>
24 #include <mutex>
25 
26 namespace theplu {
27 namespace yat {
28 namespace utility {
29 namespace detail {
30 
34  template<class Derived, typename T, class Container>
35  class BasicQueue
36  {
37  public:
39  typedef typename Container::value_type value_type;
40 
44  typedef typename Container::size_type size_type;
45 
49  BasicQueue(void) {}
50 
54  BasicQueue(const BasicQueue& other)
55  {
56  std::unique_lock<std::mutex> lock(other.mutex_);
57  q_ = other.q_;
58  } // lock is released here
59 
63  explicit BasicQueue(const Container& container) : q_(container) {}
64 
70  void clear(void)
71  {
72  std::unique_lock<std::mutex> lock(mutex_);
73  return q_.clear();
74  }
75 
76 
80  bool empty(void) const
81  {
82  std::unique_lock<std::mutex> lock(mutex_);
83  return q_.empty();
84  } // lock is released here
85 
86 
94  void pop(T& value)
95  {
96  std::unique_lock<std::mutex> lock(mutex_);
97  while (q_.empty())
98  condition_.wait(lock);
99  // The obvious choice would be to create a temp copy of front,
100  // pop the queue and then return by-value. This is, however,
101  // dangerous becasue if the copy constructor throws, the queue
102  // has been popped and the element is lost. Instead we choose to
103  // pass via passed reference.
104  static_cast<Derived*>(this)->pop_impl(value, lock);
105  } // lock is released here
106 
107 
111  void push(const T& t)
112  {
113  std::unique_lock<std::mutex> lock(mutex_);
114  static_cast<Derived*>(this)->push_impl(t, lock);
115  lock.unlock(); // unlock the mutex
116 
117  // Notify others that data is ready after we have unlocked
118  condition_.notify_one();
119  }
120 
121 
129  void push(T&& t)
130  {
131  std::unique_lock<std::mutex> lock(mutex_);
132  static_cast<Derived*>(this)->push_impl(std::move(t), lock);
133  lock.unlock(); // unlock the mutex
134 
135  // Notify others that data is ready after we have unlocked
136  condition_.notify_one();
137  }
138 
139 
143  size_type size(void) const
144  {
145  std::unique_lock<std::mutex> lock(mutex_);
146  return q_.size();
147  } // lock is released here
148 
149 
154  bool try_pop(T& value)
155  {
156  std::unique_lock<std::mutex> lock(mutex_);
157  if (q_.empty())
158  return false;
159  static_cast<Derived*>(this)->pop_impl(value, lock);
160  return true;
161  } // lock is released here
162 
163  protected:
167  void assign(const BasicQueue& other)
168  {
169  if (this != &other) {
170  // std::lock guarantees that the two mutexes are locked in
171  // the same order regardless of passed order and thereby
172  // avoiding deadlock when two threads are calling
173  // lhs.assign(rhs) and rhs.assign(lhs) simultaneously.
174  std::lock(mutex_, other.mutex_);
175  std::unique_lock<std::mutex> lock(mutex_, std::adopt_lock_t());
176  std::unique_lock<std::mutex> other_lock(other.mutex_,
177  std::adopt_lock_t());
178  q_ = other.q_;
179  }
180  }
181 
183  Container q_;
184  private:
185  mutable std::mutex mutex_;
186  std::condition_variable condition_;
187  };
188 
189 }}}}
190 #endif
Container::size_type size_type
Definition: BasicQueue.h:44
void clear(void)
clear queue
Definition: BasicQueue.h:70
BasicQueue(const BasicQueue &other)
Definition: BasicQueue.h:54
The Department of Theoretical Physics namespace as we define it.
bool try_pop(T &value)
Definition: BasicQueue.h:154
void assign(const BasicQueue &other)
Definition: BasicQueue.h:167
Definition: BasicQueue.h:35
BasicQueue(void)
Definition: BasicQueue.h:49
void push(const T &t)
insert an element into container
Definition: BasicQueue.h:111
void pop(T &value)
access next element in queue
Definition: BasicQueue.h:94
size_type size(void) const
Definition: BasicQueue.h:143
Container q_
data
Definition: BasicQueue.h:183
BasicQueue(const Container &container)
Definition: BasicQueue.h:63
void push(T &&t)
insert an element into container
Definition: BasicQueue.h:129
bool empty(void) const
Definition: BasicQueue.h:80
Container::value_type value_type
Type of object stored.
Definition: BasicQueue.h:39

Generated on Tue Sep 7 2021 17:32:32 for yat by  doxygen 1.8.14