From 8994dac676a881dce818238d4519182a8bf635ea Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Tue, 19 Jul 2005 13:18:33 +0000 Subject: better exception handling and error message much better detach method handling (one thread for all object instances) oops, forgot to code one branch better definition of output values (atoms, lists, anythings) svn path=/trunk/; revision=3360 --- externals/grill/py/readme.txt | 1 + externals/grill/py/source/main.h | 5 ++- externals/grill/py/source/py.cpp | 14 +------ externals/grill/py/source/pyargs.cpp | 5 +++ externals/grill/py/source/pybase.cpp | 75 +++++++++++++++++++++++------------- externals/grill/py/source/pybase.h | 15 +++++--- externals/grill/py/source/pyext.cpp | 9 +---- externals/grill/py/source/pyext.h | 5 --- externals/grill/py/source/pymeth.cpp | 14 +------ 9 files changed, 70 insertions(+), 73 deletions(-) (limited to 'externals/grill/py') diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt index 9213786d..0c4bc0f4 100644 --- a/externals/grill/py/readme.txt +++ b/externals/grill/py/readme.txt @@ -98,6 +98,7 @@ Version history: - FIX: cleanup for outbound messages (e.g. symbol atoms instead of one-element general messages) - FIX: better exception handling (no longer leaves reference to function object) and cleared misleading error message - FIX: better definition of output values for atoms, lists and anythings +- FIX: much better detached method handling (one thread for all object instances!) 0.2.0: - ADD: handling of Python threads diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h index 479c082d..86098b4c 100644 --- a/externals/grill/py/source/main.h +++ b/externals/grill/py/source/main.h @@ -25,11 +25,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. #define PY_STOP_TICK 1 // ms +class pybase; + class FifoEl : public Fifo::Cell { public: - void Set(PyObject *f,PyObject *a) { fun = f,args = a; } + void Set(pybase *t,PyObject *f,PyObject *a) { th = t,fun = f,args = a; } + pybase *th; PyObject *fun,*args; }; diff --git a/externals/grill/py/source/py.cpp b/externals/grill/py/source/py.cpp index 4b7c2bdc..b4b4f225 100644 --- a/externals/grill/py/source/py.cpp +++ b/externals/grill/py/source/py.cpp @@ -47,7 +47,6 @@ protected: bool SetFunction(const t_symbol *func); bool ResetFunction(); - virtual bool thrcall(void *data); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); PyObject **objects; @@ -77,10 +76,6 @@ private: #ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) - FLEXT_THREAD(threadworker) - FLEXT_THREAD_X(work_wrapper) -#else - FLEXT_CALLBACK_X(work_wrapper) #endif }; @@ -104,7 +99,7 @@ void pyobj::Setup(t_classid c) FLEXT_CADDMETHOD_(c,0,"set",m_set); - FLEXT_CADDATTR_VAR1(c,"xlate",xlate); + FLEXT_CADDATTR_VAR1(c,"py",xlate); FLEXT_CADDATTR_VAR1(c,"respond",respond); } @@ -116,8 +111,6 @@ pyobj::pyobj(int argc,const t_atom *argv) { #ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); - // launch thread worker - FLEXT_CALLMETHOD(threadworker); #endif PyThreadState *state = PyLockSys(); @@ -426,8 +419,3 @@ void pyobj::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); } - -bool pyobj::thrcall(void *data) -{ - return FLEXT_CALLMETHOD_X(work_wrapper,data); -} diff --git a/externals/grill/py/source/pyargs.cpp b/externals/grill/py/source/pyargs.cpp index 2cdfdade..d631903b 100644 --- a/externals/grill/py/source/pyargs.cpp +++ b/externals/grill/py/source/pyargs.cpp @@ -192,6 +192,11 @@ const t_symbol *pybase::GetPyArgs(AtomList &lst,PyObject *pValue,int offs) getlist(lst.Atoms(),l,rargc); sym = pyObject_AsSymbol(s); } + else { + // (symbol,atom) list + lst(offs+rargc); + sym = getlist(lst.Atoms(),pValue,rargc); + } Py_DECREF(s); Py_DECREF(l); diff --git a/externals/grill/py/source/pybase.cpp b/externals/grill/py/source/pybase.cpp index 65c4369d..20f16e13 100644 --- a/externals/grill/py/source/pybase.cpp +++ b/externals/grill/py/source/pybase.cpp @@ -56,6 +56,9 @@ void pybase::FreeThreadState() pythrmap.erase(it); } } + +PyFifo pybase::qufifo; +flext::ThrCond pybase::qucond; #endif @@ -167,6 +170,9 @@ void pybase::lib_setup() #ifdef FLEXT_THREADS // release global lock PyEval_ReleaseLock(); + + // launch thread worker + LaunchThread(quworker,NULL); #endif post("------------------------------------------------"); @@ -182,7 +188,8 @@ FLEXT_LIB_SETUP(py,pybase::lib_setup) pybase::pybase() : module(NULL) #ifdef FLEXT_THREADS - , shouldexit(false),thrcount(0),stoptick(0) + , thrcount(0) + , shouldexit(false),stoptick(0) #endif , detach(0) , xlate(true) @@ -202,8 +209,11 @@ pybase::~pybase() void pybase::Exit() { #ifdef FLEXT_THREADS + erasethreads(); + shouldexit = true; qucond.Signal(); + if(thrcount) { // Wait for a certain time for(int i = 0; i < (PY_STOP_WAIT/PY_STOP_TICK) && thrcount; ++i) @@ -580,7 +590,10 @@ bool pybase::gencall(PyObject *pmeth,PyObject *pargs) case 2: // each call a new thread if(!shouldexit) { - ret = thrcall(new work_data(pmeth,pargs)); + thr_params *p = new thr_params; + p->cl = (flext_base *)this; + p->var->_ext = new work_data(pmeth,pargs); + ret = LaunchThread(thrworker,p); if(!ret) post("py/pyext - Failed to launch thread!"); } break; @@ -609,62 +622,54 @@ void pybase::exchandle() #endif } -void pybase::work_wrapper(void *data) -{ - FLEXT_ASSERT(data); - #ifdef FLEXT_THREADS - ++thrcount; -#endif +void pybase::thrworker(thr_params *p) +{ + FLEXT_ASSERT(p); + pybase *th = (pybase *)p->cl; + work_data *w = (work_data *)p->var->_ext; + ++th->thrcount; // \todo this should be atomic PyThreadState *state = PyLock(); // call worker - work_data *w = (work_data *)data; - docall(w->fun,w->args); + th->docall(w->fun,w->args); delete w; PyUnlock(state); - -#ifdef FLEXT_THREADS - --thrcount; -#endif + --th->thrcount; // \todo this should be atomic } -#ifdef FLEXT_THREADS bool pybase::qucall(PyObject *fun,PyObject *args) { FifoEl *el = qufifo.New(); - el->Set(fun,args); + el->Set(this,fun,args); qufifo.Put(el); qucond.Signal(); return true; } -void pybase::threadworker() +void pybase::quworker(thr_params *) { - ++thrcount; - FifoEl *el; PyThreadState *my = FindThreadState(),*state; for(;;) { while(el = qufifo.Get()) { - ++thrcount; + ++el->th->thrcount; // \todo this should be atomic state = PyLock(my); - docall(el->fun,el->args); + el->th->docall(el->fun,el->args); Py_XDECREF(el->fun); Py_XDECREF(el->args); PyUnlock(state); + --el->th->thrcount; // \todo this should be atomic qufifo.Free(el); - --thrcount; } - if(shouldexit) - break; - else - qucond.Wait(); + qucond.Wait(); } + // we never end +#if 0 state = PyLock(my); // unref remaining Python objects while(el = qufifo.Get()) { @@ -673,8 +678,24 @@ void pybase::threadworker() qufifo.Free(el); } PyUnlock(state); +#endif +} - --thrcount; +void pybase::erasethreads() +{ + PyFifo tmp; + FifoEl *el; + while(el = qufifo.Get()) { + if(el->th == this) { + Py_XDECREF(el->fun); + Py_XDECREF(el->args); + qufifo.Free(el); + } + else + tmp.Put(el); + } + // Push back + while(el = tmp.Get()) qufifo.Put(el); } #endif diff --git a/externals/grill/py/source/pybase.h b/externals/grill/py/source/pybase.h index f7b6840b..28ee9770 100644 --- a/externals/grill/py/source/pybase.h +++ b/externals/grill/py/source/pybase.h @@ -148,7 +148,7 @@ protected: return true; } - virtual bool thrcall(void *data) = 0; +// virtual bool thrcall(void *data) = 0; virtual void callpy(PyObject *fun,PyObject *args) = 0; void exchandle(); @@ -161,13 +161,16 @@ protected: protected: - void work_wrapper(void *data); - #ifdef FLEXT_THREADS + static void thrworker(thr_params *data); + bool qucall(PyObject *fun,PyObject *args); - void threadworker(); - PyFifo qufifo; - ThrCond qucond; + + static void quworker(thr_params *); + void erasethreads(); + + static PyFifo qufifo; + static ThrCond qucond; static PyThreadState *pythrsys; static PyThreadState *FindThreadState(); diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp index a48a45ed..4252e64a 100644 --- a/externals/grill/py/source/pyext.cpp +++ b/externals/grill/py/source/pyext.cpp @@ -41,7 +41,7 @@ void pyext::Setup(t_classid c) FLEXT_CADDMETHOD_(c,0,"get",m_get); FLEXT_CADDMETHOD_(c,0,"set",m_set); - FLEXT_CADDATTR_VAR1(c,"xlate",xlate); + FLEXT_CADDATTR_VAR1(c,"py",xlate); FLEXT_CADDATTR_VAR1(c,"respond",respond); // ---------------------------------------------------- @@ -120,8 +120,6 @@ pyext::pyext(int argc,const t_atom *argv,bool sig): { #ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); - // launch thread worker - FLEXT_CALLMETHOD(threadworker); #endif if(argc >= 2 && CanbeInt(argv[0]) && CanbeInt(argv[1])) { @@ -629,8 +627,3 @@ void pyext::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); } - -bool pyext::thrcall(void *data) -{ - return FLEXT_CALLMETHOD_X(work_wrapper,data); -} diff --git a/externals/grill/py/source/pyext.h b/externals/grill/py/source/pyext.h index 361eda5d..d4652409 100644 --- a/externals/grill/py/source/pyext.h +++ b/externals/grill/py/source/pyext.h @@ -113,7 +113,6 @@ private: bool call(const char *meth,int inlet,const t_symbol *s,int argc,const t_atom *argv); - virtual bool thrcall(void *data); virtual void callpy(PyObject *fun,PyObject *args); static bool stcallpy(PyObject *fun,PyObject *args); @@ -148,10 +147,6 @@ private: #ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) - FLEXT_THREAD(threadworker) - FLEXT_THREAD_X(work_wrapper) -#else - FLEXT_CALLBACK_X(work_wrapper) #endif }; diff --git a/externals/grill/py/source/pymeth.cpp b/externals/grill/py/source/pymeth.cpp index e2278d1c..399c9463 100644 --- a/externals/grill/py/source/pymeth.cpp +++ b/externals/grill/py/source/pymeth.cpp @@ -124,7 +124,6 @@ protected: void SetFunction(const t_symbol *func); void ResetFunction(); - virtual bool thrcall(void *data); virtual void DumpOut(const t_symbol *sym,int argc,const t_atom *argv); PyObject **objects; @@ -154,10 +153,6 @@ private: #ifdef FLEXT_THREADS FLEXT_CALLBACK_T(tick) - FLEXT_THREAD(threadworker) - FLEXT_THREAD_X(work_wrapper) -#else - FLEXT_CALLBACK_X(work_wrapper) #endif }; @@ -181,7 +176,7 @@ void pymeth::Setup(t_classid c) FLEXT_CADDMETHOD_(c,0,"set",m_set); - FLEXT_CADDATTR_VAR1(c,"xlate",xlate); + FLEXT_CADDATTR_VAR1(c,"py",xlate); FLEXT_CADDATTR_VAR1(c,"respond",respond); // init translation map @@ -195,8 +190,6 @@ pymeth::pymeth(int argc,const t_atom *argv) { #ifdef FLEXT_THREADS FLEXT_ADDTIMER(stoptmr,tick); - // launch thread worker - FLEXT_CALLMETHOD(threadworker); #endif PyThreadState *state = PyLockSys(); @@ -436,8 +429,3 @@ void pymeth::DumpOut(const t_symbol *sym,int argc,const t_atom *argv) { ToOutAnything(GetOutAttr(),sym?sym:thisTag(),argc,argv); } - -bool pymeth::thrcall(void *data) -{ - return FLEXT_CALLMETHOD_X(work_wrapper,data); -} -- cgit v1.2.1