MPD 0.20.6

- Main Page
- Namespaces
- Data Structures
- Files

- File List
- Globals

WorkQueue.hxx
Go to the documentation of this file.
1 /*
2 * Copyright 2003-2017 The Music Player Daemon Project
3 * http://www.musicpd.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef _WORKQUEUE_H_INCLUDED_
21 #define _WORKQUEUE_H_INCLUDED_
22
23 #include "thread/Mutex.hxx"
24 #include "thread/Cond.hxx"
25
26 #include <assert.h>
27 #include <pthread.h>
28
29 #include <string>
30 #include <queue>
31
32 #define LOGINFO(X)
33 #define LOGERR(X)
34
48 template <class T>
49 class WorkQueue {
50 // Configuration
51 const std::string name;
52
53 // Status
54 // Worker threads having called exit
55 unsigned n_workers_exited = 0;
56 bool ok = false;
57
58 unsigned n_threads = 0;
59 pthread_t *threads = nullptr;
60
61 // Synchronization
62 std::queue<T> queue;
63 Cond client_cond;
64 Cond worker_cond;
65 Mutex mutex;
66
67 public:
71 explicit WorkQueue(const char *_name)
72 :name(_name)
73 {
74 }
75
76 ~WorkQueue() {
77 setTerminateAndWait();
78 }
79
80 WorkQueue(const WorkQueue &) = delete;
81 WorkQueue &operator=(const WorkQueue &) = delete;
82
91 bool start(unsigned nworkers, void *(*workproc)(void *), void *arg)
92 {
93 const std::lock_guard<Mutex> protect(mutex);
94
95 assert(nworkers > 0);
96 assert(!ok);
97 assert(n_threads == 0);
98 assert(threads == nullptr);
99
100 ok = true;
101 n_threads = nworkers;
102 threads = new pthread_t[n_threads];
103
104 for (unsigned i = 0; i < nworkers; i++) {
105 int err;
106 if ((err = pthread_create(&threads[i], 0, workproc, arg))) {
107 LOGERR(("WorkQueue:%s: pthread_create failed, err %d\n",
108 name.c_str(), err));
109 return false;
110 }
111 }
112
113 return true;
114 }
115
120 template<typename U>
121 bool put(U &&u)
122 {
123 const std::lock_guard<Mutex> protect(mutex);
124
125 queue.emplace(std::forward<U>(u));
126
127 // Just wake one worker, there is only one new task.
128 worker_cond.signal();
129
130 return true;
131 }
132
133
136 void setTerminateAndWait()
137 {
138 const std::lock_guard<Mutex> protect(mutex);
139
140 // Wait for all worker threads to have called workerExit()
141 ok = false;
142 while (n_workers_exited < n_threads) {
143 worker_cond.broadcast();
144 client_cond.wait(mutex);
145 }
146
147 // Perform the thread joins and compute overall status
148 // Workers return (void*)1 if ok
149 for (unsigned i = 0; i < n_threads; ++i) {
150 void *status;
151 pthread_join(threads[i], &status);
152 }
153
154 delete[] threads;
155 threads = nullptr;
156 n_threads = 0;
157
158 // Reset to start state.
159 n_workers_exited = 0;
160 }
161
167 bool take(T &tp)
168 {
169 const std::lock_guard<Mutex> protect(mutex);
170
171 if (!ok)
172 return false;
173
174 while (queue.empty()) {
175 worker_cond.wait(mutex);
176 if (!ok)
177 return false;
178 }
179
180 tp = std::move(queue.front());
181 queue.pop();
182 return true;
183 }
184
193 void workerExit()
194 {
195 const std::lock_guard<Mutex> protect(mutex);
196
197 n_workers_exited++;
198 ok = false;
199 client_cond.broadcast();
200 }
201 };
202
203 #endif /* _WORKQUEUE_H_INCLUDED_ */
WorkQueue::workerExit
void workerExit()
Advertise exit and abort queue.
Definition: WorkQueue.hxx:193
LOGERR
#define LOGERR(X)
Definition: WorkQueue.hxx:33
WorkQueue::put
bool put(U &&u)
Add item to work queue, called from client.
Definition: WorkQueue.hxx:121
WorkQueue
A WorkQueue manages the synchronisation around a queue of work items, where a number of client thread...
Definition: WorkQueue.hxx:49
PosixCond::wait
void wait(PosixMutex &mutex)
Definition: PosixCond.hxx:73
Cond
Definition: Cond.hxx:41
Mutex
Definition: Mutex.hxx:43
WorkQueue::~WorkQueue
~WorkQueue()
Definition: WorkQueue.hxx:76
Cond.hxx
WorkQueue::setTerminateAndWait
void setTerminateAndWait()
Tell the workers to exit, and wait for them.
Definition: WorkQueue.hxx:136
WorkQueue::take
bool take(T &tp)
Take task from queue.
Definition: WorkQueue.hxx:167
WorkQueue::start
bool start(unsigned nworkers, void *(*workproc)(void *), void *arg)
Start the worker threads.
Definition: WorkQueue.hxx:91
Mutex.hxx
PosixCond::signal
void signal()
Definition: PosixCond.hxx:65
WorkQueue::WorkQueue
WorkQueue(const char *_name)
Create a WorkQueue.
Definition: WorkQueue.hxx:71
PosixCond::broadcast
void broadcast()
Definition: PosixCond.hxx:69
WorkQueue::operator=
WorkQueue & operator=(const WorkQueue &)=delete