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 "../jthread/jthread.h"
25 #include "../jthread/jmutex.h"
26 #include "../jthread/jmutexautolock.h"
31 class MutexedVariable {
33 MutexedVariable(T value):
39 JMutexAutoLock lock(m_mutex);
45 JMutexAutoLock lock(m_mutex);
49 // You'll want to grab this in a SharedPtr
50 JMutexAutoLock *getLock()
52 return new JMutexAutoLock(m_mutex);
55 // You pretty surely want to grab the lock when accessing this
63 A single worker thread - multiple client threads queue framework.
65 template<typename Key, typename T, typename Caller, typename CallerData>
70 std::pair<Caller, CallerData> caller;
73 template<typename Key, typename T, typename Caller, typename CallerData>
74 class ResultQueue : public MutexedQueue<GetResult<Key, T, Caller, CallerData> > {
77 template<typename Caller, typename Data, typename Key, typename T>
82 ResultQueue<Key, T, Caller, Data> *dest;
85 template<typename Key, typename T, typename Caller, typename CallerData>
91 GetRequest(Key a_key) {
96 std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
100 * Notes for RequestQueue usage
101 * @param Key unique key to identify a request for a specific resource
103 * @param Caller unique id of calling thread
104 * @param CallerData data passed back to caller
106 template<typename Key, typename T, typename Caller, typename CallerData>
111 return m_queue.empty();
114 void add(Key key, Caller caller, CallerData callerdata,
115 ResultQueue<Key, T, Caller, CallerData> *dest)
117 typename std::deque<GetRequest<Key, T, Caller, CallerData> >::iterator i;
118 typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator j;
121 JMutexAutoLock lock(m_queue.getMutex());
124 If the caller is already on the list, only update CallerData
126 for (i = m_queue.getQueue().begin(); i != m_queue.getQueue().end(); ++i) {
127 GetRequest<Key, T, Caller, CallerData> &request = *i;
128 if (request.key != key)
131 for (j = request.callers.begin(); j != request.callers.end(); ++j) {
132 CallerInfo<Caller, CallerData, Key, T> &ca = *j;
133 if (ca.caller == caller) {
134 ca.data = callerdata;
139 CallerInfo<Caller, CallerData, Key, T> ca;
141 ca.data = callerdata;
143 request.callers.push_back(ca);
149 Else add a new request to the queue
152 GetRequest<Key, T, Caller, CallerData> request;
154 CallerInfo<Caller, CallerData, Key, T> ca;
156 ca.data = callerdata;
158 request.callers.push_back(ca);
160 m_queue.push_back(request);
163 GetRequest<Key, T, Caller, CallerData> pop(unsigned int timeout_ms)
165 return m_queue.pop_front(timeout_ms);
168 GetRequest<Key, T, Caller, CallerData> pop()
170 return m_queue.pop_frontNoEx();
173 void pushResult(GetRequest<Key, T, Caller, CallerData> req, T res)
175 for (typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator
176 i = req.callers.begin();
177 i != req.callers.end(); ++i) {
178 CallerInfo<Caller, CallerData, Key, T> &ca = *i;
180 GetResult<Key,T,Caller,CallerData> result;
182 result.key = req.key;
184 result.caller.first = ca.caller;
185 result.caller.second = ca.data;
187 ca.dest->push_back(result);
192 MutexedQueue<GetRequest<Key, T, Caller, CallerData> > m_queue;
195 class UpdateThread : public JThread {
198 virtual ~UpdateThread() {}
217 const char *thread_name = getName();
218 log_register_thread(thread_name);
219 porting::setThreadName(thread_name);
221 DSTACK(__FUNCTION_NAME);
222 BEGIN_DEBUG_EXCEPTION_HANDLER
224 while (!StopRequested()) {
227 // Empty the queue, just in case doUpdate() is expensive
228 while (m_update_sem.GetValue())
237 END_DEBUG_EXCEPTION_HANDLER(errorstream)
243 virtual void doUpdate() = 0;
244 virtual const char *getName() = 0;
247 JSemaphore m_update_sem;