add thread support based in proposal #398495 by Joseph Winston

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7929 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2005-12-06 06:39:24 +00:00
commit 0fd2fe23cf
16 changed files with 337 additions and 37 deletions

View file

@ -28,15 +28,19 @@ SWIG_AsArgcArgv(PyObject* input,
argv[i] = 0;
}
} else {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_Clear();
PyErr_SetString(PyExc_TypeError,"list or tuple must contain strings only");
SWIG_PYTHON_THREAD_END_BLOCK;
}
}
argv[i] = 0;
return argv;
} else {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
*argc = 0;
PyErr_SetString(PyExc_TypeError,"a list or tuple is expected");
SWIG_PYTHON_THREAD_END_BLOCK;
return 0;
}
} else {

View file

@ -21,16 +21,17 @@
*/
SWIGINTERN PyObject *swig_call_defargs(PyObject *self, PyObject *args) {
PyObject *func;
PyObject *parms;
if (!PyArg_ParseTuple(args,"OO",&func,&parms))
return NULL;
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError, "__call_defarg : Need a callable object!");
return NULL;
}
return PyEval_CallObject(func,parms);
PyObject *func;
PyObject *parms;
if (!PyArg_ParseTuple(args,"OO",&func,&parms))
return NULL;
if (!PyCallable_Check(func)) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError, "__call_defarg : Need a callable object!");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
return PyEval_CallObject(func,parms);
}

View file

@ -221,6 +221,7 @@ namespace Swig {
DirectorException(PyObject *error, const char* hdr ="", const char* msg ="")
: swig_msg(hdr)
{
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (strlen(msg)) {
swig_msg += " ";
swig_msg += msg;
@ -230,6 +231,7 @@ namespace Swig {
} else {
SWIG_Python_AddErrorMsg(getMessage());
}
SWIG_PYTHON_THREAD_END_BLOCK;
}
const char *getMessage() const
@ -359,7 +361,9 @@ namespace Swig {
/* decrement the reference count of the wrapped python object */
void swig_decref() const {
if (swig_disown_flag) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
Py_DECREF(swig_self);
SWIG_PYTHON_THREAD_END_BLOCK;
}
}

View file

@ -13,6 +13,7 @@
#include <iostream>
%}
/**** The PySequence C++ Wrap ***/
%insert(header) %{
@ -104,7 +105,13 @@ namespace std {
{
bool
operator()(PyObject * v, PyObject *w) const
{ return PyObject_Compare(v, w) < 0; }
{
bool res;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
res = PyObject_Compare(v, w) < 0;
SWIG_PYTHON_THREAD_END_BLOCK;
return res;
}
};
template <>
@ -112,7 +119,9 @@ namespace std {
{
bool
operator()(const swig::PyObject_ptr& v, const swig::PyObject_ptr& w) const
{ return PyObject_Compare(v, w) < 0; }
{
return std::less<PyObject *>()(v, w);
}
};
template <>
@ -120,7 +129,9 @@ namespace std {
{
bool
operator()(const swig::PyObject_var& v, const swig::PyObject_var& w) const
{ return PyObject_Compare(v, w) < 0; }
{
return std::less<PyObject *>()(v, w);
}
};
}
@ -262,10 +273,15 @@ namespace swig
{
%ignore stop_iteration;
%typemap(throws) stop_iteration {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetObject(PyExc_StopIteration, SWIG_Py_Void());
SWIG_PYTHON_THREAD_END_BLOCK;
SWIG_fail;
}
}
namespace swig {
%newobject PySequence_OutputIterator::operator +;
%newobject PySequence_OutputIterator::operator - (ptrdiff_t n) const;
@ -478,6 +494,7 @@ namespace swig
try {
return swig::as<T>(item, true);
} catch (std::exception& e) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
char msg[1024];
snprintf(msg, sizeof(msg), "in sequence element %d ", _index);
if (!PyErr_Occurred()) {
@ -485,6 +502,7 @@ namespace swig
}
SWIG_Python_AddErrorMsg(msg);
SWIG_Python_AddErrorMsg(e.what());
SWIG_PYTHON_THREAD_END_BLOCK;
throw;
}
}
@ -895,8 +913,11 @@ namespace swig
}
} catch (std::exception& e) {
if (seq) {
if (!PyErr_Occurred())
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
if (!PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, e.what());
}
SWIG_PYTHON_THREAD_END_BLOCK;
}
return 0;
}
@ -934,8 +955,10 @@ namespace swig
}
return obj;
} else {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"sequence size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
}

