libosmscout  1.1.1
ProcessingQueue.h
Go to the documentation of this file.
1 #ifndef OSMSCOUT_UTIL_PROCESSINGQUEUE_H
2 #define OSMSCOUT_UTIL_PROCESSINGQUEUE_H
3 
4 /*
5  This source is part of the libosmscout library
6  Copyright (C) 2020 Tim Teulings
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22 
23 #include <condition_variable>
24 #include <deque>
25 #include <limits>
26 #include <memory>
27 #include <mutex>
28 #include <optional>
29 
31 
32 namespace osmscout {
33 
54  template<typename T>
56  {
57  private:
58  std::mutex mutex;
59  std::condition_variable pushCondition;
60  std::condition_variable popCondition;
61  std::deque<T> tasks;
62  size_t queueLimit=std::numeric_limits<size_t>::max();
63  bool running{true};
64 
65  public:
67  explicit ProcessingQueue(size_t queueLimit);
68 
69  ProcessingQueue(const ProcessingQueue&) = delete;
70  ProcessingQueue &operator=(const ProcessingQueue&) = delete;
71 
72  ~ProcessingQueue() = default;
73 
74  void PushTask(const T& task);
75  void PushTask(T&& task);
76  std::optional<T> PopTask();
77 
78  void Stop();
79  };
80 
86  template<class T>
88 
97  template<class T>
99  : queueLimit(queueLimit)
100  {
101  // no code
102  }
103 
111  template<class T>
112  void ProcessingQueue<T>::PushTask(const T& task)
113  {
114  std::unique_lock lock(mutex);
115 
116  pushCondition.wait(lock,[this]{return tasks.size()<queueLimit;});
117 
118  tasks.push_back(task);
119 
120  lock.unlock();
121 
122  popCondition.notify_one();
123  }
124 
132  template<class T>
134  {
135  std::unique_lock lock(mutex);
136 
137  pushCondition.wait(lock,[this]{return tasks.size()<queueLimit;});
138 
139  tasks.push_back(std::forward<T>(task));
140 
141  lock.unlock();
142 
143  popCondition.notify_one();
144  }
145 
153  template<class T>
154  std::optional<T> ProcessingQueue<T>::PopTask()
155  {
156  std::unique_lock lock(mutex);
157 
158  popCondition.wait(lock,[this]{return !tasks.empty() || !running;});
159 
160  if (!running &&
161  tasks.empty()) {
162  return std::nullopt;
163  }
164 
165  std::optional<T> task=std::move(tasks.front());
166  tasks.pop_front();
167 
168  lock.unlock();
169 
170  pushCondition.notify_one();
171 
172  return task;
173  }
174 
181  template<class R>
183  {
184  std::unique_lock lock(mutex);
185 
186  running=false;
187 
188  lock.unlock();
189 
190  popCondition.notify_all();
191  }
192 }
193 
194 #endif
Definition: Area.h:38
void PushTask(const T &task)
Definition: ProcessingQueue.h:112
ProcessingQueue & operator=(const ProcessingQueue &)=delete
void Stop()
Definition: ProcessingQueue.h:182
std::optional< T > PopTask()
Definition: ProcessingQueue.h:154
Definition: ProcessingQueue.h:55