From 0ed7a8b68dd73e2b0473b8127aeca99f3bac9061 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 1 Apr 2009 21:13:09 +0000 Subject: cleaned up grill externals - replaced with svn:externals to svn.grrrr.org/ext/trunk/ svn path=/trunk/; revision=10951 --- externals/grill/flext/source/flthr.cpp | 646 --------------------------------- 1 file changed, 646 deletions(-) delete mode 100644 externals/grill/flext/source/flthr.cpp (limited to 'externals/grill/flext/source/flthr.cpp') diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp deleted file mode 100644 index 36559997..00000000 --- a/externals/grill/flext/source/flthr.cpp +++ /dev/null @@ -1,646 +0,0 @@ -/* - -flext - C++ layer for Max/MSP and pd (pure data) externals - -Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org) -For information on usage and redistribution, and for a DISCLAIMER OF ALL -WARRANTIES, see the file, "license.txt," in this distribution. - -*/ - -/*! \file flthr.cpp - \brief Implementation of the flext thread functionality. -*/ - -#include "flext.h" - -#ifdef FLEXT_THREADS - -// maximum wait time for threads to finish (in ms) -#define MAXIMUMWAIT 100 - - -#include "flinternal.h" -#include "flcontainers.h" - -#include - -#if FLEXT_OSAPI == FLEXT_OSAPI_MAC_MACH || FLEXT_OSAPI == FLEXT_OSAPI_UNIX_POSIX || FLEXT_OSAPI == FLEXT_OSAPI_WIN_POSIX -#include -#include -#elif FLEXT_OS == FLEXT_OS_WIN -#include -#endif - -#if FLEXT_THREADS == FLEXT_THR_WIN32 && WINVER < 0x0500 -#error WIN32 threads need Windows SDK version >= 0x500 -#endif - -#include - -//! Thread id of system thread - will be initialized in flext::Setup -flext::thrid_t flext::thrid; - -//! Thread id of helper thread - will be initialized in flext::Setup -flext::thrid_t flext::thrhelpid; - - -//! \brief This represents an entry to the list of active method threads -class thr_entry - : public flext - , public Fifo::Cell -{ -public: - void Set(void (*m)(thr_params *),thr_params *p,thrid_t id = GetThreadId()) - { - th = p?p->cl:NULL; - meth = m,params = p,thrid = id; - shouldexit = false; -#if FLEXT_THREADS == FLEXT_THR_MP - weight = 100; // MP default weight -#endif - } - - //! \brief Check if this class represents the current thread - bool Is(thrid_t id = GetThreadId()) const { return IsThread(thrid,id); } - - FLEXT_CLASSDEF(flext_base) *This() const { return th; } - thrid_t Id() const { return thrid; } - - FLEXT_CLASSDEF(flext_base) *th; - void (*meth)(thr_params *); - thr_params *params; - thrid_t thrid; - bool shouldexit; -#if FLEXT_THREADS == FLEXT_THR_MP - int weight; -#endif -}; - -template -class ThrFinder: - public T -{ -public: - void Push(thr_entry *e) { T::Push(e); } - thr_entry *Pop() { return T::Pop(); } - - thr_entry *Find(flext::thrid_t id,bool pop = false) - { - TypedLifo qutmp; - thr_entry *fnd; - while((fnd = Pop()) && !fnd->Is(id)) qutmp.Push(fnd); - // put back entries - for(thr_entry *ti; (ti = qutmp.Pop()) != NULL; ) Push(ti); - if(fnd && !pop) Push(fnd); - return fnd; - } -}; - -static ThrFinder< PooledLifo > thrpending; -static ThrFinder< TypedLifo > thractive,thrstopped; - -//! Helper thread conditional -static flext::ThrCond *thrhelpcond = NULL; - - -static void LaunchHelper(thr_entry *e) -{ - e->thrid = flext::GetThreadId(); - e->meth(e->params); -} - -bool initialized = false; - -//! Start helper thread -bool flext::StartHelper() -{ - bool ok = false; - initialized = false; -#if FLEXT_THREADS == FLEXT_THR_POSIX - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); - - pthread_t tmp; - ok = pthread_create (&tmp,&attr,(void *(*)(void *))ThrHelper,NULL) == 0; -#elif FLEXT_THREADS == FLEXT_THR_MP - if(!MPLibraryIsLoaded()) - error("Thread library is not loaded"); - else { - MPTaskID tmp; - OSStatus ret = MPCreateTask((TaskProc)ThrHelper,NULL,0,0,0,0,0,&tmp); - ok = ret == noErr; - } -#elif FLEXT_THREADS == FLEXT_THR_WIN32 - ok = _beginthread(ThrHelper,0,NULL) >= 0; -#else -#error -#endif - if(!ok) - error("flext - Could not launch helper thread!"); - else { - // now we have to wait for thread helper to initialize - while(!initialized) Sleep(0.001); - - // we are ready for threading now! - } - -#if FLEXT_THREADS == FLEXT_THR_POSIX - pthread_attr_destroy(&attr); -#endif - return ok; -} - -//! Static helper thread function -void flext::ThrHelper(void *) -{ - thrhelpid = GetThreadId(); - -#if FLEXT_THREADS == FLEXT_THR_POSIX - // set prototype thread attributes - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); -#endif - - // set thread priority one point below normal - // so thread construction won't disturb real-time audio - RelPriority(-1); - - thrhelpcond = new ThrCond; - - initialized = true; - - // helper loop - for(;;) { - thrhelpcond->Wait(); - - // start all inactive threads - thr_entry *ti; - while((ti = thrpending.Pop()) != NULL) { - bool ok; - - #if FLEXT_THREADS == FLEXT_THR_POSIX - thrid_t dummy; - ok = pthread_create (&dummy,&attr,(void *(*)(void *))LaunchHelper,ti) == 0; - #elif FLEXT_THREADS == FLEXT_THR_MP - thrid_t dummy; - ok = MPCreateTask((TaskProc)LaunchHelper,ti,0,0,0,0,0,&dummy) == noErr; - #elif FLEXT_THREADS == FLEXT_THR_WIN32 - ok = _beginthread((void (*)(void *))LaunchHelper,0,ti) >= 0; - #else - #error - #endif - if(!ok) { - error("flext - Could not launch thread!"); - thrpending.Free(ti); ti = NULL; - } - else - // insert into queue of active threads - thractive.Push(ti); - } - } - - FLEXT_ASSERT(false); -/* - // Never reached! - - delete thrhelpcond; - thrhelpcond = NULL; - -#if FLEXT_THREADS == FLEXT_THR_POSIX - pthread_attr_destroy(&attr); -#endif -*/ -} - - -bool flext::LaunchThread(void (*meth)(thr_params *p),thr_params *p) -{ - FLEXT_ASSERT(thrhelpcond); - - // make an entry into thread list - thr_entry *e = thrpending.New(); - e->Set(meth,p); - thrpending.Push(e); - // signal thread helper - thrhelpcond->Signal(); - - return true; -} - -static bool waitforstopped(TypedFifo &qufnd,float wait = 0) -{ - TypedLifo qutmp; - - double until; - if(wait) until = flext::GetOSTime()+wait; - - for(;;) { - thr_entry *fnd = qufnd.Get(); - if(!fnd) break; // no more entries -> done! - - thr_entry *ti; - // search for entry - while((ti = thrstopped.Pop()) != NULL && ti != fnd) qutmp.Push(ti); - // put back entries - while((ti = qutmp.Pop()) != NULL) thrstopped.Push(ti); - - if(ti) { - // still in thrstopped queue - qufnd.Put(fnd); - // yield to other threads - flext::ThrYield(); - - if(wait && flext::GetOSTime() > until) - // not successful -> remaining thread are still in qufnd queue - return false; - } - } - return true; -} - -bool flext::StopThread(void (*meth)(thr_params *p),thr_params *p,bool wait) -{ - FLEXT_ASSERT(thrhelpcond); - - TypedLifo qutmp; - thr_entry *ti; - - // first search pending queue - // -------------------------- - - { - bool found = false; - while((ti = thrpending.Pop()) != NULL) - if(ti->meth == meth && ti->params == p) { - // found -> thread hasn't started -> just delete - thrpending.Free(ti); - found = true; - } - else - qutmp.Push(ti); - - // put back into pending queue (order doesn't matter) - while((ti = qutmp.Pop()) != NULL) thrpending.Push(ti); - - if(found) return true; - } - - // now search active queue - // ----------------------- - - TypedFifo qufnd; - - while((ti = thractive.Pop()) != NULL) - if(ti->meth == meth && ti->params == p) { - thrstopped.Push(ti); - thrhelpcond->Signal(); - qufnd.Put(ti); - } - else - qutmp.Push(ti); - - // put back into pending queue (order doesn't matter) - while((ti = qutmp.Pop()) != NULL) thractive.Push(ti); - - // wakeup helper thread - thrhelpcond->Signal(); - - // now wait for entries in qufnd to have vanished from thrstopped - if(wait) - return waitforstopped(qufnd); - else - return qufnd.Size() == 0; -} - -bool flext::ShouldExit() -{ - return thrstopped.Find(GetThreadId()) != NULL; -} - -bool flext::PushThread() -{ - // set priority of newly created thread one point below the system thread's - RelPriority(-1); - return true; -} - -void flext::PopThread() -{ - thrid_t id = GetThreadId(); - thr_entry *fnd = thrstopped.Find(id,true); - if(!fnd) fnd = thractive.Find(id,true); - - if(fnd) - thrpending.Free(fnd); -#ifdef FLEXT_DEBUG - else - post("flext - INTERNAL ERROR: Thread not found!"); -#endif -} - -//! Terminate all object threads -bool flext_base::StopThreads() -{ - FLEXT_ASSERT(thrhelpcond); - - TypedLifo qutmp; - thr_entry *ti; - - // first search pending queue - // -------------------------- - - while((ti = thrpending.Pop()) != NULL) - if(ti->This() == this) - // found -> thread hasn't started -> just delete - thrpending.Free(ti); - else - qutmp.Push(ti); - - // put back into pending queue (order doesn't matter) - while((ti = qutmp.Pop()) != NULL) thrpending.Push(ti); - - // now search active queue - // ----------------------- - - TypedFifo qufnd; - - while((ti = thractive.Pop()) != NULL) - if(ti->This() == this) { - thrstopped.Push(ti); - thrhelpcond->Signal(); - qufnd.Put(ti); - } - else - qutmp.Push(ti); - - // put back into pending queue (order doesn't matter) - while((ti = qutmp.Pop()) != NULL) thractive.Push(ti); - - // wakeup helper thread - thrhelpcond->Signal(); - - // now wait for entries in qufnd to have vanished from thrstopped - if(!waitforstopped(qufnd,MAXIMUMWAIT*0.001f)) { -#ifdef FLEXT_DEBUG - post("flext - doing hard thread termination"); -#endif - - // timeout -> hard termination - while((ti = qufnd.Get()) != NULL) { -#if FLEXT_THREADS == FLEXT_THR_POSIX - if(pthread_cancel(ti->thrid)) - post("%s - Thread could not be terminated!",thisName()); -#elif FLEXT_THREADS == FLEXT_THR_MP - MPTerminateTask(ti->thrid,0); - // here, we should use a task queue to check whether the task has really terminated!! -#elif FLEXT_THREADS == FLEXT_THR_WIN32 - // can't use the c library function _endthread.. memory leaks will occur - HANDLE hnd = OpenThread(THREAD_ALL_ACCESS,TRUE,ti->thrid); - TerminateThread(hnd,0); -#else -#error Not implemented -#endif - thrpending.Free(ti); - } - return false; - } - else - return true; -} - -bool flext::RelPriority(int dp,thrid_t ref,thrid_t id) -{ -#if FLEXT_THREADS == FLEXT_THR_POSIX - sched_param parm; - int policy; - if(pthread_getschedparam(ref,&policy,&parm) < 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to get thread priority"); -#endif - return false; - } - else { - parm.sched_priority += dp; - - // MSVC++ 6 produces wrong code with the following lines!!! -// int schmin = sched_get_priority_min(policy); -// int schmax = sched_get_priority_max(policy); - - if(parm.sched_priority < sched_get_priority_min(policy)) { -#ifdef FLEXT_DEBUG - post("flext - minimum thread priority reached"); -#endif - parm.sched_priority = sched_get_priority_min(policy); - } - else if(parm.sched_priority > sched_get_priority_max(policy)) { -#ifdef FLEXT_DEBUG - post("flext - maximum thread priority reached"); -#endif - parm.sched_priority = sched_get_priority_max(policy); - } - - if(pthread_setschedparam(id,policy,&parm) < 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to change thread priority"); -#endif - return false; - } - } - return true; - -#elif FLEXT_THREADS == FLEXT_THR_WIN32 - HANDLE href = OpenThread(THREAD_ALL_ACCESS,TRUE,ref); - HANDLE hid = OpenThread(THREAD_ALL_ACCESS,TRUE,id); - int pr = GetThreadPriority(href); - - if(pr == THREAD_PRIORITY_ERROR_RETURN) { -#ifdef FLEXT_DEBUG - post("flext - failed to get thread priority"); -#endif - return false; - } - - pr += dp; - if(pr < THREAD_PRIORITY_IDLE) { -#ifdef FLEXT_DEBUG - post("flext - minimum thread priority reached"); -#endif - pr = THREAD_PRIORITY_IDLE; - } - else if(pr > THREAD_PRIORITY_TIME_CRITICAL) { -#ifdef FLEXT_DEBUG - post("flext - maximum thread priority reached"); -#endif - pr = THREAD_PRIORITY_TIME_CRITICAL; - } - - if(SetThreadPriority(hid,pr) == 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to change thread priority"); -#endif - return false; - } - return true; - -#elif FLEXT_THREADS == FLEXT_THR_MP - thr_entry *ti = thrpending.Find(id); - if(!ti) ti = thractive.Find(id); - if(ti) { - // thread found in list - int w = GetPriority(id); - if(dp < 0) w /= 1<<(-dp); - else w *= 1< 10000) { - #ifdef FLEXT_DEBUG - post("flext - maximum thread priority reached"); - #endif - w = 10000; - } - ti->weight = w; - return MPSetTaskWeight(id,w) == noErr; - } - else return false; -#else -#error -#endif -} - - -int flext::GetPriority(thrid_t id) -{ -#if FLEXT_THREADS == FLEXT_THR_POSIX - sched_param parm; - int policy; - if(pthread_getschedparam(id,&policy,&parm) < 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to get parms"); -#endif - return -1; - } - return parm.sched_priority; - -#elif FLEXT_THREADS == FLEXT_THR_WIN32 - HANDLE hid = OpenThread(THREAD_ALL_ACCESS,TRUE,id); - int pr = GetThreadPriority(hid); - - if(pr == THREAD_PRIORITY_ERROR_RETURN) { -#ifdef FLEXT_DEBUG - post("flext - failed to get thread priority"); -#endif - return -1; - } - return pr; - -#elif FLEXT_THREADS == FLEXT_THR_MP - thr_entry *ti = thrpending.Find(id); - if(!ti) ti = thractive.Find(id); - return ti?ti->weight:-1; -#else -#error -#endif -} - - -bool flext::SetPriority(int p,thrid_t id) -{ -#if FLEXT_THREADS == FLEXT_THR_POSIX - sched_param parm; - int policy; - if(pthread_getschedparam(id,&policy,&parm) < 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to get parms"); -#endif - return false; - } - else { - parm.sched_priority = p; - if(pthread_setschedparam(id,policy,&parm) < 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to change priority"); -#endif - return false; - } - } - return true; - -#elif FLEXT_THREADS == FLEXT_THR_WIN32 - HANDLE hid = OpenThread(THREAD_ALL_ACCESS,TRUE,id); - if(SetThreadPriority(hid,p) == 0) { -#ifdef FLEXT_DEBUG - post("flext - failed to change thread priority"); -#endif - return false; - } - return true; - -#elif FLEXT_THREADS == FLEXT_THR_MP - thr_entry *ti = thrpending.Find(id); - if(!ti) ti = thractive.Find(id); - return ti && MPSetTaskWeight(id,ti->weight = p) == noErr; -#else -#error -#endif -} - - -flext_base::thr_params::thr_params(int n): cl(NULL),var(new _data[n]) {} -flext_base::thr_params::~thr_params() { if(var) delete[] var; } - -void flext_base::thr_params::set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any = new AtomAnything(s,argc,argv); } -void flext_base::thr_params::set_list(int argc,const t_atom *argv) { var[0]._list = new AtomList(argc,argv); } - - -#if FLEXT_THREADS == FLEXT_THR_POSIX -bool flext::ThrCond::Wait() { - Lock(); - bool ret = pthread_cond_wait(&cond,&mutex) == 0; - Unlock(); - return ret; -} - -bool flext::ThrCond::TimedWait(double ftm) -{ - timespec tm; -#if FLEXT_OS == FLEXT_OS_WIN && FLEXT_OSAPI == FLEXT_OSAPI_WIN_NATIVE -#ifdef _MSC_VER - _timeb tmb; - _ftime(&tmb); -#else - timeb tmb; - ftime(&tmb); -#endif - tm.tv_nsec = tmb.millitm*1000000; - tm.tv_sec = (long)tmb.time; -#else // POSIX -#if 0 // find out when the following is defined - clock_gettime(CLOCK_REALTIME,tm); -#else - struct timeval tp; - gettimeofday(&tp, NULL); - tm.tv_nsec = tp.tv_usec*1000; - tm.tv_sec = tp.tv_sec; -#endif -#endif - - tm.tv_nsec += (long)((ftm-(long)ftm)*1.e9); - long nns = tm.tv_nsec%1000000000; - tm.tv_sec += (long)ftm+(tm.tv_nsec-nns)/1000000000; - tm.tv_nsec = nns; - - Lock(); - bool ret = pthread_cond_timedwait(&cond,&mutex,&tm) == 0; - Unlock(); - return ret; -} -#endif - -#endif // FLEXT_THREADS -- cgit v1.2.1