summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/threading/mutex.cpp9
-rw-r--r--src/threading/mutex.h2
-rw-r--r--src/threading/thread.cpp15
-rw-r--r--src/threading/thread.h1
-rw-r--r--src/unittest/test_threading.cpp2
5 files changed, 27 insertions, 2 deletions
diff --git a/src/threading/mutex.cpp b/src/threading/mutex.cpp
index 0908b5d37..d864f12c5 100644
--- a/src/threading/mutex.cpp
+++ b/src/threading/mutex.cpp
@@ -88,6 +88,15 @@ void Mutex::lock()
#endif
}
+bool Mutex::try_lock()
+{
+#if USE_WIN_MUTEX
+ return TryEnterCriticalSection(&mutex) != 0;
+#else
+ return pthread_mutex_trylock(&mutex) == 0;
+#endif
+}
+
void Mutex::unlock()
{
#if USE_WIN_MUTEX
diff --git a/src/threading/mutex.h b/src/threading/mutex.h
index fb5c029fc..6feb23c25 100644
--- a/src/threading/mutex.h
+++ b/src/threading/mutex.h
@@ -56,6 +56,8 @@ public:
void lock();
void unlock();
+ bool try_lock();
+
protected:
Mutex(bool recursive);
void init_mutex(bool recursive);
diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp
index fbe4ba1f3..4f4c9474a 100644
--- a/src/threading/thread.cpp
+++ b/src/threading/thread.cpp
@@ -101,6 +101,11 @@ Thread::Thread(const std::string &name) :
Thread::~Thread()
{
kill();
+
+ // Make sure start finished mutex is unlocked before it's destroyed
+ m_start_finished_mutex.try_lock();
+ m_start_finished_mutex.unlock();
+
}
@@ -113,6 +118,9 @@ bool Thread::start()
m_request_stop = false;
+ // The mutex may already be locked if the thread is being restarted
+ m_start_finished_mutex.try_lock();
+
#if USE_CPP11_THREADS
try {
@@ -135,6 +143,9 @@ bool Thread::start()
#endif
+ // Allow spawned thread to continue
+ m_start_finished_mutex.unlock();
+
while (!m_running)
sleep_ms(1);
@@ -249,6 +260,10 @@ DWORD WINAPI Thread::threadProc(LPVOID param)
g_logger.registerThread(thr->m_name);
thr->m_running = true;
+ // Wait for the thread that started this one to finish initializing the
+ // thread handle so that getThreadId/getThreadHandle will work.
+ thr->m_start_finished_mutex.lock();
+
thr->m_retval = thr->run();
thr->m_running = false;
diff --git a/src/threading/thread.h b/src/threading/thread.h
index 14a0e13ab..4785d3e03 100644
--- a/src/threading/thread.h
+++ b/src/threading/thread.h
@@ -153,6 +153,7 @@ private:
Atomic<bool> m_request_stop;
Atomic<bool> m_running;
Mutex m_mutex;
+ Mutex m_start_finished_mutex;
#if USE_CPP11_THREADS
std::thread *m_thread_obj;
diff --git a/src/unittest/test_threading.cpp b/src/unittest/test_threading.cpp
index cdbf9674e..e1e1d3660 100644
--- a/src/unittest/test_threading.cpp
+++ b/src/unittest/test_threading.cpp
@@ -39,9 +39,7 @@ static TestThreading g_test_instance;
void TestThreading::runTests(IGameDef *gamedef)
{
-#if !(defined(__MACH__) && defined(__APPLE__))
TEST(testStartStopWait);
-#endif
TEST(testThreadKill);
TEST(testAtomicSemaphoreThread);
}