]> git.lizzy.rs Git - dragonfireclient.git/blob - src/util/thread.h
Cleanup jthread and fix win32 build
[dragonfireclient.git] / src / util / thread.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #ifndef UTIL_THREAD_HEADER
21 #define UTIL_THREAD_HEADER
22
23 #include "../irrlichttypes.h"
24 #include "../jthread/jthread.h"
25 #include "../jthread/jmutex.h"
26 #include "../jthread/jmutexautolock.h"
27
28 template<typename T>
29 class MutexedVariable
30 {
31 public:
32         MutexedVariable(T value):
33                 m_value(value)
34         {
35         }
36
37         T get()
38         {
39                 JMutexAutoLock lock(m_mutex);
40                 return m_value;
41         }
42
43         void set(T value)
44         {
45                 JMutexAutoLock lock(m_mutex);
46                 m_value = value;
47         }
48         
49         // You'll want to grab this in a SharedPtr
50         JMutexAutoLock * getLock()
51         {
52                 return new JMutexAutoLock(m_mutex);
53         }
54         
55         // You pretty surely want to grab the lock when accessing this
56         T m_value;
57
58 private:
59         JMutex m_mutex;
60 };
61
62 /*
63         A base class for simple background thread implementation
64 */
65
66 class SimpleThread : public JThread
67 {
68         bool run;
69         JMutex run_mutex;
70
71 public:
72
73         SimpleThread():
74                 JThread(),
75                 run(true)
76         {
77         }
78
79         virtual ~SimpleThread()
80         {}
81
82         virtual void * Thread() = 0;
83
84         bool getRun()
85         {
86                 JMutexAutoLock lock(run_mutex);
87                 return run;
88         }
89         void setRun(bool a_run)
90         {
91                 JMutexAutoLock lock(run_mutex);
92                 run = a_run;
93         }
94
95         void stop()
96         {
97                 setRun(false);
98                 while(IsRunning())
99                         sleep_ms(100);
100         }
101 };
102
103 /*
104         A single worker thread - multiple client threads queue framework.
105 */
106
107
108
109 template<typename Key, typename T, typename Caller, typename CallerData>
110 class GetResult
111 {
112 public:
113         Key key;
114         T item;
115         std::pair<Caller, CallerData> caller;
116 };
117
118 template<typename Key, typename T, typename Caller, typename CallerData>
119 class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
120 {
121 };
122
123 template<typename Caller, typename Data, typename Key, typename T>
124 class CallerInfo
125 {
126 public:
127         Caller caller;
128         Data data;
129         ResultQueue< Key, T, Caller, Data>* dest;
130 };
131
132 template<typename Key, typename T, typename Caller, typename CallerData>
133 class GetRequest
134 {
135 public:
136         GetRequest()
137         {
138         }
139         GetRequest(Key a_key)
140         {
141                 key = a_key;
142         }
143         ~GetRequest()
144         {
145         }
146         
147         Key key;
148         std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
149 };
150
151 /**
152  * Notes for RequestQueue usage
153  * @param Key unique key to identify a request for a specific resource
154  * @param T ?
155  * @param Caller unique id of calling thread
156  * @param CallerData data passed back to caller
157  */
158 template<typename Key, typename T, typename Caller, typename CallerData>
159 class RequestQueue
160 {
161 public:
162         bool empty()
163         {
164                 return m_queue.empty();
165         }
166
167         void add(Key key, Caller caller, CallerData callerdata,
168                         ResultQueue<Key, T, Caller, CallerData> *dest)
169         {
170                 JMutexAutoLock lock(m_queue.getMutex());
171                 
172                 /*
173                         If the caller is already on the list, only update CallerData
174                 */
175                 for(typename std::list< GetRequest<Key, T, Caller, CallerData> >::iterator
176                                 i = m_queue.getList().begin();
177                                 i != m_queue.getList().end(); ++i)
178                 {
179                         GetRequest<Key, T, Caller, CallerData> &request = *i;
180
181                         if(request.key == key)
182                         {
183                                 for(typename std::list< CallerInfo<Caller, CallerData, Key, T> >::iterator
184                                                 i = request.callers.begin();
185                                                 i != request.callers.end(); ++i)
186                                 {
187                                         CallerInfo<Caller, CallerData, Key, T> &ca = *i;
188                                         if(ca.caller == caller)
189                                         {
190                                                 ca.data = callerdata;
191                                                 return;
192                                         }
193                                 }
194                                 CallerInfo<Caller, CallerData, Key, T> ca;
195                                 ca.caller = caller;
196                                 ca.data = callerdata;
197                                 ca.dest = dest;
198                                 request.callers.push_back(ca);
199                                 return;
200                         }
201                 }
202
203                 /*
204                         Else add a new request to the queue
205                 */
206
207                 GetRequest<Key, T, Caller, CallerData> request;
208                 request.key = key;
209                 CallerInfo<Caller, CallerData, Key, T> ca;
210                 ca.caller = caller;
211                 ca.data = callerdata;
212                 ca.dest = dest;
213                 request.callers.push_back(ca);
214                 
215                 m_queue.getList().push_back(request);
216         }
217
218         GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
219         {
220                 return m_queue.pop_front(wait_if_empty);
221         }
222
223         void pushResult(GetRequest<Key, T, Caller, CallerData> req,
224                                         T res) {
225
226                 for(typename std::list< CallerInfo<Caller, CallerData, Key, T> >::iterator
227                                 i = req.callers.begin();
228                                 i != req.callers.end(); ++i)
229                 {
230                         CallerInfo<Caller, CallerData, Key, T> &ca = *i;
231
232                         GetResult<Key,T,Caller,CallerData> result;
233
234                         result.key = req.key;
235                         result.item = res;
236                         result.caller.first = ca.caller;
237                         result.caller.second = ca.data;
238
239                         ca.dest->push_back(result);
240                 }
241         }
242
243 private:
244         MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
245 };
246
247 #endif
248