xoreos  0.0.5
thread.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
27 #include "src/common/fallthrough.h"
29 #include <SDL_timer.h>
31 
32 #include "src/common/thread.h"
33 #include "src/common/util.h"
34 
35 namespace Common {
36 
37 Thread::Thread() : _killThread(false), _thread(0), _threadRunning(false) {
38 }
39 
41  destroyThread();
42 }
43 
44 bool Thread::createThread(const UString &name) {
45  if (_threadRunning.load(boost::memory_order_relaxed)) {
46  if (_name == name) {
47  warning("Thread::createThread(): Thread \"%s\" already running", _name.c_str());
48  return true;
49  }
50 
51  warning("Thread::createThread(): Thread \"%s\" already running and trying to rename to \"%s\"", _name.c_str(), name.c_str());
52  return false;
53  }
54 
55  _name = name;
56 
57  // Try to create the thread
58  if (!(_thread = SDL_CreateThread(threadHelper, _name.empty() ? 0 : _name.c_str(), static_cast<void *>(this))))
59  return false;
60 
61  return true;
62 }
63 
65  if (!_threadRunning.load(boost::memory_order_seq_cst)) {
66  SDL_WaitThread(_thread, 0);
67  _thread = 0;
68 
69  return true;
70  }
71 
72  // Signal the thread that it should die
73  _killThread.store(true, boost::memory_order_seq_cst);
74 
75  // Wait a whole second for the thread to finish on its own
76  for (int i = 0; _threadRunning.load(boost::memory_order_seq_cst) && (i < 100); i++)
77  SDL_Delay(10);
78 
79  _killThread.store(false, boost::memory_order_seq_cst);
80 
81  const bool stillRunning = _threadRunning.load(boost::memory_order_seq_cst);
82 
83  /* Clean up the thread if it's not still running. If the thread is still running,
84  * this would block, potentially indefinitely, so we leak instead in that case.
85  *
86  * We could use SDL_DetachThread() instead, but:
87  * - This only means that thread resources will be released once the thread
88  * ends. We waited for a whole second, so it might just not.
89  * - SDL_DetachThread() was added in SDL 2.0.2, so we'd need to bump the
90  * minimum SDL version from 2.0.0 to 2.0.2. Not worth it for this case, IMHO. */
91  if (!stillRunning)
92  SDL_WaitThread(_thread, 0);
93 
94  _thread = 0;
95 
96  /* TODO:: If we get threads that we start and stop multiple times within the runtime
97  * of xoreos, we might need to do something more aggressive here, like throw. */
98  if (stillRunning) {
99  warning("Thread::destroyThread(): Thread \"%s\" still running", _name.c_str());
100  return false;
101  }
102 
103  return true;
104 }
105 
106 int Thread::threadHelper(void *obj) {
107  Thread *thread = static_cast<Thread *>(obj);
108 
109  // The thread is running.
110  thread->_threadRunning.store(true, boost::memory_order_relaxed);
111 
112  // Run the thread
113  thread->threadMethod();
114 
115  // Thread thread is not running.
116  thread->_threadRunning.store(false, boost::memory_order_relaxed);
117 
118  return 0;
119 }
120 
121 } // End of namespace Common
Definition: 2dafile.h:39
#define START_IGNORE_IMPLICIT_FALLTHROUGH
Definition: fallthrough.h:79
SDL_Thread * _thread
Definition: thread.h:56
A class holding an UTF-8 string.
Definition: ustring.h:48
bool destroyThread()
Definition: thread.cpp:64
boost::atomic< bool > _killThread
Definition: thread.h:53
virtual ~Thread()
Definition: thread.cpp:40
Threading helpers.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
bool createThread(const UString &name="")
Definition: thread.cpp:44
A class that creates its own thread.
Definition: thread.h:44
Utility templates and functions.
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
void warning(const char *s,...)
Definition: util.cpp:33
#define STOP_IGNORE_IMPLICIT_FALLTHROUGH
Definition: fallthrough.h:80
virtual void threadMethod()=0
static int threadHelper(void *obj)
Definition: thread.cpp:106
Compiler-specific defines to mark an implicit switch-case fallthrough.
Common::UString _name
Definition: thread.h:57
boost::atomic< bool > _threadRunning
Definition: thread.h:59