aboutsummaryrefslogtreecommitdiff
path: root/externals
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2005-02-23 04:57:19 +0000
committerThomas Grill <xovo@users.sourceforge.net>2005-02-23 04:57:19 +0000
commit579f564ce490566d0462bc2138a4beefa7747b7e (patch)
tree1d97a889e28f2638209acf05b6a9f5dff6cd6c80 /externals
parent4a65e0dcd504848ee89dfe3d12321e2587b2a77d (diff)
better cleanup behavior (shutdown hook method _del and garbage collection)
- garbage collection at module scope update for flext build system - better handling of bang messages fixes for single-threaded compilation little restructuring svn path=/trunk/; revision=2573
Diffstat (limited to 'externals')
-rw-r--r--externals/grill/py/readme.txt3
-rw-r--r--externals/grill/py/source/main.cpp23
-rw-r--r--externals/grill/py/source/main.h12
-rw-r--r--externals/grill/py/source/pyext.cpp42
4 files changed, 47 insertions, 33 deletions
diff --git a/externals/grill/py/readme.txt b/externals/grill/py/readme.txt
index a39f529e..1aa18022 100644
--- a/externals/grill/py/readme.txt
+++ b/externals/grill/py/readme.txt
@@ -81,6 +81,7 @@ Version history:
- FIX: __init__ wasn't called on reload
- FIX: bound instance methods weren't correctly decref'd
- ADD: Python symbol type
+- ADD: _del method in pyext-derived class can be used to clean up things on exit
0.1.4:
- ADD: better (and independent) handling of inlet and outlet count (as class variables or dynamically initialized in __init__)
@@ -152,7 +153,5 @@ features:
- stop individual threads
- support named (keyword) arguments (like attributes for messages)
-- shutdown hook for threaded Python apps
-
tests:
- check for python threading support
diff --git a/externals/grill/py/source/main.cpp b/externals/grill/py/source/main.cpp
index 89696b46..bf7345d5 100644
--- a/externals/grill/py/source/main.cpp
+++ b/externals/grill/py/source/main.cpp
@@ -17,6 +17,7 @@ static PyMethodDef StdOut_Methods[] =
{ NULL, NULL, }
};
+static PyObject *gcollect = NULL;
#ifdef FLEXT_THREADS
@@ -119,6 +120,13 @@ void py::lib_setup()
py_out = Py_InitModule("stderr", StdOut_Methods);
PySys_SetObject("stderr", py_out);
+ // get garbage collector function
+ PyObject *gcobj = PyImport_ImportModule("gc");
+ if(gcobj) {
+ gcollect = PyObject_GetAttrString(gcobj,"collect");
+ Py_DECREF(gcobj);
+ }
+
// -------------------------------------------------------------
FLEXT_SETUP(pyobj);
@@ -548,6 +556,21 @@ short py::patcher_myvol(t_patcher *x)
}
#endif
+void py::collect()
+{
+ if(gcollect) {
+ PyObject *args = PyTuple_New(0);
+ PyObject *ret = PyObject_Call(gcollect,args,NULL);
+ Py_DECREF(args);
+ if(ret) {
+#ifdef FLEXT_DEBUG
+ int refs = PyInt_AsLong(ret);
+ if(refs) post("py/pyext - Garbage collector reports %i unreachable objects",refs);
+#endif
+ Py_DECREF(ret);
+ }
+ }
+}
Fifo::~Fifo()
{
diff --git a/externals/grill/py/source/main.h b/externals/grill/py/source/main.h
index 8671a87f..621c9eff 100644
--- a/externals/grill/py/source/main.h
+++ b/externals/grill/py/source/main.h
@@ -90,7 +90,7 @@ protected:
void Respond(bool b);
- static bool IsAnything(const t_symbol *s) { return s && s != sym_bang && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
+ static bool IsAnything(const t_symbol *s) { return s && s != sym_float && s != sym_int && s != sym_symbol && s != sym_list && s != sym_pointer; }
enum retval { nothing,atom,sequ };
@@ -132,6 +132,8 @@ protected:
static short patcher_myvol(t_patcher *x);
#endif
+ static void collect();
+
private:
void work_wrapper(void *data);
@@ -142,16 +144,14 @@ private:
Fifo qufifo;
ThrCond qucond;
+ static PyThreadState *FindThreadState();
+ static void FreeThreadState();
+
FLEXT_THREAD_X(work_wrapper)
#else
FLEXT_CALLBACK_X(work_wrapper)
#endif
-#ifdef FLEXT_THREADS
- static PyThreadState *FindThreadState();
- static void FreeThreadState();
-#endif
-
public:
#ifdef FLEXT_THREADS
diff --git a/externals/grill/py/source/pyext.cpp b/externals/grill/py/source/pyext.cpp
index 4acafd60..de208aac 100644
--- a/externals/grill/py/source/pyext.cpp
+++ b/externals/grill/py/source/pyext.cpp
@@ -225,28 +225,26 @@ void pyext::DoExit()
{
ClearBinding();
+ bool gcrun = false;
if(pyobj) {
- if(pyobj->ob_refcnt > 1) {
- post("%s - Python object is still referenced",thisName());
-
- // Force-quit object:
- // call __del__ manually
- // this is dangerous, because it could get called a second time
- // if object really has no more references then
- PyObject *meth = PyObject_GetAttrString(pyobj,"__del__"); // get ref
- if(meth) {
- if(PyMethod_Check(meth)) {
- PyObject *res = PyObject_CallObject(meth,NULL);
- if(!res)
- PyErr_Print();
- else
- Py_DECREF(res);
- }
- Py_DECREF(meth);
- }
+ // try to run del to clean up the class instance
+ PyObject *objdel = PyObject_GetAttrString(pyobj,"_del");
+ if(objdel) {
+ PyObject *args = PyTuple_New(0);
+ PyObject *ret = PyObject_Call(objdel,args,NULL);
+ if(!ret)
+ post("%s - Could not call _del method",thisName());
+ else
+ Py_DECREF(ret);
+ Py_DECREF(args);
+ Py_DECREF(objdel);
}
+
+ gcrun = pyobj->ob_refcnt > 1;
Py_DECREF(pyobj); // opposite of SetClssMeth
}
+
+ if(gcrun) collect();
}
void pyext::InitInOut(int &inl,int &outl)
@@ -542,13 +540,7 @@ bool pyext::work(int n,const t_symbol *s,int argc,const t_atom *argv)
// try anything/inlet
if(!ret) {
sprintf(str,"_anything_%i",n);
- if(s == sym_bang && !argc) {
- t_atom argv;
- SetSymbol(argv,sym__);
- ret = call(str,0,s,1,&argv);
- }
- else
- ret = call(str,0,s,argc,argv);
+ ret = call(str,0,s,argc,argv);
}
// try int at any inlet