From ea0df3e4cb75a7a104a81e050c019049219c4fee Mon Sep 17 00:00:00 2001
From: sapier <Sapier at GMX dot net>
Date: Fri, 31 Jan 2014 22:16:47 +0100
Subject: [PATCH] jthread remove locks that aren't absolutely required add
 c++11 atomic support (optional)

---
 src/jthread/jthread.h           | 38 ++++++++++++++++++---
 src/jthread/pthread/jthread.cpp | 58 +++------------------------------
 src/jthread/win32/jthread.cpp   | 52 ++---------------------------
 3 files changed, 39 insertions(+), 109 deletions(-)

diff --git a/src/jthread/jthread.h b/src/jthread/jthread.h
index f7bce6f9a..89743a3e3 100644
--- a/src/jthread/jthread.h
+++ b/src/jthread/jthread.h
@@ -26,9 +26,12 @@
 */
 
 #ifndef JTHREAD_H
-
 #define JTHREAD_H
 
+#if __cplusplus >= 201103L
+#include <atomic>
+#endif
+
 #include "jthread/jmutex.h"
 
 #define ERR_JTHREAD_CANTINITMUTEX						-1
@@ -43,11 +46,14 @@ public:
 	JThread();
 	virtual ~JThread();
 	int Start();
-	void Stop();
+	inline void Stop()
+		{ requeststop = true; }
 	int Kill();
 	virtual void *Thread() = 0;
-	bool IsRunning();
-	bool StopRequested();
+	inline bool IsRunning()
+		{ return running; }
+	inline bool StopRequested()
+		{ return requeststop; }
 	void *GetReturnValue();
 	bool IsSameThread();
 
@@ -75,13 +81,35 @@ private:
 
 	pthread_t threadid;
 
+	/*
+	 * reading and writing bool values is atomic on all relevant architectures
+	 * ( x86 + arm ). No need to waste time for locking here.
+	 * once C++11 is supported we can tell compiler to handle cpu caches correct
+	 * too. This should cause additional improvement (and silence thread
+	 * concurrency check tools.
+	 */
+#if __cplusplus >= 201103L
+	std::atomic_bool started;
+#else
 	bool started;
+#endif
 #endif // WIN32
 	void *retval;
+	/*
+	 * reading and writing bool values is atomic on all relevant architectures
+	 * ( x86 + arm ). No need to waste time for locking here.
+	 * once C++11 is supported we can tell compiler to handle cpu caches correct
+	 * too. This should cause additional improvement (and silence thread
+	 * concurrency check tools.
+	 */
+#if __cplusplus >= 201103L
+	std::atomic_bool running;
+	std::atomic_bool requeststop;
+#else
 	bool running;
 	bool requeststop;
+#endif
 
-	JMutex runningmutex;
 	JMutex continuemutex,continuemutex2;
 };
 
diff --git a/src/jthread/pthread/jthread.cpp b/src/jthread/pthread/jthread.cpp
index d818b19ed..a8e54e315 100644
--- a/src/jthread/pthread/jthread.cpp
+++ b/src/jthread/pthread/jthread.cpp
@@ -46,38 +46,25 @@ JThread::~JThread()
 	Kill();
 }
 
-void JThread::Stop() {
-	runningmutex.Lock();
-	requeststop = true;
-	runningmutex.Unlock();
-}
-
 void JThread::Wait() {
 	void* status;
-	runningmutex.Lock();
 	if (started) {
-		runningmutex.Unlock();
 		int pthread_join_retval = pthread_join(threadid,&status);
 		assert(pthread_join_retval == 0);
 		UNUSED(pthread_join_retval);
-		runningmutex.Lock();
 		started = false;
 	}
-	runningmutex.Unlock();
 }
 
 int JThread::Start()
 {
 	int status;
 
-	runningmutex.Lock();
 	if (running)
 	{
-		runningmutex.Unlock();
 		return ERR_JTHREAD_ALREADYRUNNING;
 	}
 	requeststop = false;
-	runningmutex.Unlock();
 
 	pthread_attr_t attr;
 	pthread_attr_init(&attr);
@@ -94,21 +81,15 @@ int JThread::Start()
 
 	/* Wait until 'running' is set */
 
-	runningmutex.Lock();
 	while (!running)
 	{
-		runningmutex.Unlock();
-
 		struct timespec req,rem;
 
 		req.tv_sec = 0;
 		req.tv_nsec = 1000000;
 		nanosleep(&req,&rem);
-
-		runningmutex.Lock();
 	}
 	started = true;
-	runningmutex.Unlock();
 
 	continuemutex.Unlock();
 
@@ -120,63 +101,37 @@ int JThread::Start()
 int JThread::Kill()
 {
 	void* status;
-	runningmutex.Lock();
 	if (!running)
 	{
 		if (started) {
-			runningmutex.Unlock();
 			int pthread_join_retval = pthread_join(threadid,&status);
 			assert(pthread_join_retval == 0);
 			UNUSED(pthread_join_retval);
-			runningmutex.Lock();
 			started = false;
 		}
-		runningmutex.Unlock();
 		return ERR_JTHREAD_NOTRUNNING;
 	}
 	pthread_cancel(threadid);
 	if (started) {
-		runningmutex.Unlock();
 		int pthread_join_retval = pthread_join(threadid,&status);
 		assert(pthread_join_retval == 0);
 		UNUSED(pthread_join_retval);
-		runningmutex.Lock();
 		started = false;
 	}
 	running = false;
-	runningmutex.Unlock();
 	return 0;
 }
 
-bool JThread::IsRunning()
-{
-	bool r;
-
-	runningmutex.Lock();
-	r = running;
-	runningmutex.Unlock();
-	return r;
-}
-
-bool JThread::StopRequested() {
-	bool r;
-
-	runningmutex.Lock();
-	r = requeststop;
-	runningmutex.Unlock();
-	return r;
-}
-
 void *JThread::GetReturnValue()
 {
 	void *val;
 
-	runningmutex.Lock();
-	if (running)
+	if (running) {
 		val = NULL;
-	else
+	} else {
 		val = retval;
-	runningmutex.Unlock();
+	}
+
 	return val;
 }
 
@@ -193,19 +148,14 @@ void *JThread::TheThread(void *param)
 	jthread = (JThread *)param;
 
 	jthread->continuemutex2.Lock();
-	jthread->runningmutex.Lock();
 	jthread->running = true;
-	jthread->runningmutex.Unlock();
 
 	jthread->continuemutex.Lock();
 	jthread->continuemutex.Unlock();
 
 	ret = jthread->Thread();
 
-	jthread->runningmutex.Lock();
 	jthread->running = false;
-	jthread->retval = ret;
-	jthread->runningmutex.Unlock();
 
 	return NULL;
 }
