summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog1
-rw-r--r--python/progress.cc19
-rw-r--r--python/progress.h17
3 files changed, 37 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index 0f9463b2..db6204ba 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,7 @@ python-apt (0.7.10.4) UNRELEASED; urgency=low
fetched
* python/progress.cc:
- low level code for update_status_full and pulse_items()
+ - better threading support
-- Michael Vogt <michael.vogt@ubuntu.com> Tue, 05 May 2009 11:57:57 +0200
diff --git a/python/progress.cc b/python/progress.cc
index 95cece3b..027a51b4 100644
--- a/python/progress.cc
+++ b/python/progress.cc
@@ -94,6 +94,7 @@ void PyOpProgress::Done()
bool PyFetchProgress::MediaChange(string Media, string Drive)
{
+ PyCbObj_END_ALLOW_THREADS
//std::cout << "MediaChange" << std::endl;
PyObject *arglist = Py_BuildValue("(ss)", Media.c_str(), Drive.c_str());
PyObject *result;
@@ -106,6 +107,7 @@ bool PyFetchProgress::MediaChange(string Media, string Drive)
// FIXME: find out what it should return usually
//std::cerr << "res is: " << res << std::endl;
+ PyCbObj_BEGIN_ALLOW_THREADS
return res;
}
@@ -116,6 +118,7 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
// Added object file size and object partial size to
// parameters that are passed to updateStatus.
// -- Stephan
+ PyCbObj_END_ALLOW_THREADS
PyObject *arglist = Py_BuildValue("(sssikk)", Itm.URI.c_str(),
Itm.Description.c_str(),
Itm.ShortDesc.c_str(),
@@ -131,6 +134,7 @@ void PyFetchProgress::UpdateStatus(pkgAcquire::ItemDesc &Itm, int status)
Itm.ShortDesc.c_str(),
status);
RunSimpleCallback("updateStatus", arglist);
+ PyCbObj_BEGIN_ALLOW_THREADS
}
@@ -190,11 +194,21 @@ void PyFetchProgress::Start()
Py_XDECREF(o);
RunSimpleCallback("start");
+ /* After calling the start method we can safely allow
+ * other Python threads to do their work for now.
+ */
+ PyCbObj_BEGIN_ALLOW_THREADS
}
void PyFetchProgress::Stop()
{
+ /* After the stop operation occured no other threads
+ * are allowed. This is done so we have a matching
+ * PyCbObj_END_ALLOW_THREADS to our previous
+ * PyCbObj_BEGIN_ALLOW_THREADS (Python requires this!).
+ */
+ PyCbObj_END_ALLOW_THREADS
//std::cout << "Stop" << std::endl;
pkgAcquireStatus::Stop();
RunSimpleCallback("stop");
@@ -202,6 +216,7 @@ void PyFetchProgress::Stop()
bool PyFetchProgress::Pulse(pkgAcquire * Owner)
{
+ PyCbObj_END_ALLOW_THREADS
pkgAcquireStatus::Pulse(Owner);
//std::cout << "Pulse" << std::endl;
@@ -290,11 +305,13 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
RunSimpleCallback("pulse_items", arglist, &result);
if (result != NULL && PyArg_Parse(result, "b", &res) && res == false) {
// the user returned a explicit false here, stop
+ PyCbObj_BEGIN_ALLOW_THREADS
return false;
}
arglist = Py_BuildValue("()");
if (!RunSimpleCallback("pulse", arglist, &result)) {
+ PyCbObj_BEGIN_ALLOW_THREADS
return true;
}
@@ -303,9 +320,11 @@ bool PyFetchProgress::Pulse(pkgAcquire * Owner)
// most of the time the user who subclasses the pulse()
// method forgot to add a return {True,False} so we just
// assume he wants a True
+ PyCbObj_BEGIN_ALLOW_THREADS
return true;
}
+ PyCbObj_BEGIN_ALLOW_THREADS
// fetching can be canceld by returning false
return res;
}
diff --git a/python/progress.h b/python/progress.h
index 5ac67b1c..29243bfc 100644
--- a/python/progress.h
+++ b/python/progress.h
@@ -15,10 +15,27 @@
#include <apt-pkg/cdrom.h>
#include <Python.h>
+/* PyCbObj_BEGIN_ALLOW_THREADS and PyCbObj_END_ALLOW_THREADS are sligthly
+ * modified versions of Py_BEGIN_ALLOW_THREADS and Py_END_ALLOW_THREADS.
+ * Instead of storing the thread state in a function-local variable these
+ * use a class attribute (with the same) name, allowing blocking and
+ * unblocking from different class methods.
+ * Py_BLOCK_THREADS and Py_UNBLOCK_THREADS do not define their own
+ * local variable but use the one provided by PyCbObj_BEGIN_ALLOW_THREADS
+ * and thus are the same as Py_BLOCK_THREADS and Py_UNBLOCK_THREADS.
+ */
+#define PyCbObj_BEGIN_ALLOW_THREADS \
+ _save = PyEval_SaveThread();
+#define PyCbObj_END_ALLOW_THREADS \
+ PyEval_RestoreThread(_save); \
+ _save = NULL;
+#define PyCbObj_BLOCK_THREADS Py_BLOCK_THREADS
+#define PyCbObj_UNBLOCK_THREADS Py_UNBLOCK_THREADS
class PyCallbackObj {
protected:
PyObject *callbackInst;
+ PyThreadState *_save;
public:
void setCallbackInst(PyObject *o) {