From 0bd834874c00c5fc5ed251c9fdbff68608d44eb5 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Tue, 8 Mar 2005 04:59:25 +0000 Subject: pass timeout argument to stop method fixes for detached mode fixes for detached operation and single-threaded version use lock count instead of message queuing to avoid py->py messaging deadlock use new flext fifo svn path=/trunk/; revision=2602 --- externals/grill/py/source/clmeth.cpp | 7 +++-- externals/grill/py/source/main.cpp | 48 ++++++++++++++++++++++------------- externals/grill/py/source/main.h | 23 +++++++++++------ externals/grill/py/source/modmeth.cpp | 6 +++-- 4 files changed, 55 insertions(+), 29 deletions(-) (limited to 'externals') diff --git a/externals/grill/py/source/clmeth.cpp b/externals/grill/py/source/clmeth.cpp index 489b7dc5..6062eda9 100644 --- a/externals/grill/py/source/clmeth.cpp +++ b/externals/grill/py/source/clmeth.cpp @@ -113,6 +113,7 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) ERRINTERNAL(); } +#ifdef FLEXT_THREADS if(PyString_Check(name)) { char* sname = PyString_AS_STRING(name); if(sname) { @@ -124,6 +125,7 @@ PyObject* pyext::pyext_getattr(PyObject *,PyObject *args) // post("pyext::getattr %s",sname); } } +#endif if(!ret) { #if PY_VERSION_HEX >= 0x02020000 @@ -231,9 +233,10 @@ PyObject *pyext::pyext_stop(PyObject *,PyObject *args) } else { pyext *ext = GetThis(self); - int cnt = 0; + int cnt; t_atom at; - if(val >= 0) flext::SetInt(at,val); + if(val >= 0) cnt = 1,flext::SetInt(at,val); + else cnt = 0; ext->m_stop(cnt,&at); } diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp index feabfde1..01dc0afa 100644 --- a/externals/grill/py/source/main.cpp +++ b/externals/grill/py/source/main.cpp @@ -157,18 +157,19 @@ void py::Setup(t_classid c) #endif } -py::py(): - module(NULL), - detach(0),shouldexit(false),thrcount(0), - stoptick(0) +py::py() + : module(NULL),detach(0) +#ifdef FLEXT_THREADS + , shouldexit(false),thrcount(0),stoptick(0) +#endif { PyThreadState *state = PyLock(); Py_INCREF(module_obj); PyUnlock(state); +#ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); -#ifdef FLEXT_THREADS // launch thread worker FLEXT_CALLMETHOD(threadworker); #endif @@ -176,27 +177,29 @@ py::py(): py::~py() { - shouldexit = true; + PyThreadState *state = PyLock(); + Py_XDECREF(module_obj); + PyUnlock(state); +} +void py::Exit() +{ #ifdef FLEXT_THREADS + shouldexit = true; qucond.Signal(); - if(thrcount) { // Wait for a certain time - for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) Sleep((float)(PY_STOP_TICK/1000.)); + for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) Sleep(PY_STOP_TICK/1000.f); // Wait forever post("%s - Waiting for thread termination!",thisName()); - while(thrcount) Sleep(0.01f); + while(thrcount) Sleep(PY_STOP_TICK/1000.f); post("%s - Okay, all threads have terminated",thisName()); } #endif - PyThreadState *state = PyLock(); - Py_XDECREF(module_obj); - PyUnlock(state); + flext_base::Exit(); } - void py::GetDir(PyObject *obj,AtomList &lst) { if(obj) { @@ -475,7 +478,6 @@ bool py::gencall(PyObject *pmeth,PyObject *pargs) // put call into queue ret = qucall(pmeth,pargs); break; -#endif case 2: // each call a new thread if(!shouldexit) { @@ -483,8 +485,9 @@ bool py::gencall(PyObject *pmeth,PyObject *pargs) if(!ret) post("%s - Failed to launch thread!",thisName()); } break; +#endif default: - FLEXT_ASSERT(false); + post("%s - Unknown detach mode",thisName()); } return ret; } @@ -493,7 +496,9 @@ void py::work_wrapper(void *data) { FLEXT_ASSERT(data); +#ifdef FLEXT_THREADS ++thrcount; +#endif PyThreadState *state = PyLock(); @@ -504,7 +509,9 @@ void py::work_wrapper(void *data) PyUnlock(state); +#ifdef FLEXT_THREADS --thrcount; +#endif } #ifdef FLEXT_THREADS @@ -522,16 +529,22 @@ void py::threadworker() FifoEl *el; PyThreadState *state; - while(!shouldexit) { + ++thrcount; + for(;;) { while(el = qufifo.Get()) { + ++thrcount; state = PyLock(); callpy(el->fun,el->args); Py_XDECREF(el->fun); Py_XDECREF(el->args); PyUnlock(state); qufifo.Free(el); + --thrcount; } - qucond.Wait(); + if(shouldexit) + break; + else + qucond.Wait(); } state = PyLock(); @@ -542,6 +555,7 @@ void py::threadworker() qufifo.Free(el); } PyUnlock(state); + --thrcount; } #endif diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h index cd1c3736..2d495461 100644 --- a/externals/grill/py/source/main.h +++ b/externals/grill/py/source/main.h @@ -25,8 +25,8 @@ WARRANTIES, see the file, "license.txt," in this distribution. #define PYEXT_MODULE "pyext" // name for module #define PYEXT_CLASS "_class" // name for base class -#define PY_STOP_WAIT 1000 // ms -#define PY_STOP_TICK 10 // ms +#define PY_STOP_WAIT 100 // ms +#define PY_STOP_TICK 1 // ms @@ -50,6 +50,8 @@ public: ~py(); static void lib_setup(); + virtual void Exit(); + static PyObject *MakePyArgs(const t_symbol *s,int argc,const t_atom *argv,int inlet = -1,bool withself = false); static AtomList *GetPyArgs(PyObject *pValue,PyObject **self = NULL); @@ -109,14 +111,18 @@ protected: virtual void m_stop(int argc,const t_atom *argv); - bool shouldexit,respond; + bool respond; +#ifdef FLEXT_THREADS + bool shouldexit; int thrcount; int stoptick; Timer stoptmr; - int detach; void tick(void *); - +#endif + + int detach; + bool gencall(PyObject *fun,PyObject *args); virtual bool callpy(PyObject *fun,PyObject *args) = 0; @@ -153,18 +159,19 @@ public: // this is respecially needed when one py/pyext object calls another one // we don't want the message to be queued, but otoh we have to avoid deadlock + // (recursive calls can only happen in the system thread) static int lockcount; inline PyThreadState *PyLock() { - if(!lockcount++) PyEval_AcquireLock(); + if(!IsSystemThread() || !lockcount++) PyEval_AcquireLock(); return PyThreadState_Swap(FindThreadState()); } inline void PyUnlock(PyThreadState *st) { PyThreadState_Swap(st); - if(!--lockcount) PyEval_ReleaseLock(); + if(!IsSystemThread() || !--lockcount) PyEval_ReleaseLock(); } #else inline void Lock() {} @@ -189,9 +196,9 @@ protected: FLEXT_CALLBACK(m_dir) FLEXT_CALLGET_V(mg_dir) FLEXT_CALLBACK(m_doc) - FLEXT_CALLBACK_T(tick) #ifdef FLEXT_THREADS + FLEXT_CALLBACK_T(tick) FLEXT_THREAD(threadworker) #endif }; diff --git a/externals/grill/py/source/modmeth.cpp b/externals/grill/py/source/modmeth.cpp index cf4dca88..70eb536a 100644 --- a/externals/grill/py/source/modmeth.cpp +++ b/externals/grill/py/source/modmeth.cpp @@ -45,7 +45,7 @@ const char *py::py_doc = ; - +#ifdef FLEXT_THREADS void py::tick(void *) { Lock(); @@ -68,9 +68,11 @@ void py::tick(void *) Unlock(); } +#endif void py::m_stop(int argc,const t_atom *argv) { +#ifdef FLEXT_THREADS if(thrcount) { Lock(); @@ -89,7 +91,7 @@ void py::m_stop(int argc,const t_atom *argv) Unlock(); } - +#endif } PyObject *py::py_samplerate(PyObject *self,PyObject *args) -- cgit v1.2.1