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)