jthread remove locks that aren't absolutely required
add c++11 atomic support (optional)master
parent
c00ed9dac3
commit
ea0df3e4cb
|
@ -26,9 +26,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef JTHREAD_H
|
#ifndef JTHREAD_H
|
||||||
|
|
||||||
#define JTHREAD_H
|
#define JTHREAD_H
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
#include <atomic>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "jthread/jmutex.h"
|
#include "jthread/jmutex.h"
|
||||||
|
|
||||||
#define ERR_JTHREAD_CANTINITMUTEX -1
|
#define ERR_JTHREAD_CANTINITMUTEX -1
|
||||||
|
@ -43,11 +46,14 @@ public:
|
||||||
JThread();
|
JThread();
|
||||||
virtual ~JThread();
|
virtual ~JThread();
|
||||||
int Start();
|
int Start();
|
||||||
void Stop();
|
inline void Stop()
|
||||||
|
{ requeststop = true; }
|
||||||
int Kill();
|
int Kill();
|
||||||
virtual void *Thread() = 0;
|
virtual void *Thread() = 0;
|
||||||
bool IsRunning();
|
inline bool IsRunning()
|
||||||
bool StopRequested();
|
{ return running; }
|
||||||
|
inline bool StopRequested()
|
||||||
|
{ return requeststop; }
|
||||||
void *GetReturnValue();
|
void *GetReturnValue();
|
||||||
bool IsSameThread();
|
bool IsSameThread();
|
||||||
|
|
||||||
|
@ -75,13 +81,35 @@ private:
|
||||||
|
|
||||||
pthread_t threadid;
|
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;
|
bool started;
|
||||||
|
#endif
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
void *retval;
|
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 running;
|
||||||
bool requeststop;
|
bool requeststop;
|
||||||
|
#endif
|
||||||
|
|
||||||
JMutex runningmutex;
|
|
||||||
JMutex continuemutex,continuemutex2;
|
JMutex continuemutex,continuemutex2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,38 +46,25 @@ JThread::~JThread()
|
||||||
Kill();
|
Kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JThread::Stop() {
|
|
||||||
runningmutex.Lock();
|
|
||||||
requeststop = true;
|
|
||||||
runningmutex.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JThread::Wait() {
|
void JThread::Wait() {
|
||||||
void* status;
|
void* status;
|
||||||
runningmutex.Lock();
|
|
||||||
if (started) {
|
if (started) {
|
||||||
runningmutex.Unlock();
|
|
||||||
int pthread_join_retval = pthread_join(threadid,&status);
|
int pthread_join_retval = pthread_join(threadid,&status);
|
||||||
assert(pthread_join_retval == 0);
|
assert(pthread_join_retval == 0);
|
||||||
UNUSED(pthread_join_retval);
|
UNUSED(pthread_join_retval);
|
||||||
runningmutex.Lock();
|
|
||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
runningmutex.Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int JThread::Start()
|
int JThread::Start()
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
runningmutex.Lock();
|
|
||||||
if (running)
|
if (running)
|
||||||
{
|
{
|
||||||
runningmutex.Unlock();
|
|
||||||
return ERR_JTHREAD_ALREADYRUNNING;
|
return ERR_JTHREAD_ALREADYRUNNING;
|
||||||
}
|
}
|
||||||
requeststop = false;
|
requeststop = false;
|
||||||
runningmutex.Unlock();
|
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
|
@ -94,21 +81,15 @@ int JThread::Start()
|
||||||
|
|
||||||
/* Wait until 'running' is set */
|
/* Wait until 'running' is set */
|
||||||
|
|
||||||
runningmutex.Lock();
|
|
||||||
while (!running)
|
while (!running)
|
||||||
{
|
{
|
||||||
runningmutex.Unlock();
|
|
||||||
|
|
||||||
struct timespec req,rem;
|
struct timespec req,rem;
|
||||||
|
|
||||||
req.tv_sec = 0;
|
req.tv_sec = 0;
|
||||||
req.tv_nsec = 1000000;
|
req.tv_nsec = 1000000;
|
||||||
nanosleep(&req,&rem);
|
nanosleep(&req,&rem);
|
||||||
|
|
||||||
runningmutex.Lock();
|
|
||||||
}
|
}
|
||||||
started = true;
|
started = true;
|
||||||
runningmutex.Unlock();
|
|
||||||
|
|
||||||
continuemutex.Unlock();
|
continuemutex.Unlock();
|
||||||
|
|
||||||
|
@ -120,63 +101,37 @@ int JThread::Start()
|
||||||
int JThread::Kill()
|
int JThread::Kill()
|
||||||
{
|
{
|
||||||
void* status;
|
void* status;
|
||||||
runningmutex.Lock();
|
|
||||||
if (!running)
|
if (!running)
|
||||||
{
|
{
|
||||||
if (started) {
|
if (started) {
|
||||||
runningmutex.Unlock();
|
|
||||||
int pthread_join_retval = pthread_join(threadid,&status);
|
int pthread_join_retval = pthread_join(threadid,&status);
|
||||||
assert(pthread_join_retval == 0);
|
assert(pthread_join_retval == 0);
|
||||||
UNUSED(pthread_join_retval);
|
UNUSED(pthread_join_retval);
|
||||||
runningmutex.Lock();
|
|
||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
runningmutex.Unlock();
|
|
||||||
return ERR_JTHREAD_NOTRUNNING;
|
return ERR_JTHREAD_NOTRUNNING;
|
||||||
}
|
}
|
||||||
pthread_cancel(threadid);
|
pthread_cancel(threadid);
|
||||||
if (started) {
|
if (started) {
|
||||||
runningmutex.Unlock();
|
|
||||||
int pthread_join_retval = pthread_join(threadid,&status);
|
int pthread_join_retval = pthread_join(threadid,&status);
|
||||||
assert(pthread_join_retval == 0);
|
assert(pthread_join_retval == 0);
|
||||||
UNUSED(pthread_join_retval);
|
UNUSED(pthread_join_retval);
|
||||||
runningmutex.Lock();
|
|
||||||
started = false;
|
started = false;
|
||||||
}
|
}
|
||||||
running = false;
|
running = false;
|
||||||
runningmutex.Unlock();
|
|
||||||
return 0;
|
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 *JThread::GetReturnValue()
|
||||||
{
|
{
|
||||||
void *val;
|
void *val;
|
||||||
|
|
||||||
runningmutex.Lock();
|
if (running) {
|
||||||
if (running)
|
|
||||||
val = NULL;
|
val = NULL;
|
||||||
else
|
} else {
|
||||||
val = retval;
|
val = retval;
|
||||||
runningmutex.Unlock();
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,19 +148,14 @@ void *JThread::TheThread(void *param)
|
||||||
jthread = (JThread *)param;
|
jthread = (JThread *)param;
|
||||||
|
|
||||||
jthread->continuemutex2.Lock();
|
jthread->continuemutex2.Lock();
|
||||||
jthread->runningmutex.Lock();
|
|
||||||
jthread->running = true;
|
jthread->running = true;
|
||||||
jthread->runningmutex.Unlock();
|
|
||||||
|
|
||||||
jthread->continuemutex.Lock();
|
jthread->continuemutex.Lock();
|
||||||
jthread->continuemutex.Unlock();
|
jthread->continuemutex.Unlock();
|
||||||
|
|
||||||
ret = jthread->Thread();
|
ret = jthread->Thread();
|
||||||
|
|
||||||
jthread->runningmutex.Lock();
|
|
||||||
jthread->running = false;
|
jthread->running = false;
|
||||||
jthread->retval = ret;
|
|
||||||
jthread->runningmutex.Unlock();
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,35 +44,20 @@ JThread::~JThread()
|
||||||
Kill();
|
Kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JThread::Stop() {
|
|
||||||
runningmutex.Lock();
|
|
||||||
requeststop = true;
|
|
||||||
runningmutex.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JThread::Wait() {
|
void JThread::Wait() {
|
||||||
runningmutex.Lock();
|
|
||||||
if (running)
|
if (running)
|
||||||
{
|
{
|
||||||
runningmutex.Unlock();
|
|
||||||
WaitForSingleObject(threadhandle, INFINITE);
|
WaitForSingleObject(threadhandle, INFINITE);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
runningmutex.Unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int JThread::Start()
|
int JThread::Start()
|
||||||
{
|
{
|
||||||
runningmutex.Lock();
|
|
||||||
if (running)
|
if (running)
|
||||||
{
|
{
|
||||||
runningmutex.Unlock();
|
|
||||||
return ERR_JTHREAD_ALREADYRUNNING;
|
return ERR_JTHREAD_ALREADYRUNNING;
|
||||||
}
|
}
|
||||||
requeststop = false;
|
requeststop = false;
|
||||||
runningmutex.Unlock();
|
|
||||||
|
|
||||||
continuemutex.Lock();
|
continuemutex.Lock();
|
||||||
#ifndef _WIN32_WCE
|
#ifndef _WIN32_WCE
|
||||||
|
@ -87,15 +72,10 @@ int JThread::Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until 'running' is set */
|
/* Wait until 'running' is set */
|
||||||
|
|
||||||
runningmutex.Lock();
|
|
||||||
while (!running)
|
while (!running)
|
||||||
{
|
{
|
||||||
runningmutex.Unlock();
|
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
runningmutex.Lock();
|
|
||||||
}
|
}
|
||||||
runningmutex.Unlock();
|
|
||||||
|
|
||||||
continuemutex.Unlock();
|
continuemutex.Unlock();
|
||||||
|
|
||||||
|
@ -107,48 +87,24 @@ int JThread::Start()
|
||||||
|
|
||||||
int JThread::Kill()
|
int JThread::Kill()
|
||||||
{
|
{
|
||||||
runningmutex.Lock();
|
|
||||||
if (!running)
|
if (!running)
|
||||||
{
|
{
|
||||||
runningmutex.Unlock();
|
|
||||||
return ERR_JTHREAD_NOTRUNNING;
|
return ERR_JTHREAD_NOTRUNNING;
|
||||||
}
|
}
|
||||||
TerminateThread(threadhandle,0);
|
TerminateThread(threadhandle,0);
|
||||||
CloseHandle(threadhandle);
|
CloseHandle(threadhandle);
|
||||||
running = false;
|
running = false;
|
||||||
runningmutex.Unlock();
|
|
||||||
return 0;
|
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 *JThread::GetReturnValue()
|
||||||
{
|
{
|
||||||
void *val;
|
void *val;
|
||||||
|
|
||||||
runningmutex.Lock();
|
if (running) {
|
||||||
if (running)
|
|
||||||
val = NULL;
|
val = NULL;
|
||||||
else
|
} else {
|
||||||
val = retval;
|
val = retval;
|
||||||
runningmutex.Unlock();
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,20 +125,16 @@ DWORD WINAPI JThread::TheThread(void *param)
|
||||||
jthread = (JThread *)param;
|
jthread = (JThread *)param;
|
||||||
|
|
||||||
jthread->continuemutex2.Lock();
|
jthread->continuemutex2.Lock();
|
||||||
jthread->runningmutex.Lock();
|
|
||||||
jthread->running = true;
|
jthread->running = true;
|
||||||
jthread->runningmutex.Unlock();
|
|
||||||
|
|
||||||
jthread->continuemutex.Lock();
|
jthread->continuemutex.Lock();
|
||||||
jthread->continuemutex.Unlock();
|
jthread->continuemutex.Unlock();
|
||||||
|
|
||||||
ret = jthread->Thread();
|
ret = jthread->Thread();
|
||||||
|
|
||||||
jthread->runningmutex.Lock();
|
|
||||||
jthread->running = false;
|
jthread->running = false;
|
||||||
jthread->retval = ret;
|
jthread->retval = ret;
|
||||||
CloseHandle(jthread->threadhandle);
|
CloseHandle(jthread->threadhandle);
|
||||||
jthread->runningmutex.Unlock();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue