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 #ifndef UTIL_THREAD_HEADER
21 #define UTIL_THREAD_HEADER
23 #include "../irrlichttypes.h"
24 #include "../threading/thread.h"
25 #include "../threading/mutex_auto_lock.h"
28 #include "container.h"
34 MutexedVariable(const T &value):
40 MutexAutoLock lock(m_mutex);
44 void set(const T &value)
46 MutexAutoLock lock(m_mutex);
50 // You pretty surely want to grab the lock when accessing this
57 A single worker thread - multiple client threads queue framework.
59 template<typename Key, typename T, typename Caller, typename CallerData>
64 std::pair<Caller, CallerData> caller;
67 template<typename Key, typename T, typename Caller, typename CallerData>
68 class ResultQueue : public MutexedQueue<GetResult<Key, T, Caller, CallerData> > {
71 template<typename Caller, typename Data, typename Key, typename T>
76 ResultQueue<Key, T, Caller, Data> *dest;
79 template<typename Key, typename T, typename Caller, typename CallerData>
85 GetRequest(const Key &a_key): key(a_key)
90 std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
94 * Notes for RequestQueue usage
95 * @param Key unique key to identify a request for a specific resource
97 * @param Caller unique id of calling thread
98 * @param CallerData data passed back to caller
100 template<typename Key, typename T, typename Caller, typename CallerData>
105 return m_queue.empty();
108 void add(const Key &key, Caller caller, CallerData callerdata,
109 ResultQueue<Key, T, Caller, CallerData> *dest)
111 typename std::deque<GetRequest<Key, T, Caller, CallerData> >::iterator i;
112 typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator j;
115 MutexAutoLock lock(m_queue.getMutex());
118 If the caller is already on the list, only update CallerData
120 for (i = m_queue.getQueue().begin(); i != m_queue.getQueue().end(); ++i) {
121 GetRequest<Key, T, Caller, CallerData> &request = *i;
122 if (request.key != key)
125 for (j = request.callers.begin(); j != request.callers.end(); ++j) {
126 CallerInfo<Caller, CallerData, Key, T> &ca = *j;
127 if (ca.caller == caller) {
128 ca.data = callerdata;
133 CallerInfo<Caller, CallerData, Key, T> ca;
135 ca.data = callerdata;
137 request.callers.push_back(ca);
143 Else add a new request to the queue
146 GetRequest<Key, T, Caller, CallerData> request;
148 CallerInfo<Caller, CallerData, Key, T> ca;
150 ca.data = callerdata;
152 request.callers.push_back(ca);
154 m_queue.push_back(request);
157 GetRequest<Key, T, Caller, CallerData> pop(unsigned int timeout_ms)
159 return m_queue.pop_front(timeout_ms);
162 GetRequest<Key, T, Caller, CallerData> pop()
164 return m_queue.pop_frontNoEx();
167 void pushResult(GetRequest<Key, T, Caller, CallerData> req, T res)
169 for (typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator
170 i = req.callers.begin();
171 i != req.callers.end(); ++i) {
172 CallerInfo<Caller, CallerData, Key, T> &ca = *i;
174 GetResult<Key,T,Caller,CallerData> result;
176 result.key = req.key;
178 result.caller.first = ca.caller;
179 result.caller.second = ca.data;
181 ca.dest->push_back(result);
186 MutexedQueue<GetRequest<Key, T, Caller, CallerData> > m_queue;
189 class UpdateThread : public Thread
192 UpdateThread(const std::string &name) : Thread(name + "Update") {}
195 void deferUpdate() { m_update_sem.post(); }
207 DSTACK(FUNCTION_NAME);
208 BEGIN_DEBUG_EXCEPTION_HANDLER
210 while (!stopRequested()) {
212 // Set semaphore to 0
213 while (m_update_sem.wait(0));
215 if (stopRequested()) break;
220 END_DEBUG_EXCEPTION_HANDLER
226 virtual void doUpdate() = 0;
229 Semaphore m_update_sem;