View file

@ -61,27 +61,35 @@ swig_varlink_dealloc(swig_varlinkobject *v) {
SWIGINTERN PyObject *
swig_varlink_getattr(swig_varlinkobject *v, char *n) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
swig_globalvar *var = v->vars;
while (var) {
if (strcmp(var->name,n) == 0) {
return (*var->get_attr)();
PyObject *obj = (*var->get_attr)();
SWIG_PYTHON_THREAD_END_BLOCK;
return obj;
}
var = var->next;
}
PyErr_SetString(PyExc_NameError,"Unknown C global variable");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
SWIGINTERN int
swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
swig_globalvar *var = v->vars;
while (var) {
if (strcmp(var->name,n) == 0) {
return (*var->set_attr)(p);
int res = (*var->set_attr)(p);
SWIG_PYTHON_THREAD_END_BLOCK;
return res;
}
var = var->next;
}
PyErr_SetString(PyExc_NameError,"Unknown C global variable");
SWIG_PYTHON_THREAD_END_BLOCK;
return 1;
}

View file

@ -43,7 +43,7 @@
/* Error manipulation */
#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code)
#define SWIG_Error(code, msg) PyErr_SetString(SWIG_Python_ErrorType(code), msg)
#define SWIG_Error(code, msg) {SWIG_PYTHON_THREAD_BEGIN_BLOCK; PyErr_SetString(SWIG_Python_ErrorType(code), msg); SWIG_PYTHON_THREAD_END_BLOCK; }
#define SWIG_fail goto fail
/*
@ -652,6 +652,7 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
if (pyobj && PySwigObject_Check(pyobj)) {
return (PySwigObject *) pyobj;
} else {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyObject *obj = 0;
#ifndef SWIG_PYTHON_SLOW_GETSET_THIS
if (PyInstance_Check(pyobj)) {
@ -669,16 +670,17 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
#else
obj = PyObject_GetAttr(pyobj,SWIG_This());
Py_XDECREF(obj);
#endif
#endif
if (!obj || PyErr_Occurred()) {
PyErr_Clear();
SWIG_PYTHON_THREAD_END_BLOCK;
return 0;
}
if (PySwigObject_Check(obj)) {
return (PySwigObject *)obj;
} else {
return 0;
}
if (!PySwigObject_Check(obj)) {
obj = 0;
}
SWIG_PYTHON_THREAD_END_BLOCK;
return (PySwigObject *)obj;
}
}
@ -836,7 +838,9 @@ SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
return SWIG_Py_Void();
} else if (!type) {
if (!PyErr_Occurred()) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj");
SWIG_PYTHON_THREAD_END_BLOCK;
}
return NULL;
} else {
@ -901,21 +905,27 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
{
PyObject *dict;
if (!PyModule_Check(m)) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError,
"PyModule_AddObject() needs module as first arg");
SWIG_PYTHON_THREAD_END_BLOCK;
return SWIG_ERROR;
}
if (!o) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError,
"PyModule_AddObject() needs non-NULL value");
SWIG_PYTHON_THREAD_END_BLOCK;
return SWIG_ERROR;
}
dict = PyModule_GetDict(m);
if (dict == NULL) {
/* Internal error -- modules must have a dict! */
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
PyModule_GetName(m));
SWIG_PYTHON_THREAD_END_BLOCK;
return SWIG_ERROR;
}
if (PyDict_SetItemString(dict, name, o))

