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"
34 MutexedVariable(T value):
41 JMutexAutoLock lock(m_mutex);
47 JMutexAutoLock lock(m_mutex);
51 // You'll want to grab this in a SharedPtr
52 JMutexAutoLock * getLock()
54 return new JMutexAutoLock(m_mutex);
57 // You pretty surely want to grab the lock when accessing this
65 A single worker thread - multiple client threads queue framework.
67 template<typename Key, typename T, typename Caller, typename CallerData>
73 std::pair<Caller, CallerData> caller;
76 template<typename Key, typename T, typename Caller, typename CallerData>
77 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
81 template<typename Caller, typename Data, typename Key, typename T>
87 ResultQueue< Key, T, Caller, Data>* dest;
90 template<typename Key, typename T, typename Caller, typename CallerData>
106 std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
110 * Notes for RequestQueue usage
111 * @param Key unique key to identify a request for a specific resource
113 * @param Caller unique id of calling thread
114 * @param CallerData data passed back to caller
116 template<typename Key, typename T, typename Caller, typename CallerData>
122 return m_queue.empty();
125 void add(Key key, Caller caller, CallerData callerdata,
126 ResultQueue<Key, T, Caller, CallerData> *dest)
129 JMutexAutoLock lock(m_queue.getMutex());
132 If the caller is already on the list, only update CallerData
134 for(typename std::deque< GetRequest<Key, T, Caller, CallerData> >::iterator
135 i = m_queue.getQueue().begin();
136 i != m_queue.getQueue().end(); ++i)
138 GetRequest<Key, T, Caller, CallerData> &request = *i;
140 if(request.key == key)
142 for(typename std::list< CallerInfo<Caller, CallerData, Key, T> >::iterator
143 i = request.callers.begin();
144 i != request.callers.end(); ++i)
146 CallerInfo<Caller, CallerData, Key, T> &ca = *i;
147 if(ca.caller == caller)
149 ca.data = callerdata;
153 CallerInfo<Caller, CallerData, Key, T> ca;
155 ca.data = callerdata;
157 request.callers.push_back(ca);
164 Else add a new request to the queue
167 GetRequest<Key, T, Caller, CallerData> request;
169 CallerInfo<Caller, CallerData, Key, T> ca;
171 ca.data = callerdata;
173 request.callers.push_back(ca);
175 m_queue.push_back(request);
178 GetRequest<Key, T, Caller, CallerData> pop(unsigned int timeout_ms)
180 return m_queue.pop_front(timeout_ms);
183 GetRequest<Key, T, Caller, CallerData> pop()
185 return m_queue.pop_frontNoEx();
188 void pushResult(GetRequest<Key, T, Caller, CallerData> req,
191 for(typename std::list< CallerInfo<Caller, CallerData, Key, T> >::iterator
192 i = req.callers.begin();
193 i != req.callers.end(); ++i)
195 CallerInfo<Caller, CallerData, Key, T> &ca = *i;
197 GetResult<Key,T,Caller,CallerData> result;
199 result.key = req.key;
201 result.caller.first = ca.caller;
202 result.caller.second = ca.data;
204 ca.dest->push_back(result);
209 MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
212 class UpdateThread : public JThread
215 JSemaphore m_update_sem;
218 virtual void doUpdate() = 0;
219 virtual const char *getName() = 0;
245 const char *thread_name = getName();
247 log_register_thread(thread_name);
249 DSTACK(__FUNCTION_NAME);
251 BEGIN_DEBUG_EXCEPTION_HANDLER
253 porting::setThreadName(thread_name);
255 while (!StopRequested()) {
259 // Empty the queue, just in case doUpdate() is expensive
260 while (m_update_sem.GetValue()) m_update_sem.Wait();
262 if (StopRequested()) break;
266 END_DEBUG_EXCEPTION_HANDLER(errorstream)