cwThread.cpp : Made stateId and doFlags atomic.

This commit is contained in:
kevin.larke 2020-04-19 13:01:47 -04:00
parent b577d476d3
commit 48ebcc89c7

View File

@ -21,10 +21,12 @@ namespace cw
typedef struct thread_str
{
pthread_t pThreadH;
stateId_t stateId;
std::atomic<stateId_t> stateId;
std::atomic<unsigned> doFlags;
cbFunc_t func;
void* funcArg;
unsigned doFlags;
unsigned stateMicros;
unsigned pauseMicros;
unsigned sleepMicros = 15000;
@ -34,22 +36,29 @@ namespace cw
inline thread_t* _handleToPtr(handle_t h) { return handleToPtr<handle_t,thread_t>(h); }
// Called from client thread to wait for the internal thread to transition to a specified state.
rc_t _waitForState( thread_t* p, unsigned stateId )
{
unsigned waitTimeMicroSecs = 0;
stateId_t curStateId;
while( p->stateId != stateId && waitTimeMicroSecs < p->stateMicros )
do
{
sleepUs( p->sleepMicros );
waitTimeMicroSecs += p->sleepMicros;
}
curStateId = p->stateId.load(std::memory_order_acquire);
return p->stateId==stateId ? kOkRC : kTimeOutRC;
if(curStateId == stateId )
break;
sleepUs( p->sleepMicros );
}while( waitTimeMicroSecs < p->stateMicros );
return curStateId==stateId ? kOkRC : kTimeOutRC;
}
void _threadCleanUpCallback(void* p)
{
((thread_t*)p)->stateId = kExitedThId;
((thread_t*)p)->stateId.store(kExitedThId,std::memory_order_release);
}
@ -61,37 +70,44 @@ namespace cw
// thread terminates unexpectedly or pthread_cleanup_pop() is called.
pthread_cleanup_push(_threadCleanUpCallback,p);
while( cwIsFlag(p->doFlags,kDoExitThFl) == false )
unsigned curDoFlags = 0;
do
{
// get the current thread state (running or paused)
stateId_t curStateId = p->stateId.load(std::memory_order_relaxed);
// if we are in the pause state
if( p->stateId == kPausedThId )
if( curStateId == kPausedThId )
{
sleepUs( p->pauseMicros );
curDoFlags = p->doFlags.load(std::memory_order_acquire);
// check if we have been requested to leave the pause state
if( cwIsFlag(p->doFlags,kDoRunThFl) )
if( cwIsFlag(curDoFlags,kDoRunThFl) )
{
p->doFlags = cwClrFlag(p->doFlags,kDoRunThFl);
p->stateId = kRunningThId;
p->stateId.store(kRunningThId,std::memory_order_release);
}
}
else
else // ... we are in running state
{
// call the user-defined function
if( p->func(p->funcArg)==false )
break;
curDoFlags = p->doFlags.load(std::memory_order_acquire);
// check if we have been requested to enter the pause state
if( cwIsFlag(p->doFlags,kDoPauseThFl) )
if( cwIsFlag(curDoFlags,kDoPauseThFl) )
{
p->doFlags = cwClrFlag(p->doFlags,kDoPauseThFl);
p->stateId = kPausedThId;
}
p->stateId.store(kPausedThId,std::memory_order_release);
}
}
}while( cwIsFlag(curDoFlags,kDoExitThFl) == false );
pthread_cleanup_pop(1);
pthread_exit(NULL);
@ -157,7 +173,7 @@ cw::rc_t cw::thread::destroy( handle_t& hRef )
thread_t* p = _handleToPtr(hRef);
// tell the thread to exit
p->doFlags = cwSetFlag(p->doFlags,kDoExitThFl);
p->doFlags.store(kDoExitThFl,std::memory_order_release);
// wait for the thread to exit and then deallocate the thread object
if((rc = _waitForState(p,kExitedThId)) != kOkRC )
@ -184,7 +200,8 @@ cw::rc_t cw::thread::pause( handle_t h, unsigned cmdFlags )
bool pauseFl = cwIsFlag(cmdFlags,kPauseFl);
bool waitFl = cwIsFlag(cmdFlags,kWaitFl);
thread_t* p = _handleToPtr(h);
bool isPausedFl = p->stateId == kPausedThId;
stateId_t curStateId = p->stateId.load(std::memory_order_acquire);
bool isPausedFl = curStateId == kPausedThId;
unsigned waitId;
if( isPausedFl == pauseFl )
@ -192,12 +209,12 @@ cw::rc_t cw::thread::pause( handle_t h, unsigned cmdFlags )
if( pauseFl )
{
p->doFlags = cwSetFlag(p->doFlags,kDoPauseThFl);
p->doFlags.store(kDoPauseThFl,std::memory_order_release);
waitId = kPausedThId;
}
else
{
p->doFlags = cwSetFlag(p->doFlags,kDoRunThFl);
p->doFlags.store(kDoRunThFl,std::memory_order_release);
waitId = kRunningThId;
}
@ -217,7 +234,7 @@ cw::rc_t cw::thread::unpause( handle_t h )
cw::thread::stateId_t cw::thread::state( handle_t h )
{
thread_t* p = _handleToPtr(h);
return p->stateId;
return p->stateId.load(std::memory_order_acquire);
}
cw::thread::thread_id_t cw::thread::id()