diff options
Diffstat (limited to 'externals/grill/flext/source/flthr.cpp')
-rw-r--r-- | externals/grill/flext/source/flthr.cpp | 164 |
1 files changed, 160 insertions, 4 deletions
diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp index f23eb38f..97da5584 100644 --- a/externals/grill/flext/source/flthr.cpp +++ b/externals/grill/flext/source/flthr.cpp @@ -23,16 +23,146 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include <errno.h> +//! Thread id of system thread +pthread_t flext_base::thrid; + +//! Thread id of helper thread +pthread_t flext_base::thrhelpid; + +flext_base::thr_entry *flext_base::thrhead = NULL,*flext_base::thrtail = NULL; +flext::ThrMutex flext_base::tlmutex; + +//! Helper thread should terminate +bool thrhelpexit = false; + +flext::ThrCond *thrhelpcond = NULL; + +//! Start helper thread +bool flext_base::StartHelper() +{ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + + thrhelpexit = false; + int ret = pthread_create (&thrhelpid,&attr,(void *(*)(void *))ThrHelper,NULL); + if(ret) { + error((char *)("flext - Could not launch helper thread!")); + return false; + } + else + return true; +} + +#if 0 +/*! \brief Stop helper thread + \note not called! +*/ +bool flext_base::StopHelper() +{ + thrhelpexit = true; + if(thrhelpcond) thrhelpcond->Signal(); +} +#endif + +//! Static helper thread function +void flext_base::ThrHelper(void *) +{ + // set prototype thread attributes + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + + // set thread priority one point below normal + // so thread construction won't disturb real-time audio + sched_param parm; + int policy; + pthread_getschedparam(thrhelpid,&policy,&parm); + int prio = parm.sched_priority; + int schmin = sched_get_priority_min(policy); + if(prio > schmin) { + parm.sched_priority = prio-1; + pthread_setschedparam(thrhelpid,policy,&parm); + } + + thrhelpcond = new ThrCond; + + // helper loop + for(;;) { + thrhelpcond->Wait(); + if(thrhelpexit) break; + + tlmutex.Lock(); + + // start all inactive threads in queue + thr_entry *prv = NULL,*ti; + for(ti = thrhead; ti; prv = ti,ti = ti->nxt) { + if(!ti->active) { + int ret = pthread_create (&ti->thrid,&attr,(void *(*)(void *))ti->meth,ti->params); + if(ret) { + error((char *)("flext - Could not launch thread!")); + + // delete from queue + if(prv) + prv->nxt = ti->nxt; + else + thrhead = ti->nxt; + if(thrtail == ti) thrtail = prv; + + ti->nxt = NULL; + delete ti; + } + else { + // set active flag + ti->active = true; + } + } + } + + tlmutex.Unlock(); + } + + delete thrhelpcond; + thrhelpcond = NULL; +} + + +bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname) +{ +#ifdef FLEXT_DEBUG + if(!p || !thrhelpcond) { + ERRINTERNAL(); + return false; + } +#endif + + tlmutex.Lock(); + + // make an entry into thread list + thr_entry *nt = new thr_entry(this,meth,p); + if(thrtail) thrtail->nxt = nt; + else thrhead = nt; + thrtail = nt; + + // signal thread helper + thrhelpcond->Signal(); + + tlmutex.Unlock(); + return true; +} + +/* bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname) { - static bool init = false; - static pthread_attr_t attr; #ifdef FLEXT_DEBUG if(!p) { ERRINTERNAL(); return false; } #endif + + static bool init = false; + static pthread_attr_t attr; if(!init) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); @@ -62,8 +192,9 @@ bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *me if(ret) { #ifdef FLEXT_DEBUG error((char *)(ret == EAGAIN?"%s - Unsufficient resources to launch thread!":"%s - Could not launch method!"),methname); -#endif +#else error((char *)("%s - Could not launch method!"),methname); +#endif delete p; return false; @@ -71,6 +202,7 @@ bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *me else return true; } +*/ bool flext_base::PushThread() { @@ -78,12 +210,13 @@ bool flext_base::PushThread() // post("Push thread"); +/* // make an entry into thread list thr_entry *nt = new thr_entry; if(thrtail) thrtail->nxt = nt; else thrhead = nt; thrtail = nt; - +*/ { #if FLEXT_OS == FLEXT_OS_WIN // set detached thread to lower priority class @@ -151,6 +284,29 @@ void flext_base::PopThread() tlmutex.Unlock(); } +void flext_base::TermThreads() +{ + // wait for thread termination + shouldexit = true; + for(int wi = 0; thrhead && wi < 100; ++wi) Sleep(0.01f); + + qmutex.Lock(); // Lock message queue + tlmutex.Lock(); + + // timeout -> hard termination + for(thr_entry *t = thrhead; t; ) + if(t->th == this) { + if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName()); + thr_entry *tn = t->nxt; + t->nxt = NULL; delete t; + t = tn; + } + else t = t->nxt; + + tlmutex.Unlock(); + qmutex.Unlock(); +} + flext_base::thrid_t flext_base::GetThreadId() { return pthread_self(); |