View file

@ -34,6 +34,7 @@ PyString_FromFormat(const char *fmt, ...) {
%}
%insert(runtime) "swigrun.swg"; /* SWIG API */
%insert(runtime) "swigerrors.swg" /* SWIG errors */
%insert(runtime) "pythreads.swg"; /* Python thread code */
%insert(runtime) "pyapi.swg"; /* Pyton API */
%insert(runtime) "pyrun.swg"; /* Python run-time code */

72
Lib/python/pythreads.swg Normal file
View file

@ -0,0 +1,72 @@
#if !defined(SWIG_PYTHON_NO_THREADING)
# if !defined(SWIG_PYTHON_THREADING)
# define SWIG_PYTHON_THREADING
# endif
#else
# if defined(SWIG_PYTHON_THREADING)
# undef SWIG_PYTHON_THREADING
# endif
#endif
#if defined(SWIG_PYTHON_THREADING) /* Threading support is enabled */
# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL)
# if (PY_VERSION_HEX >= 0x02030000) /* For 2.3 or later, use the PyGILState calls */
# define SWIG_PYTHON_USE_GIL
# endif
# endif
# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */
# if !defined(SWIG_PYTHON_INITIALIZE_THREADING)
# define SWIG_PYTHON_INITIALIZE_THREADING PyEval_InitThreads()
# endif
# ifdef __cplusplus
class SWIG_Python_Thread_Block {
bool status;
PyGILState_STATE state;
public:
void begin() { if (!status) { state = PyGILState_Ensure(); status = true;} }
void end() { if (status) { PyGILState_Release(state); status = false;} }
SWIG_Python_Thread_Block() : status(false) { begin(); }
~SWIG_Python_Thread_Block() { end(); }
};
class SWIG_Python_Thread_Allow {
bool status;
PyThreadState *save;
public:
void begin() { if (!status) { status = true; save = PyEval_SaveThread(); }}
void end() { if (status) { PyEval_RestoreThread(save); status = false; }}
SWIG_Python_Thread_Allow() : status(false) { begin(); }
~SWIG_Python_Thread_Allow() { end(); }
};
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block
# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end()
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow
# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end()
# else /* C++ */
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_allow = PyGILState_Ensure()
# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_allow)
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW Py_BEGIN_ALLOW_THREADS
# define SWIG_PYTHON_THREAD_END_ALLOW Py_END_ALLOW_THREADS
# endif
# else /* Old thread way, not implemented, user must provide it */
# if !defined(SWIG_PYTHON_INITIALIZE_THREADING)
# define SWIG_PYTHON_INITIALIZE_THREADING
# endif
# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
# endif
# if !defined(SWIG_PYTHON_THREAD_END_BLOCK)
# define SWIG_PYTHON_THREAD_END_BLOCK
# endif
# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW)
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
# endif
# if !defined(SWIG_PYTHON_THREAD_END_ALLOW)
# define SWIG_PYTHON_THREAD_END_ALLOW
# endif
# endif
#else /* No thread support */
# define SWIG_PYTHON_INITIALIZE_THREADING
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
# define SWIG_PYTHON_THREAD_END_BLOCK
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
# define SWIG_PYTHON_THREAD_END_ALLOW
#endif

View file

@ -56,7 +56,9 @@
/* raise */
%define %raise(obj, type, desc)
PyObject *_obj = obj;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetObject(SWIG_Python_ExceptionType(desc), _obj);
SWIG_PYTHON_THREAD_END_BLOCK;
Py_DECREF(_obj);
SWIG_fail %enddef

View file

