yat  0.16.4pre
BasicQueue.h
1 #ifndef theplu_yat_utility_basic_queue
2 #define theplu_yat_utility_basic_queue
3 
4 // $Id: BasicQueue.h 3792 2019-04-12 07:15:09Z peter $
5 //
6 // Copyright (C) 2017, 2018 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 <boost/thread.hpp>
24 
25 namespace theplu {
26 namespace yat {
27 namespace utility {
28 namespace detail {
29 
33  template<class Derived, typename T, class Container>
34  class BasicQueue
35  {
36  public:
38  typedef typename Container::value_type value_type;
39 
43  typedef typename Container::size_type size_type;
44 
48  BasicQueue(void) {}
49 
53  BasicQueue(const BasicQueue& other)
54  {
55  boost::unique_lock<boost::mutex> lock(other.mutex_);
56  q_ = other.q_;
57  } // lock is released here
58 
62  explicit BasicQueue(const Container& container) : q_(container) {}
63 
69  void clear(void)
70  {
71  boost::unique_lock<boost::mutex> lock(mutex_);
72  return q_.clear();
73  }
74 
75 
79  bool empty(void) const
80  {
81  boost::unique_lock<boost::mutex> lock(mutex_);
82  return q_.empty();
83  } // lock is released here
84 
85 
93  void pop(T& value)
94  {
95  boost::unique_lock<boost::mutex> lock(mutex_);
96  while (q_.empty())
97  condition_.wait(lock);
98  // The obvious choice would be to create a temp copy of front,
99  // pop the queue and then return by-value. This is, however,
100  // dangerous becasue if the copy constructor throws, the queue
101  // has been popped and the element is lost. Instead we choose to
102  // pass via passed reference.
103  static_cast<Derived*>(this)->pop_impl(value, lock);
104  } // lock is released here
105 
106 
110  void push(const T& t)
111  {
112  boost::unique_lock<boost::mutex> lock(mutex_);
113  static_cast<Derived*>(this)->push_impl(t, lock);
114  lock.unlock(); // unlock the mutex
115 
116  // Notify others that data is ready after we have unlocked
117  condition_.notify_one();
118  }
119 
120 
121 #ifdef YAT_HAVE_RVALUE
122 
129  void push(T&& t)
130  {
131  boost::unique_lock<boost::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 #endif
139 
140 
144  size_type size(void) const
145  {
146  boost::unique_lock<boost::mutex> lock(mutex_);
147  return q_.size();
148  } // lock is released here
149 
150 
155  bool try_pop(T& value)
156  {
157  boost::unique_lock<boost::mutex> lock(mutex_);
158  if (q_.empty())
159  return false;
160  static_cast<Derived*>(this)->pop_impl(value, lock);
161  return true;
162  } // lock is released here
163 
164  protected:
168  void assign(const BasicQueue& other)
169  {
170  if (this != &other) {
171  // boost::lock guarantees that the two mutexes are locked in
172  // the same order regardless of passed order and thereby
173  // avoiding deadlock when two threads are calling
174  // lhs.assign(rhs) and rhs.assign(lhs) simultaneously.
175  boost::lock(mutex_, other.mutex_);
176  boost::unique_lock<boost::mutex> lock(mutex_, boost::adopt_lock_t());
177  boost::unique_lock<boost::mutex> other_lock(other.mutex_,
178  boost::adopt_lock_t());
179  q_ = other.q_;
180  }
181  }
182 
184  Container q_;
185  private:
186  mutable boost::mutex mutex_;
187  boost::condition_variable condition_;
188  };
189 
190 }}}}
191 #endif
Container::size_type size_type
Definition: BasicQueue.h:43
void clear(void)
clear queue
Definition: BasicQueue.h:69
size_type size(void) const
Definition: BasicQueue.h:144
BasicQueue(const BasicQueue &other)
Definition: BasicQueue.h:53
The Department of Theoretical Physics namespace as we define it.
bool try_pop(T &value)
Definition: BasicQueue.h:155
void assign(const BasicQueue &other)
Definition: BasicQueue.h:168
Definition: BasicQueue.h:34
BasicQueue(void)
Definition: BasicQueue.h:48
void push(const T &t)
insert an element into container
Definition: BasicQueue.h:110
void pop(T &value)
access next element in queue
Definition: BasicQueue.h:93
bool empty(void) const
Definition: BasicQueue.h:79
Container q_
data
Definition: BasicQueue.h:184
BasicQueue(const Container &container)
Definition: BasicQueue.h:62
Container::value_type value_type
Type of object stored.
Definition: BasicQueue.h:38

Generated on Thu Dec 12 2019 03:12:08 for yat by  doxygen 1.8.11