source: trunk/yat/utility/Queue.h @ 3188

Last change on this file since 3188 was 3188, checked in by Peter, 10 years ago

merge patch release 0.11.2

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.0 KB
Line 
1#ifndef theplu_yat_utility_queue
2#define theplu_yat_utility_queue
3
4// $Id: Queue.h 3188 2014-03-25 10:24:29Z peter $
5//
6// Copyright (C) 2013 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 this program. If not, see <http://www.gnu.org/licenses/>.
20
21#include <boost/thread.hpp>
22
23#include <deque>
24#include <utility>
25
26namespace theplu {
27namespace yat {
28namespace utility {
29
30  /**
31     \brief Multi-thread safe queue
32
33     This class provides a multi-thread safe queue. The Queue is
34     typically shared by multiple threads such that some threads push
35     elements and some pop elements. The Queue is a "first in first
36     out" container and holds the same functionality as the similar
37     <a href="http://www.sgi.com/tech/stl/queue.html">std::queue</a>. The
38     difference is that Queue is multi-thread safe, in other words,
39     when one thread access the Queue, other threads are locked out
40     from access so that only one thread touches the Queue at a time
41     and its behaviour is well defined. In a single-thread application
42     there is no point in using the class as std::queue should be
43     prefereble.
44
45     \note Copy constructor and assignment are available but they are
46     not thread safe in the current implementation.
47
48     \since New in yat 0.11
49   */
50  template<typename T>
51  class Queue
52  {
53  public:
54    /// Type of object stored in Queue
55    typedef T value_type;
56
57    /**
58       An unsigned integral type. \see size(void)
59    */
60    typedef typename std::deque<T>::size_type size_type;
61
62    /**
63       \brief Create a Queue with no elements
64    */
65    Queue(void) {}
66
67    /**
68       \brief Copy constructor
69
70       \note is not thread safe
71    */
72    Queue(const Queue& other) : q_(other.q_) {}
73
74    /**
75       \return \c true if container's size is zero
76     */
77    bool empty(void) const
78    {
79      boost::unique_lock<boost::mutex> lock(mutex_);
80      return q_.empty();
81    } // lock is released here
82
83
84    /**
85       \brief access next element is queue
86
87       Access the next element is queue. If container is empty,
88       process is waiting until other process is inserting element
89       into container.
90     */
91    void pop(T& value)
92    {
93      boost::unique_lock<boost::mutex> lock(mutex_);
94      while (q_.empty())
95        condition_.wait(lock);
96      // The obvious choice would be to create a temp copy of front,
97      // pop the queue and then return by-value. This is, however,
98      // dangerous becasue if the copy constructor throws, the queue
99      // has been popped and the element is lost. Instead we choose to
100      // pass via passed reference.
101      value = q_.front();
102      q_.pop_front();
103    } // lock is released here
104
105
106    /**
107       \brief insert an element into container
108     */
109    void push(const T& t)
110    {
111      boost::unique_lock<boost::mutex> lock(mutex_);
112      q_.push_back(t);
113      lock.unlock(); // unlock the mutex
114
115      // Notify others that data is ready after we have unlocked
116      condition_.notify_one();
117    }
118
119
120    /**
121       \return Number of elements stored in container
122     */
123    size_type size(void) const
124    {
125      boost::unique_lock<boost::mutex> lock(mutex_);
126      return q_.size();
127    } // lock is released here
128
129
130    /**
131       If Queue is empty() do nothing and return \c false, else pop
132       the element into \a value and return \c true
133     */
134    bool try_pop(T& value)
135    {
136      boost::unique_lock<boost::mutex> lock(mutex_);
137      if (q_.empty())
138        return false;
139      value = q_.front();
140      q_.pop_front();
141      return true;
142    } // lock is released here
143
144
145    /**
146       \brief assignment operator
147
148       \note is not thread safe
149     */
150    Queue& operator=(const Queue& lhs)
151    {
152      q_ = lhs.q_;
153      return *this;
154    }
155
156  private:
157    std::deque<T> q_;
158    mutable boost::mutex mutex_;
159    boost::condition_variable condition_;
160  };
161
162}}}
163#endif
Note: See TracBrowser for help on using the repository browser.