@ -2,11 +2,14 @@
* Special user directives
* ----------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------- */
/* shadow code */
#define %shadow %insert("shadow")
#define %pythoncode %insert("python")
/* ----------------------------------------------------------------------------- */
/*
Use the "nondynamic" feature to make a wrapped class behaves as a "nondynamic"
one, ie, a python class that doesn't dynamically add new attributes.
@ -47,6 +50,8 @@ so, it works with old python versions.
#define %clearpythonnondynamic %feature("python:nondynamic", "")
#define %pythondynamic %nopythonnondynamic
/* ----------------------------------------------------------------------------- */
/*
Use %pythonmaybecall to flag a method like __add__ or __radd__, which
@ -60,6 +65,7 @@ These methods "may be called" if needed.
#define %nopythonmaybecall %feature("python:maybecall", "0")
#define %clearpythonmaybecall %feature("python:maybecall", "")
/* ----------------------------------------------------------------------------- */
/*
The %pythoncallback feature produce a more natural callback wrap
than the %callback mechanism, ie, it use the original name for
@ -105,6 +111,7 @@ These methods "may be called" if needed.
#define %nopythoncallback %feature("python:callback","0")
#define %clearpythoncallback %feature("python:callback","")
/* ----------------------------------------------------------------------------- */
/*
Support for the old %callback directive name
*/
@ -124,3 +131,31 @@ These methods "may be called" if needed.
#define %nocallback %nopythoncallback
#define %clearcallback %clearpythoncallback
/* ----------------------------------------------------------------------------- */
/*
Thread support
*/
#define %threads %feature("threads")
#define %nothreads %feature("threads","0")
#define %clearthreads %feature("threads","")
#define %nothreadblock %feature("nothreadblock")
#define %threadblock %feature("nothreadblock","0")
#define %clearnothreadblock %feature("nothreadblock","")
#define %nothreadallow %feature("nothreadallow")
#define %threadallow %feature("nothreadallow","0")
#define %clearnothreadallow %feature("nothreadallow","")
/* ----------------------------------------------------------------------------- */
/*
Directors
*/
#define %director %feature("director")
#define %nodirector %feature("director","0")
#define %cleardirector %feature("director","")

View file

@ -30,7 +30,9 @@ SWIG_AsPtr(std::basic_string<char>)(PyObject* obj, std::string **val)
PyErr_Clear();
}
if (val) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError,"a string is expected");
SWIG_PYTHON_THREAD_END_BLOCK;
}
return 0;
}
@ -78,7 +80,9 @@ SWIGINTERN int
PyErr_Clear();
}
if (val) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError,"a wstring is expected");
SWIG_PYTHON_THREAD_END_BLOCK;
}
return 0;
}

View file

@ -25,7 +25,9 @@
::asptr(items, val);
}
if (val) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError, "a dictionary is expected");
SWIG_PYTHON_THREAD_END_BLOCK;
}
return 0;
}
@ -41,8 +43,10 @@
size_type size = map.size();
int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject *obj = PyDict_New();
@ -91,8 +95,10 @@
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject* keyList = PyList_New(pysize);
@ -107,8 +113,10 @@
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject* valList = PyTuple_New(pysize);
@ -123,8 +131,10 @@
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject* itemList = PyTuple_New(pysize);
@ -144,8 +154,10 @@
Map::size_type size = self->size();
int pysize = (size <= (Map::size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"map size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject* keyTuple = PyTuple_New(pysize);

View file

@ -25,7 +25,9 @@
::asptr(items, val);
}
if (val) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_TypeError, "a dictionary is expected");
SWIG_PYTHON_THREAD_END_BLOCK;
}
return 0;
}
@ -41,8 +43,10 @@
size_type size = multimap.size();
int pysize = (size <= (size_type) INT_MAX) ? (int) size : -1;
if (pysize < 0) {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyErr_SetString(PyExc_OverflowError,
"multimap size not valid in python");
SWIG_PYTHON_THREAD_END_BLOCK;
return NULL;
}
PyObject *obj = PyDict_New();