diff --git a/src/jthread/win32/jthread.cpp b/src/jthread/win32/jthread.cpp
index 6a745c590..a1cf91a2c 100755
--- a/src/jthread/win32/jthread.cpp
+++ b/src/jthread/win32/jthread.cpp
@@ -44,35 +44,20 @@ JThread::~JThread()
 	Kill();
 }
 
-void JThread::Stop() {
-	runningmutex.Lock();
-	requeststop = true;
-	runningmutex.Unlock();
-}
-
 void JThread::Wait() {
-	runningmutex.Lock();
 	if (running)
 	{
-		runningmutex.Unlock();
 		WaitForSingleObject(threadhandle, INFINITE);
 	}
-	else
-	{
-		runningmutex.Unlock();
-	}
 }
 
 int JThread::Start()
 {
-	runningmutex.Lock();
 	if (running)
 	{
-		runningmutex.Unlock();
 		return ERR_JTHREAD_ALREADYRUNNING;
 	}
 	requeststop = false;
-	runningmutex.Unlock();
 
 	continuemutex.Lock();
 #ifndef _WIN32_WCE
@@ -87,15 +72,10 @@ int JThread::Start()
 	}
 
 	/* Wait until 'running' is set */
-
-	runningmutex.Lock();
 	while (!running)
 	{
-		runningmutex.Unlock();
 		Sleep(1);
-		runningmutex.Lock();
 	}
-	runningmutex.Unlock();
 
 	continuemutex.Unlock();
 
@@ -107,48 +87,24 @@ int JThread::Start()
 
 int JThread::Kill()
 {
-	runningmutex.Lock();
 	if (!running)
 	{
-		runningmutex.Unlock();
 		return ERR_JTHREAD_NOTRUNNING;
 	}
 	TerminateThread(threadhandle,0);
 	CloseHandle(threadhandle);
 	running = false;
-	runningmutex.Unlock();
 	return 0;
 }
 
-bool JThread::IsRunning()
-{
-	bool r;
-
-	runningmutex.Lock();
-	r = running;
-	runningmutex.Unlock();
-	return r;
-}
-
-bool JThread::StopRequested() {
-	bool r;
-
-	runningmutex.Lock();
-	r = requeststop;
-	runningmutex.Unlock();
-	return r;
-}
-
 void *JThread::GetReturnValue()
 {
 	void *val;
 
-	runningmutex.Lock();
-	if (running)
+	if (running) {
 		val = NULL;
-	else
+	} else {
 		val = retval;
-	runningmutex.Unlock();
 	return val;
 }
 
@@ -169,20 +125,16 @@ DWORD WINAPI JThread::TheThread(void *param)
 	jthread = (JThread *)param;
 
 	jthread->continuemutex2.Lock();
-	jthread->runningmutex.Lock();
 	jthread->running = true;
-	jthread->runningmutex.Unlock();
 
 	jthread->continuemutex.Lock();
 	jthread->continuemutex.Unlock();
 
 	ret = jthread->Thread();
 
-	jthread->runningmutex.Lock();
 	jthread->running = false;
 	jthread->retval = ret;
 	CloseHandle(jthread->threadhandle);
-	jthread->runningmutex.Unlock();
 	return 0;
 }
 
-- 
2.25.1