From 53c16e06983f9b03464f41b8c0ed3206382c5538 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Sun, 9 Jan 2005 04:59:30 +0000 Subject: support for Python threads, at last small fixes merged in 20041229-newdetach branch. renamed locking functions svn path=/trunk/; revision=2483 --- externals/grill/py/source/pyext.cpp | 186 +++++++++++++----------------------- 1 file changed, 68 insertions(+), 118 deletions(-) (limited to 'externals/grill/py/source/pyext.cpp') diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp index 9e1ff30b..f0fc25ba 100644 --- a/externals/grill/py/source/pyext.cpp +++ b/externals/grill/py/source/pyext.cpp @@ -2,7 +2,7 @@ py/pyext - python script object for PD and Max/MSP -Copyright (c)2002-2004 Thomas Grill (gr@grrrr.org) +Copyright (c)2002-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. @@ -13,9 +13,14 @@ WARRANTIES, see the file, "license.txt," in this distribution. FLEXT_LIB_V("pyext pyext. pyx pyx.",pyext) -V pyext::Setup(t_classid c) + +static const t_symbol *sym_get; + +void pyext::Setup(t_classid c) { - FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); + sym_get = flext::MakeSymbol("get"); + + FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); FLEXT_CADDMETHOD_(c,0,"dir",m_dir); FLEXT_CADDMETHOD_(c,0,"dir+",m_dir_); @@ -35,7 +40,6 @@ V pyext::Setup(t_classid c) FLEXT_CADDATTR_VAR1(c,"respond",respond); - // ---------------------------------------------------- // register/initialize pyext base class along with module @@ -112,7 +116,7 @@ static short patcher_myvol(t_patcher *x) PyObject *pyext::class_obj = NULL; PyObject *pyext::class_dict = NULL; -pyext::pyext(I argc,const t_atom *argv): +pyext::pyext(int argc,const t_atom *argv): pyobj(NULL),pythr(NULL), inlets(-1),outlets(-1), methname(NULL) @@ -127,7 +131,7 @@ pyext::pyext(I argc,const t_atom *argv): const t_atom *clname = NULL; - PY_LOCK + PyThreadState *state = PyLock(); // init script module if(argc > apre) { @@ -238,7 +242,7 @@ pyext::pyext(I argc,const t_atom *argv): else inlets = outlets = 0; - PY_UNLOCK + PyUnlock(state); if(inlets < 0 || outlets < 0) InitProblem(); @@ -253,7 +257,7 @@ pyext::pyext(I argc,const t_atom *argv): pyext::~pyext() { - PY_LOCK + PyThreadState *state = PyLock(); ClearBinding(); @@ -265,10 +269,10 @@ pyext::~pyext() Unregister("_pyext"); UnimportModule(); - PY_UNLOCK + PyUnlock(state); } -BL pyext::DoInit() +bool pyext::DoInit() { SetThis(); @@ -293,12 +297,12 @@ BL pyext::DoInit() return true; } -BL pyext::MakeInstance() +bool pyext::MakeInstance() { // pyobj should already have been decref'd / cleared before getting here!! if(module && methname) { - PyObject *pref = PyObject_GetAttrString(module,const_cast(GetString(methname))); + PyObject *pref = PyObject_GetAttrString(module,const_cast(GetString(methname))); if(!pref) PyErr_Print(); else { @@ -319,7 +323,7 @@ BL pyext::MakeInstance() return false; } -V pyext::Reload() +void pyext::Reload() { ClearBinding(); Py_XDECREF(pyobj); @@ -333,9 +337,9 @@ V pyext::Reload() } -V pyext::m_reload() +void pyext::m_reload() { - PY_LOCK + PyThreadState *state = PyLock(); Unregister("_pyext"); // self @@ -346,10 +350,10 @@ V pyext::m_reload() SetThis(); - PY_UNLOCK + PyUnlock(state); } -V pyext::m_reload_(I argc,const t_atom *argv) +void pyext::m_reload_(int argc,const t_atom *argv) { args(argc,argv); m_reload(); @@ -357,7 +361,7 @@ V pyext::m_reload_(I argc,const t_atom *argv) void pyext::m_get(const t_symbol *s) { - PY_LOCK + PyThreadState *state = PyLock(); PyObject *pvar = PyObject_GetAttrString(pyobj,const_cast(GetString(s))); /* fetch bound method */ if(!pvar) { @@ -368,7 +372,7 @@ void pyext::m_get(const t_symbol *s) AtomList *lst = GetPyArgs(pvar); if(lst) { // dump value to attribute outlet - AtomAnything out("get",lst->Count()+1); + AtomAnything out(sym_get,lst->Count()+1); SetSymbol(out[0],s); out.Set(lst->Count(),lst->Atoms(),1); delete lst; @@ -380,12 +384,12 @@ void pyext::m_get(const t_symbol *s) Py_DECREF(pvar); } - PY_UNLOCK + PyUnlock(state); } void pyext::m_set(int argc,const t_atom *argv) { - PY_LOCK + PyThreadState *state = PyLock(); if(argc < 2 || !IsString(argv[0])) post("%s - Syntax: set varname arguments...",thisName()); @@ -417,25 +421,25 @@ void pyext::m_set(int argc,const t_atom *argv) } } - PY_UNLOCK + PyUnlock(state); } -BL pyext::m_method_(I n,const t_symbol *s,I argc,const t_atom *argv) +bool pyext::m_method_(int n,const t_symbol *s,int argc,const t_atom *argv) { - BL ret = false; + bool ret = false; if(pyobj && n >= 1) - ret = callwork(n,s,argc,argv); + ret = work(n,s,argc,argv); else post("%s - no method for type '%s' into inlet %i",thisName(),GetString(s),n); return ret; } -V pyext::m_help() +void pyext::m_help() { post(""); - post("%s %s - python class object, (C)2002-2004 Thomas Grill",thisName(),PY__VERSION); + post("%s %s - python class object, (C)2002-2005 Thomas Grill",thisName(),PY__VERSION); #ifdef FLEXT_DEBUG post("DEBUG VERSION, compiled on " __DATE__ " " __TIME__); #endif @@ -460,97 +464,50 @@ V pyext::m_help() post(""); } -PyObject *pyext::call(const C *meth,I inlet,const t_symbol *s,I argc,const t_atom *argv) +bool pyext::callpy(PyObject *fun,PyObject *args) +{ + PyObject *ret = PyObject_Call(fun,args,NULL); + if(ret == NULL) { + // function not found resp. arguments not matching + PyErr_Print(); + return false; + } + else { + if(!PyObject_Not(ret)) post("pyext - returned value is ignored"); + Py_DECREF(ret); + return true; + } +} + + +bool pyext::call(const char *meth,int inlet,const t_symbol *s,int argc,const t_atom *argv) { - PyObject *ret = NULL; + bool ret = false; - PyObject *pmeth = PyObject_GetAttrString(pyobj,const_cast(meth)); /* fetch bound method */ + PyObject *pmeth = PyObject_GetAttrString(pyobj,const_cast(meth)); /* fetch bound method */ if(pmeth == NULL) { PyErr_Clear(); // no method found } else { PyObject *pargs = MakePyArgs(s,argc,argv,inlet?inlet:-1,true); - if(!pargs) + if(!pargs) { PyErr_Print(); - else { - ret = PyEval_CallObject(pmeth, pargs); - if (ret == NULL) // function not found resp. arguments not matching - PyErr_Print(); - - Py_DECREF(pargs); - } - Py_DECREF(pmeth); - } - - return ret; -} - -V pyext::work_wrapper(V *data) -{ - ++thrcount; -#ifdef FLEXT_DEBUG - if(!data) - post("%s - no data!",thisName()); - else -#endif - { -#ifdef FLEXT_THREADS - // --- make new Python thread --- - // get the global lock - PyEval_AcquireLock(); - // create a thread state object for this thread - PyThreadState *newthr = FindThreadState(); - // free the lock - PyEval_ReleaseLock(); -#endif - { - // call worker - work_data *w = (work_data *)data; - work(w->n,w->Header(),w->Count(),w->Atoms()); - delete w; + Py_DECREF(pmeth); } - -#ifdef FLEXT_THREADS - // --- delete Python thread --- - // grab the lock - PyEval_AcquireLock(); - // swap my thread state out of the interpreter - PyThreadState_Swap(NULL); - // delete mapped thread state - FreeThreadState(); - // release the lock - PyEval_ReleaseLock(); - // ----------------------------- -#endif - } - --thrcount; -} - -BL pyext::callwork(I n,const t_symbol *s,I argc,const t_atom *argv) -{ - BL ret = true,ok = false; - if(detach) { - if(shouldexit) - post("%s - Stopping.... new threads can't be launched now!",thisName()); - else { - ret = FLEXT_CALLMETHOD_X(work_wrapper,new work_data(n,s,argc,argv)); - if(!ret) post("%s - Failed to launch thread!",thisName()); - } + else + ret = gencall(pmeth,pargs); } - else - ret = ok = work(n,s,argc,argv); - Respond(ok); - return ret; + return ret; } -BL pyext::work(I n,const t_symbol *s,I argc,const t_atom *argv) +bool pyext::work(int n,const t_symbol *s,int argc,const t_atom *argv) { - BL retv = false; + bool ret = false; - PY_LOCK + PyThreadState *state = PyLock(); - PyObject *ret = NULL; - char *str = new char[strlen(GetString(s))+10]; + // should be enough... + char str[256]; { // try tag/inlet @@ -563,7 +520,7 @@ BL pyext::work(I n,const t_symbol *s,I argc,const t_atom *argv) sprintf(str,"_anything_%i",n); if(s == sym_bang && !argc) { t_atom argv; - SetString(argv,""); + SetSymbol(argv,sym__); ret = call(str,0,s,1,&argv); } else @@ -576,29 +533,22 @@ BL pyext::work(I n,const t_symbol *s,I argc,const t_atom *argv) } if(!ret) { // try anything at any inlet - strcpy(str,"_anything_"); + const char *str1 = "_anything_"; if(s == sym_bang && !argc) { t_atom argv; - SetString(argv,""); - ret = call(str,n,s,1,&argv); + SetSymbol(argv,sym__); + ret = call(str1,n,s,1,&argv); } else - ret = call(str,n,s,argc,argv); + ret = call(str1,n,s,argc,argv); } if(!ret) // no matching python method found post("%s - no matching method found for '%s' into inlet %i",thisName(),GetString(s),n); - if(str) delete[] str; + PyUnlock(state); - if(ret) { - if(!PyObject_Not(ret)) post("%s - returned value is ignored",thisName()); - Py_DECREF(ret); - retv = true; - } - - PY_UNLOCK - - return retv; + Respond(ret); + return ret; } -- cgit v1.2.1