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.
22 #include "irrlichttypes.h"
23 #include "threading/thread.h"
24 #include "threading/mutex_auto_lock.h"
27 #include "container.h"
33 MutexedVariable(const T
&value
):
39 MutexAutoLock
lock(m_mutex
);
43 void set(const T
&value
)
45 MutexAutoLock
lock(m_mutex
);
49 // You pretty surely want to grab the lock when accessing this
56 A single worker thread - multiple client threads queue framework.
58 template<typename Key
, typename T
, typename Caller
, typename CallerData
>
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
>
75 ResultQueue
<Key
, T
, Caller
, Data
> *dest
;
78 template<typename Key
, typename T
, typename Caller
, typename CallerData
>
81 GetRequest() = default;
82 ~GetRequest() = default;
84 GetRequest(const Key
&a_key
): key(a_key
)
89 std::list
<CallerInfo
<Caller
, CallerData
, Key
, T
> > callers
;
93 * Notes for RequestQueue usage
94 * @param Key unique key to identify a request for a specific resource
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
>
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
)
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
;
132 CallerInfo
<Caller
, CallerData
, Key
, T
> ca
;
134 ca
.data
= callerdata
;
136 request
.callers
.push_back(ca
);
142 Else add a new request to the queue
145 GetRequest
<Key
, T
, Caller
, CallerData
> request
;
147 CallerInfo
<Caller
, CallerData
, Key
, T
> ca
;
149 ca
.data
= callerdata
;
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
;
177 result
.caller
.first
= ca
.caller
;
178 result
.caller
.second
= ca
.data
;
180 ca
.dest
->push_back(result
);
185 MutexedQueue
<GetRequest
<Key
, T
, Caller
, CallerData
> > m_queue
;
188 class UpdateThread
: public Thread
191 UpdateThread(const std::string
&name
) : Thread(name
+ "Update") {}
192 ~UpdateThread() = default;
194 void deferUpdate() { m_update_sem
.post(); }
206 BEGIN_DEBUG_EXCEPTION_HANDLER
208 while (!stopRequested()) {
210 // Set semaphore to 0
211 while (m_update_sem
.wait(0));
213 if (stopRequested()) break;
218 END_DEBUG_EXCEPTION_HANDLER
224 virtual void doUpdate() = 0;
227 Semaphore m_update_sem
;