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

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

add typedefs value_type and size_type to converge towards STL containers.

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