Update of /cvsroot/pure-data/externals/grill/py/source In directory sc8-pr-cvs1:/tmp/cvs-serv3396/source
Modified Files: bound.cpp clmeth.cpp main.cpp main.h modmeth.cpp py.cpp pyext.cpp pyext.h Log Message: ""
Index: bound.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/bound.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** bound.cpp 4 Jun 2003 02:38:08 -0000 1.5 --- bound.cpp 20 Oct 2003 02:38:10 -0000 1.6 *************** *** 12,37 **** #include "flinternal.h"
! #ifndef USEFLEXTBINDING ! t_class *pyext::px_class; ! pyext::py_proxy *pyext::px_head,*pyext::px_tail; ! ! void pyext::py_proxy::px_method(py_proxy *obj,const t_symbol *s,int argc,const t_atom *argv) ! { ! PY_LOCK ! ! PyObject *args = MakePyArgs(s,AtomList(argc,argv),-1,obj->self != NULL); ! PyObject *ret = PyObject_CallObject(obj->func,args); ! if(!ret) { ! PyErr_Print(); ! } ! Py_XDECREF(ret); ! ! PY_UNLOCK ! } ! ! #else ! struct bounddata { PyObject *self,*func; };
! bool pyext::boundmeth(flext_base *,const t_symbol *sym,int argc,const t_atom *argv,void *data) { bounddata *obj = (bounddata *)data; --- 12,22 ---- #include "flinternal.h"
! struct bounddata ! { ! PyObject *self; ! std::set<PyObject *> funcs; ! };
! bool pyext::boundmeth(flext_base *,t_symbol *sym,int argc,t_atom *argv,void *data) { bounddata *obj = (bounddata *)data; *************** *** 40,53 ****
PyObject *args = MakePyArgs(sym,AtomList(argc,argv),-1,obj->self != NULL); ! PyObject *ret = PyObject_CallObject(obj->func,args); ! if(!ret) { ! PyErr_Print(); ! } ! Py_XDECREF(ret);
PY_UNLOCK return true; } - #endif
PyObject *pyext::pyext_bind(PyObject *,PyObject *args) --- 25,41 ----
PyObject *args = MakePyArgs(sym,AtomList(argc,argv),-1,obj->self != NULL); ! ! // call all functions bound by this symbol ! for(std::set<PyObject *>::iterator it = obj->funcs.begin(); it != obj->funcs.end(); ++it) { ! PyObject *ret = PyObject_CallObject(*it,args); ! if(!ret) { ! PyErr_Print(); ! } ! Py_XDECREF(ret); ! }
PY_UNLOCK return true; }
PyObject *pyext::pyext_bind(PyObject *,PyObject *args) *************** *** 73,95 **** Py_DECREF(no); } - #ifndef USEFLEXTBINDING - py_proxy *px = (py_proxy *)object_new(px_class); - px->init(recv,self,meth);
! // add it to the list ! if(px_tail) px_tail->nxt = px; ! else px_head = px; ! px_tail = px; ! ! // Do bind ! pd_bind(&px->obj.ob_pd,(t_symbol *)recv); ! #else ! bounddata *data = new bounddata; ! data->self = self; ! data->func = meth; ! GetThis(self)->BindMethod(recv,boundmeth,data); ! #endif
! Py_INCREF(self); // self is borrowed reference }
--- 61,80 ---- Py_DECREF(no); }
! void *data = NULL; ! if(GetThis(self)->GetBoundMethod(recv,boundmeth,data)) { ! // already bound to that symbol and function ! bounddata *bdt = (bounddata *)data; ! FLEXT_ASSERT(bdt != NULL && bdt->self == self); ! bdt->funcs.insert(meth); ! } ! else { ! bounddata *data = new bounddata; ! data->self = self; ! data->funcs.insert(meth); ! GetThis(self)->BindMethod(recv,boundmeth,data);
! Py_INCREF(self); // self is borrowed reference ! } }
*************** *** 115,154 **** }
- #ifndef USEFLEXTBINDING - // search proxy object - py_proxy *pp = NULL,*px = px_head; - while(px) { - py_proxy *pn = px->nxt; - if(recv == px->name && self == px->self && meth == px->func) { - if(pp) - pp->nxt = pn; - else - px_head = pn; - if(!pn) px_tail = pp; - break; - } - else pp = px; - px = pn; - } - - // do unbind - if(px) { - pd_unbind(&px->obj.ob_pd,(t_symbol *)recv); - object_free(&px->obj); - - Py_DECREF(self); - if(PyMethod_Check(meth)) Py_DECREF(meth); - } - #else void *data = NULL; if(GetThis(self)->UnbindMethod(recv,boundmeth,&data)) { ! bounddata *bdt = (bounddata *)data; ! if(bdt) { ! Py_DECREF(bdt->self); ! if(PyMethod_Check(bdt->func)) Py_DECREF(bdt->func); ! if(data) delete bdt; } } - #endif }
--- 100,118 ---- }
void *data = NULL; if(GetThis(self)->UnbindMethod(recv,boundmeth,&data)) { ! bounddata *bdt = (bounddata *)data; ! FLEXT_ASSERT(bdt != NULL); ! ! if(PyMethod_Check(meth)) Py_DECREF(meth); ! ! // erase from map ! bdt->funcs.erase(meth); ! ! if(bdt->funcs.empty()) { ! Py_DECREF(bdt->self); ! delete bdt; } } }
*************** *** 160,185 **** V pyext::ClearBinding() { - #ifndef USEFLEXTBINDING - // search proxy object - py_proxy *pp = NULL,*px = px_head; - while(px) { - py_proxy *pn = px->nxt; - if(px->self == pyobj) { - if(pp) - pp->nxt = pn; - else - px_head = pn; - if(!pn) px_tail = pp; - - Py_DECREF(px->self); - if(PyMethod_Check(px->func)) Py_DECREF(px->func); - - pd_unbind(&px->obj.ob_pd,(t_symbol *)px->name); - object_free(&px->obj); - } - else pp = px; - px = pn; - } - #else void *data = NULL; const t_symbol *sym = NULL; --- 124,127 ---- *************** *** 189,199 **** bounddata *bdt = (bounddata *)data; if(bdt) { Py_DECREF(bdt->self); - if(PyMethod_Check(bdt->func)) Py_DECREF(bdt->func); if(data) delete bdt; } } - #endif } - - --- 131,142 ---- bounddata *bdt = (bounddata *)data; if(bdt) { + for(std::set<PyObject *>::iterator it = bdt->funcs.begin(); it != bdt->funcs.end(); ++it) { + PyObject *func = *it; + if(PyMethod_Check(func)) Py_DECREF(func); + } + Py_DECREF(bdt->self); if(data) delete bdt; } } }
Index: clmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/clmeth.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** clmeth.cpp 4 Jan 2003 04:36:49 -0000 1.3 --- clmeth.cpp 20 Oct 2003 02:38:10 -0000 1.4 *************** *** 18,22 **** --- 18,24 ----
{"_outlet", pyext::pyext_outlet, METH_VARARGS,"Send message to outlet"}, + #if FLEXT_SYS == FLEXT_SYS_PD {"_tocanvas", pyext::pyext_tocanvas, METH_VARARGS,"Send message to canvas" }, + #endif
{ "_bind", pyext::pyext_bind, METH_VARARGS,"Bind function to a receiving symbol" }, *************** *** 26,29 **** --- 28,32 ---- { "_stop", pyext::pyext_stop, METH_VARARGS,"Stop running threads" }, #endif + { "_isthreaded", pyext::pyext_isthreaded, METH_O,"Query whether threading is enabled" }, {NULL, NULL, 0, NULL} /* Sentinel */ }; *************** *** 222,225 **** --- 225,241 ---- #endif
+ //! Query whether threading is enabled + PyObject *pyext::pyext_isthreaded(PyObject *,PyObject *) + { + return Py_BuildValue("i", + #ifdef FLEXT_THREADED + 1 + #else + 0 + #endif + ); + } + + #if FLEXT_SYS == FLEXT_SYS_PD //! Send message to canvas PyObject *pyext::pyext_tocanvas(PyObject *,PyObject *args) *************** *** 245,253 **** t_class **cl = (t_pd *)gl; if(cl) { - #if FLEXT_SYS == FLEXT_SYS_PD pd_forwardmess(cl,lst->Count(),lst->Atoms()); - #else - #pragma message ("Send is not implemented") - #endif } #ifdef FLEXT_DEBUG --- 261,265 ---- *************** *** 270,273 **** --- 282,286 ---- return Py_None; } + #endif
Index: main.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/main.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** main.cpp 4 Jan 2003 04:36:49 -0000 1.4 --- main.cpp 20 Oct 2003 02:38:10 -0000 1.5 *************** *** 14,18 **** { post(""); ! post("py/pyext %s - python script objects, (C)2002 Thomas Grill",PY__VERSION); post("");
--- 14,18 ---- { post(""); ! post("py/pyext %s - python script objects, (C)2002,2003 Thomas Grill",PY__VERSION); post("");
*************** *** 26,30 ****
PyInterpreterState *py::pystate = NULL; !
I py::pyref = 0; --- 26,30 ----
PyInterpreterState *py::pystate = NULL; ! std::map<flext::thrid_t,PyThreadState *> py::pythrmap;
I py::pyref = 0; *************** *** 36,43 **** module(NULL), detach(false),shouldexit(false),thrcount(0), ! clk(NULL),stoptick(0) { Lock(); ! // under Max/MSP: doesn't survive next line.....
if(!(pyref++)) { --- 36,43 ---- module(NULL), detach(false),shouldexit(false),thrcount(0), ! stoptick(0) { Lock(); ! // under Max/MSP @ OS9: doesn't survive next line.....
if(!(pyref++)) { *************** *** 45,61 ****
#ifdef FLEXT_THREADS PyEval_InitThreads();
! pystate = PyThreadState_Get()->interp; ! #endif ! // register/initialize pyext module only once! module_obj = Py_InitModule(PYEXT_MODULE, func_tbl); module_dict = PyModule_GetDict(module_obj);
PyModule_AddStringConstant(module_obj,"__doc__",(C *)py_doc); - - #ifdef FLEXT_THREADS - pythrmain = PyEval_SaveThread(); - #endif } else { --- 45,68 ----
#ifdef FLEXT_THREADS + // enable thread support and acquire the global thread lock PyEval_InitThreads();
! // get thread state ! PyThreadState *pythrmain = PyThreadState_Get(); ! // get main interpreter state ! pystate = pythrmain->interp; ! ! // release global lock ! PyEval_ReleaseLock(); ! ! // add thread state of main thread to map ! pythrmap[GetThreadId()] = pythrmain; ! #endif ! ! // register/initialize pyext module only once! module_obj = Py_InitModule(PYEXT_MODULE, func_tbl); module_dict = PyModule_GetDict(module_obj);
PyModule_AddStringConstant(module_obj,"__doc__",(C *)py_doc); } else { *************** *** 68,72 **** Unlock();
! clk = clock_new(this,(t_method)tick); }
--- 75,79 ---- Unlock();
! FLEXT_ADDTIMER(stoptmr,tick); }
*************** *** 85,113 **** } - /* - // don't unregister - Lock();
if(!(--pyref)) { ! Py_DECREF(module_obj); module_obj = NULL; - Py_DECREF(module_dict); module_dict = NULL;
Py_XDECREF(module);
! // delete modules; modules = NULL; ! ! PyEval_AcquireThread(pythrmain); ! PyThreadState *new_state = PyThreadState_New(pystate); // must have lock ! PyThreadState *prev_state = PyThreadState_Swap(new_state);
Py_Finalize(); }
Unlock(); - */ - if(clk) clock_free(clk); }
--- 92,122 ---- } Lock();
if(!(--pyref)) { ! // no more py/pyext objects left... shut down Python ! module_obj = NULL; module_dict = NULL;
Py_XDECREF(module);
! PyEval_AcquireLock(); ! PyThreadState_Swap(pythrmap[GetThreadId()]);
+ #ifdef FLEXT_DEBUG + // need not necessarily do that.... Py_Finalize(); + #endif + + // reset thread state map + pythrmap.clear(); } + else { + Py_DECREF(module_obj); + Py_DECREF(module_dict); + }
Unlock(); }
Index: main.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/main.h,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** main.h 5 Mar 2003 04:37:46 -0000 1.6 --- main.h 20 Oct 2003 02:38:10 -0000 1.7 *************** *** 14,17 **** --- 14,18 ---- #include <flext.h> #include <Python.h> + #include <map>
#if FLEXT_OS == FLEXT_LINUX || FLEXT_OS == FLEXT_IRIX *************** *** 19,24 **** #endif
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 403) ! #error You need at least flext version 0.4.3 #endif
--- 20,25 ---- #endif
! #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 500) ! #error You need at least flext version 0.5.0 #endif
*************** *** 104,115 **** BL detach,shouldexit; I thrcount; - t_clock *clk; I stoptick;
! static V tick(py *obj);
public: static PyInterpreterState *pystate; ! PyThreadState *pythrmain;
#ifdef FLEXT_THREADS --- 105,116 ---- BL detach,shouldexit; I thrcount; I stoptick; + Timer stoptmr;
! V tick(V *);
public: static PyInterpreterState *pystate; ! static std::map<flext::thrid_t,PyThreadState *> pythrmap;
#ifdef FLEXT_THREADS *************** *** 128,144 **** FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_doc) };
#ifdef FLEXT_THREADS #define PY_LOCK \ { \ ! PyThreadState *thrst = PyThreadState_New(pystate); \ ! PyEval_AcquireThread(thrst);
#define PY_UNLOCK \ ! PyThreadState_Clear(thrst); /* must have lock */ \ ! PyEval_ReleaseThread(thrst); \ ! PyThreadState_Delete(thrst); /* needn't have lock */ \ ! } #else #define PY_LOCK --- 129,149 ---- FLEXT_CALLBACK_V(m_stop) FLEXT_CALLBACK(m_doc) + FLEXT_CALLBACK_T(tick) };
#ifdef FLEXT_THREADS + #define PY_LOCK \ { \ ! PyEval_AcquireLock(); \ ! PyThreadState *__st = pythrmap[GetThreadId()]; \ ! FLEXT_ASSERT(__st != NULL); \ ! PyThreadState *__oldst = PyThreadState_Swap(__st);
#define PY_UNLOCK \ ! PyThreadState_Swap(__oldst); \ ! PyEval_ReleaseLock(); \ ! } ! #else #define PY_LOCK
Index: modmeth.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/modmeth.cpp,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** modmeth.cpp 5 Mar 2003 04:37:46 -0000 1.6 --- modmeth.cpp 20 Oct 2003 02:38:10 -0000 1.7 *************** *** 44,68 ****
! V py::tick(py *th) { ! th->Lock();
! if(!th->thrcount) { // all threads have stopped ! th->shouldexit = false; ! th->stoptick = 0; } else { // still active threads ! if(!--th->stoptick) { ! post("%s - Threads couldn't be stopped entirely - %i remaining",th->thisName(),th->thrcount); ! th->shouldexit = false; } else // continue waiting ! clock_delay(th->clk,PY_STOP_TICK); }
! th->Unlock(); }
--- 44,68 ----
! V py::tick(V *) { ! Lock();
! if(!thrcount) { // all threads have stopped ! shouldexit = false; ! stoptick = 0; } else { // still active threads ! if(!--stoptick) { ! post("%s - Threads couldn't be stopped entirely - %i remaining",thisName(),thrcount); ! shouldexit = false; } else // continue waiting ! stoptmr.Delay(PY_STOP_TICK/1000.); }
! Unlock(); }
*************** *** 83,87 **** stoptick = ticks; shouldexit = true; ! clock_delay(clk,PY_STOP_TICK);
Unlock(); --- 83,87 ---- stoptick = ticks; shouldexit = true; ! stoptmr.Delay(PY_STOP_TICK/1000.);
Unlock();
Index: py.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/py.cpp,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** py.cpp 4 Jan 2003 04:36:49 -0000 1.5 --- py.cpp 20 Oct 2003 02:38:10 -0000 1.6 *************** *** 74,78 ****
! void pyobj::Setup(t_class *c) { FLEXT_CADDBANG(c,0,m_bang); --- 74,78 ----
! void pyobj::Setup(t_classid c) { FLEXT_CADDBANG(c,0,m_bang);
Index: pyext.cpp =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.cpp,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** pyext.cpp 17 Oct 2003 02:47:01 -0000 1.7 --- pyext.cpp 20 Oct 2003 02:38:10 -0000 1.8 *************** *** 17,27 **** V pyext::Setup(t_classid c) { - #ifndef USEFLEXTBINDING - px_head = px_tail = NULL; - - px_class = class_new(gensym("pyext proxy"),NULL,NULL,sizeof(py_proxy),CLASS_PD|CLASS_NOINLET, A_NULL); - ::add_anything(px_class,py_proxy::px_method); // for other inlets - #endif - FLEXT_CADDMETHOD_(c,0,"reload.",m_reload); FLEXT_CADDMETHOD_(c,0,"reload",m_reload_); --- 17,20 ---- *************** *** 117,120 **** --- 110,114 ---- else { SetArgs(0,NULL); + ImportModule(GetString(argv[0])); } *************** *** 193,198 **** Py_XDECREF(class_obj); Py_XDECREF(class_dict); - /* - // Don't unregister
if(!--pyextref) { --- 187,190 ---- *************** *** 200,204 **** class_dict = NULL; } ! */ PY_UNLOCK } --- 192,196 ---- class_dict = NULL; } ! PY_UNLOCK } *************** *** 359,365 **** PyErr_Clear(); #endif - else { - // Py_DECREF(pres); - }
Py_DECREF(pargs); --- 351,354 ---- *************** *** 380,386 **** #endif { ! work_data *w = (work_data *)data; ! work(w->n,w->Header(),w->Count(),w->Atoms()); ! delete w; } --thrcount; --- 369,407 ---- #endif { ! // --- make new Python thread --- ! // get the global lock ! PyEval_AcquireLock(); ! // get a reference to the PyInterpreterState ! // create a thread state object for this thread ! PyThreadState *newthr = PyThreadState_New(pystate); ! // free the lock ! PyEval_ReleaseLock(); ! // ----------------------------- ! ! // store new thread state ! pythrmap[GetThreadId()] = newthr; ! ! { ! // call worker ! work_data *w = (work_data *)data; ! work(w->n,w->Header(),w->Count(),w->Atoms()); ! delete w; ! } ! ! // delete mapped thread state ! pythrmap.erase(GetThreadId()); ! ! // --- delete Python thread --- ! // grab the lock ! PyEval_AcquireLock(); ! // swap my thread state out of the interpreter ! PyThreadState_Swap(NULL); ! // clear out any cruft from thread state object ! PyThreadState_Clear(newthr); ! // delete my thread state object ! PyThreadState_Delete(newthr); ! // release the lock ! PyEval_ReleaseLock(); ! // ----------------------------- } --thrcount;
Index: pyext.h =================================================================== RCS file: /cvsroot/pure-data/externals/grill/py/source/pyext.h,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** pyext.h 4 Jun 2003 02:38:08 -0000 1.7 --- pyext.h 20 Oct 2003 02:38:10 -0000 1.8 *************** *** 28,32 **** --- 28,34 ----
static PyObject *pyext_outlet(PyObject *,PyObject *args); + #if FLEXT_SYS == FLEXT_SYS_PD static PyObject *pyext_tocanvas(PyObject *,PyObject *args); + #endif
static PyObject *pyext_setattr(PyObject *,PyObject *args); *************** *** 35,38 **** --- 37,41 ---- static PyObject *pyext_detach(PyObject *,PyObject *args); static PyObject *pyext_stop(PyObject *,PyObject *args); + static PyObject *pyext_isthreaded(PyObject *,PyObject *);
I Inlets() const { return inlets; } *************** *** 69,102 **** static const C *pyext_doc;
! // -------- bound stuff ------------------ ! ! #ifndef USEFLEXTBINDING ! static t_class *px_class; ! ! friend class py_proxy; ! ! class py_proxy // no virtual table! ! { ! public: ! t_object obj; // MUST reside at memory offset 0 ! PyObject *self,*func; ! const t_symbol *name; ! ! py_proxy *nxt; ! ! void init(const t_symbol *n,PyObject *s,PyObject *f) { name = n,self = s,func = f,nxt = NULL; } ! // bool cmp(PyObject *s,PyObject *f) const { return self == s && func == f; } ! // void init(PyObject *s,char *f) { self = s,func = f,nxt = NULL; } ! // bool cmp(PyObject *s,char *f) const { return self == s && func == f; } ! static void px_method(py_proxy *c,const t_symbol *s,int argc,const t_atom *argv); ! }; ! static py_proxy *px_head,*px_tail; ! ! static PyObject *pyext_bind(PyObject *,PyObject *args); ! static PyObject *pyext_unbind(PyObject *,PyObject *args); ! #else static PyObject *pyext_bind(PyObject *,PyObject *args); static PyObject *pyext_unbind(PyObject *,PyObject *args); - #endif
// --------------------------- --- 72,78 ---- static const C *pyext_doc;
! // -------- bind stuff ------------------ static PyObject *pyext_bind(PyObject *,PyObject *args); static PyObject *pyext_unbind(PyObject *,PyObject *args);
// --------------------------- *************** *** 124,128 ****
private: ! static bool boundmeth(flext_base *,const t_symbol *sym,int argc,const t_atom *argv,void *data);
FLEXT_CALLBACK(m_reload) --- 100,104 ----
private: ! static bool boundmeth(flext_base *,t_symbol *sym,int argc,t_atom *argv,void *data);
FLEXT_CALLBACK(m_reload)