*/
#ifndef JTHREAD_H
-
#define JTHREAD_H
+#if __cplusplus >= 201103L
+#include <atomic>
+#endif
+
#include "jthread/jmutex.h"
#define ERR_JTHREAD_CANTINITMUTEX -1
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();
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;
};
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);
/* 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();
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;
}
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;
}
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
}
/* Wait until 'running' is set */
-
- runningmutex.Lock();
while (!running)
{
- runningmutex.Unlock();
Sleep(1);
- runningmutex.Lock();
}
- runningmutex.Unlock();
continuemutex.Unlock();
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;
}
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;
}