Minetest  5.4.0
thread.h
Go to the documentation of this file.
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 #pragma once
21 
22 #include "irrlichttypes.h"
23 #include "threading/thread.h"
25 #include "porting.h"
26 #include "log.h"
27 #include "container.h"
28 
29 template<typename T>
31 {
32 public:
33  MutexedVariable(const T &value):
34  m_value(value)
35  {}
36 
37  T get()
38  {
39  MutexAutoLock lock(m_mutex);
40  return m_value;
41  }
42 
43  void set(const T &value)
44  {
45  MutexAutoLock lock(m_mutex);
46  m_value = value;
47  }
48 
49  // You pretty surely want to grab the lock when accessing this
51 private:
52  std::mutex m_mutex;
53 };
54 
55 /*
56  A single worker thread - multiple client threads queue framework.
57 */
58 template<typename Key, typename T, typename Caller, typename CallerData>
59 class GetResult {
60 public:
61  Key key;
62  T item;
63  std::pair<Caller, CallerData> caller;
64 };
65 
66 template<typename Key, typename T, typename Caller, typename CallerData>
67 class ResultQueue : public MutexedQueue<GetResult<Key, T, Caller, CallerData> > {
68 };
69 
70 template<typename Caller, typename Data, typename Key, typename T>
71 class CallerInfo {
72 public:
73  Caller caller;
74  Data data;
76 };
77 
78 template<typename Key, typename T, typename Caller, typename CallerData>
79 class GetRequest {
80 public:
81  GetRequest() = default;
82  ~GetRequest() = default;
83 
84  GetRequest(const Key &a_key): key(a_key)
85  {
86  }
87 
88  Key key;
89  std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
90 };
91 
99 template<typename Key, typename T, typename Caller, typename CallerData>
101 public:
102  bool empty()
103  {
104  return m_queue.empty();
105  }
106 
107  void add(const Key &key, Caller caller, CallerData callerdata,
109  {
110  typename std::deque<GetRequest<Key, T, Caller, CallerData> >::iterator i;
111  typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator j;
112 
113  {
115 
116  /*
117  If the caller is already on the list, only update CallerData
118  */
119  for (i = m_queue.getQueue().begin(); i != m_queue.getQueue().end(); ++i) {
121  if (request.key != key)
122  continue;
123 
124  for (j = request.callers.begin(); j != request.callers.end(); ++j) {
126  if (ca.caller == caller) {
127  ca.data = callerdata;
128  return;
129  }
130  }
131 
133  ca.caller = caller;
134  ca.data = callerdata;
135  ca.dest = dest;
136  request.callers.push_back(ca);
137  return;
138  }
139  }
140 
141  /*
142  Else add a new request to the queue
143  */
144 
146  request.key = key;
148  ca.caller = caller;
149  ca.data = callerdata;
150  ca.dest = dest;
151  request.callers.push_back(ca);
152 
153  m_queue.push_back(request);
154  }
155 
157  {
158  return m_queue.pop_front(timeout_ms);
159  }
160 
162  {
163  return m_queue.pop_frontNoEx();
164  }
165 
167  {
168  for (typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator
169  i = req.callers.begin();
170  i != req.callers.end(); ++i) {
172 
174 
175  result.key = req.key;
176  result.item = res;
177  result.caller.first = ca.caller;
178  result.caller.second = ca.data;
179 
180  ca.dest->push_back(result);
181  }
182  }
183 
184 private:
186 };
187 
188 class UpdateThread : public Thread
189 {
190 public:
191  UpdateThread(const std::string &name) : Thread(name + "Update") {}
192  ~UpdateThread() = default;
193 
195 
196  void stop()
197  {
198  Thread::stop();
199 
200  // give us a nudge
201  m_update_sem.post();
202  }
203 
204  void *run()
205  {
207 
208  while (!stopRequested()) {
209  m_update_sem.wait();
210  // Set semaphore to 0
211  while (m_update_sem.wait(0));
212 
213  if (stopRequested()) break;
214 
215  doUpdate();
216  }
217 
219 
220  return NULL;
221  }
222 
223 protected:
224  virtual void doUpdate() = 0;
225 
226 private:
228 };
Definition: thread.h:71
ResultQueue< Key, T, Caller, Data > * dest
Definition: thread.h:75
Data data
Definition: thread.h:74
Caller caller
Definition: thread.h:73
Definition: thread.h:79
std::list< CallerInfo< Caller, CallerData, Key, T > > callers
Definition: thread.h:89
GetRequest()=default
~GetRequest()=default
Key key
Definition: thread.h:88
GetRequest(const Key &a_key)
Definition: thread.h:84
Definition: thread.h:59
T item
Definition: thread.h:62
std::pair< Caller, CallerData > caller
Definition: thread.h:63
Key key
Definition: thread.h:61
Definition: container.h:126
bool empty() const
Definition: container.h:133
T pop_front(u32 wait_time_max_ms)
Definition: container.h:162
void push_back(T t)
Definition: container.h:139
std::mutex & getMutex()
Definition: container.h:227
std::deque< T > & getQueue()
Definition: container.h:229
T pop_frontNoEx(u32 wait_time_max_ms)
Definition: container.h:149
Definition: thread.h:31
MutexedVariable(const T &value)
Definition: thread.h:33
T m_value
Definition: thread.h:50
std::mutex m_mutex
Definition: thread.h:52
void set(const T &value)
Definition: thread.h:43
T get()
Definition: thread.h:37
Notes for RequestQueue usage.
Definition: thread.h:100
GetRequest< Key, T, Caller, CallerData > pop()
Definition: thread.h:161
MutexedQueue< GetRequest< Key, T, Caller, CallerData > > m_queue
Definition: thread.h:185
bool empty()
Definition: thread.h:102
void add(const Key &key, Caller caller, CallerData callerdata, ResultQueue< Key, T, Caller, CallerData > *dest)
Definition: thread.h:107
void pushResult(GetRequest< Key, T, Caller, CallerData > req, T res)
Definition: thread.h:166
GetRequest< Key, T, Caller, CallerData > pop(unsigned int timeout_ms)
Definition: thread.h:156
Definition: thread.h:67
Definition: semaphore.h:33
void post(unsigned int num=1)
Definition: semaphore.cpp:85
void wait()
Definition: semaphore.cpp:100
Definition: thread.h:57
bool stop()
Definition: thread.cpp:136
bool stopRequested()
Definition: thread.h:91
Definition: thread.h:189
virtual void doUpdate()=0
UpdateThread(const std::string &name)
Definition: thread.h:191
void * run()
Definition: thread.h:204
~UpdateThread()=default
void deferUpdate()
Definition: thread.h:194
Semaphore m_update_sem
Definition: thread.h:227
void stop()
Definition: thread.h:196
#define END_DEBUG_EXCEPTION_HANDLER
Definition: debug.h:101
#define BEGIN_DEBUG_EXCEPTION_HANDLER
Definition: debug.h:100
std::unique_lock< std::mutex > MutexAutoLock
Definition: mutex_auto_lock.h:29