ONPOSIX  2.0
 All Classes Namespaces Files Functions Variables Enumerator Friends Macros Pages
PosixSharedQueue.hpp
Go to the documentation of this file.
1 /*
2  * PosixSharedQueue.hpp
3  *
4  * Copyright (C) 2012 Evidence Srl - www.evidence.eu.com
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #ifndef POSIXSHAREDQUEUE_HPP_
22 #define POSIXSHAREDQUEUE_HPP_
23 
24 #include <pthread.h>
25 #include <queue>
26 #include <stdexcept>
27 #include <errno.h>
28 #include <string.h>
29 #include "PosixMutex.hpp"
30 #include "Assert.hpp"
31 
32 namespace onposix {
33 
34 /**
35  * \brief Implementation of a thread safe FIFO queue class.
36  *
37  * The template parameter is the type of the elements contained in the queue.
38  * The class is non copyable and makes use of POSIX threads (pthreads).
39  */
40 template<typename T>
42 
43  std::queue<T> queue_;
44  pthread_cond_t empty_;
45  mutable pthread_mutex_t mutex_;
46 
49 
50 public:
53 
54  void push(const T& data);
55 
56  T pop();
57 
58  void clear();
59 
60  size_t size() const;
61 };
62 
63 /**
64  * \brief Constructor. Initialize the queue.
65  *
66  * @exception runtime_error if the initialization fails.
67  */
68 template<typename T>
70 {
71  if (pthread_mutex_init(&mutex_, NULL) != 0)
72  throw std::runtime_error(std::string("Mutex initialization: ") +
73  strerror(errno));
74  if (pthread_cond_init(&empty_, NULL) != 0)
75  throw std::runtime_error(std::string("Condition variable initialization: ") +
76  strerror(errno));
77 }
78 
79 /**
80  * \brief Destructor. Clean up the resources.
81  */
82 template<typename T>
84 {
85  VERIFY_ASSERTION(!pthread_mutex_destroy(&mutex_));
86  VERIFY_ASSERTION(!pthread_cond_destroy(&empty_));
87 }
88 
89 /**
90  * \brief Inserts an element in the queue
91  *
92  * @param data The element to be added in the queue.
93  */
94 template<typename T>
95 void PosixSharedQueue<T>::push(const T &data)
96 {
97  {
98  PthreadMutexLocker lock(mutex_);
99  queue_.push(data);
100  }
101  pthread_cond_signal(&empty_);
102 }
103 
104 /**
105  * \brief Extracts an element from the queue.
106  *
107  * Blocks the calling thread if the queue is empty.
108  * @return The first element in the queue.
109  */
110 template<typename T>
112 {
113  PthreadMutexLocker lock(mutex_);
114  while (queue_.empty())
115  if (pthread_cond_wait(&empty_, &mutex_) != 0)
116  throw std::runtime_error(std::string("Condition variable wait: ") +
117  strerror(errno));
118  T data = queue_.front();
119  queue_.pop();
120  return data;
121 }
122 
123 /**
124  * \brief Empties the queue.
125  *
126  * In order to efficiently accomplish its task,
127  * this function exchanges its content with an empty queue using the specialized
128  * version of swap() implemented for the STL container std::queue.
129  */
130 template<typename T>
132 {
133  PthreadMutexLocker lock(mutex_);
134  std::queue<T> empty;
135  std::swap(queue_, empty);
136 }
137 
138 /** \brief The current size of the queue.
139  *
140  * @return The queue size.
141  */
142 template<typename T>
144 {
145  PthreadMutexLocker lock(mutex_);
146  return queue_.size();
147 }
148 
149 } /* onposix */
150 
151 #endif /* POSIXSHAREDQUEUE_HPP_ */