incrementaltp: respect physics overrides
[waspsaliva.git] / src / util / thread.h
blob73e9beb806f44d8effc6dd8e3a3bec3f82adf23f
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser 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.
20 #pragma once
22 #include "irrlichttypes.h"
23 #include "threading/thread.h"
24 #include "threading/mutex_auto_lock.h"
25 #include "porting.h"
26 #include "log.h"
27 #include "container.h"
29 template<typename T>
30 class MutexedVariable
32 public:
33 MutexedVariable(const T &value):
34 m_value(value)
37 T get()
39 MutexAutoLock lock(m_mutex);
40 return m_value;
43 void set(const T &value)
45 MutexAutoLock lock(m_mutex);
46 m_value = value;
49 // You pretty surely want to grab the lock when accessing this
50 T m_value;
51 private:
52 std::mutex m_mutex;
56 A single worker thread - multiple client threads queue framework.
58 template<typename Key, typename T, typename Caller, typename CallerData>
59 class GetResult {
60 public:
61 Key key;
62 T item;
63 std::pair<Caller, CallerData> caller;
66 template<typename Key, typename T, typename Caller, typename CallerData>
67 class ResultQueue : public MutexedQueue<GetResult<Key, T, Caller, CallerData> > {
70 template<typename Caller, typename Data, typename Key, typename T>
71 class CallerInfo {
72 public:
73 Caller caller;
74 Data data;
75 ResultQueue<Key, T, Caller, Data> *dest;
78 template<typename Key, typename T, typename Caller, typename CallerData>
79 class GetRequest {
80 public:
81 GetRequest() = default;
82 ~GetRequest() = default;
84 GetRequest(const Key &a_key): key(a_key)
88 Key key;
89 std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
92 /**
93 * Notes for RequestQueue usage
94 * @param Key unique key to identify a request for a specific resource
95 * @param T ?
96 * @param Caller unique id of calling thread
97 * @param CallerData data passed back to caller
99 template<typename Key, typename T, typename Caller, typename CallerData>
100 class RequestQueue {
101 public:
102 bool empty()
104 return m_queue.empty();
107 void add(const Key &key, Caller caller, CallerData callerdata,
108 ResultQueue<Key, T, Caller, CallerData> *dest)
110 typename std::deque<GetRequest<Key, T, Caller, CallerData> >::iterator i;
111 typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator j;
114 MutexAutoLock lock(m_queue.getMutex());
117 If the caller is already on the list, only update CallerData
119 for (i = m_queue.getQueue().begin(); i != m_queue.getQueue().end(); ++i) {
120 GetRequest<Key, T, Caller, CallerData> &request = *i;
121 if (request.key != key)
122 continue;
124 for (j = request.callers.begin(); j != request.callers.end(); ++j) {
125 CallerInfo<Caller, CallerData, Key, T> &ca = *j;
126 if (ca.caller == caller) {
127 ca.data = callerdata;
128 return;
132 CallerInfo<Caller, CallerData, Key, T> ca;
133 ca.caller = caller;
134 ca.data = callerdata;
135 ca.dest = dest;
136 request.callers.push_back(ca);
137 return;
142 Else add a new request to the queue
145 GetRequest<Key, T, Caller, CallerData> request;
146 request.key = key;
147 CallerInfo<Caller, CallerData, Key, T> ca;
148 ca.caller = caller;
149 ca.data = callerdata;
150 ca.dest = dest;
151 request.callers.push_back(ca);
153 m_queue.push_back(request);
156 GetRequest<Key, T, Caller, CallerData> pop(unsigned int timeout_ms)
158 return m_queue.pop_front(timeout_ms);
161 GetRequest<Key, T, Caller, CallerData> pop()
163 return m_queue.pop_frontNoEx();
166 void pushResult(GetRequest<Key, T, Caller, CallerData> req, T res)
168 for (typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator
169 i = req.callers.begin();
170 i != req.callers.end(); ++i) {
171 CallerInfo<Caller, CallerData, Key, T> &ca = *i;
173 GetResult<Key,T,Caller,CallerData> result;
175 result.key = req.key;
176 result.item = res;
177 result.caller.first = ca.caller;
178 result.caller.second = ca.data;
180 ca.dest->push_back(result);
184 private:
185 MutexedQueue<GetRequest<Key, T, Caller, CallerData> > m_queue;
188 class UpdateThread : public Thread
190 public:
191 UpdateThread(const std::string &name) : Thread(name + "Update") {}
192 ~UpdateThread() = default;
194 void deferUpdate() { m_update_sem.post(); }
196 void stop()
198 Thread::stop();
200 // give us a nudge
201 m_update_sem.post();
204 void *run()
206 BEGIN_DEBUG_EXCEPTION_HANDLER
208 while (!stopRequested()) {
209 m_update_sem.wait();
210 // Set semaphore to 0
211 while (m_update_sem.wait(0));
213 if (stopRequested()) break;
215 doUpdate();
218 END_DEBUG_EXCEPTION_HANDLER
220 return NULL;
223 protected:
224 virtual void doUpdate() = 0;
226 private:
227 Semaphore m_update_sem;