simplify the thread implementation, use feature 'nothread' to disable threads instead of 'thread' to enable them, plus other fixes around threads
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7933 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
d35515351b
commit
2eeef5275d
6 changed files with 62 additions and 101 deletions
|
|
@ -21,49 +21,32 @@ Version 1.3.28 (unreleased).
|
|||
1.- the module thread support is enable via the "threads" module
|
||||
option, ie
|
||||
|
||||
%module("threads"=1)
|
||||
|
||||
2.- For each method you want to add full thread support, you
|
||||
should use the "threads" feature, as in
|
||||
|
||||
%feature("threads") method;
|
||||
|
||||
or in the directive form
|
||||
|
||||
%threads method;
|
||||
|
||||
3.- Since threads is a feature, you can enable it for the
|
||||
entire interface as follow
|
||||
|
||||
%module("threads"=1)
|
||||
%threads;
|
||||
|
||||
4.- Equivalent to that, is the following swig option
|
||||
2.- Equivalent to that, is the following swig option
|
||||
|
||||
swig -threads -python ...
|
||||
|
||||
ie, swig enables thread support for the module and all
|
||||
the methods.
|
||||
ie, swig enables thread support for the module.
|
||||
|
||||
5.- You can partially disable thread support for each
|
||||
3.- You can partially disable thread support for a given
|
||||
method using:
|
||||
|
||||
%feature("nothreads") method;
|
||||
%feature("nothread") method;
|
||||
|
||||
also, you can disable sections of the thread support,
|
||||
for example
|
||||
|
||||
%feature("nothreadsblock") method;
|
||||
%feature("nothreadsallow") method;
|
||||
%feature("nothreadblock") method;
|
||||
%feature("nothreadallow") method;
|
||||
|
||||
the first disable the C++/python thread protection, and the
|
||||
second the python/C++ thread protection. See
|
||||
pythreads.swg for more information.
|
||||
the first disables the C++/python thread protection, and the
|
||||
second disables the python/C++ thread protection.
|
||||
|
||||
6.- The current thread support is based in the PyGIL
|
||||
4.- The current thread support is based in the PyGIL
|
||||
extension present in python version 2.3 or later, but
|
||||
you can provide the thread code for older versions by
|
||||
defining the macros described in pythreads.swg.
|
||||
defining the macros in pythreads.swg.
|
||||
|
||||
If you get a working implementation for older versions,
|
||||
please send us a patch.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ class Foo;
|
|||
extern "C" void* working(void* t);
|
||||
%}
|
||||
|
||||
%threads;
|
||||
%director Foo;
|
||||
|
||||
%inline {
|
||||
|
|
|
|||
|
|
@ -643,7 +643,6 @@ 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)) {
|
||||
|
|
@ -664,13 +663,11 @@ SWIG_Python_GetSwigThis(PyObject *pyobj)
|
|||
#endif
|
||||
if (!obj || PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||
return 0;
|
||||
}
|
||||
if (!PySwigObject_Check(obj)) {
|
||||
obj = 0;
|
||||
}
|
||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||
return (PySwigObject *)obj;
|
||||
}
|
||||
}
|
||||
|
|
@ -828,11 +825,9 @@ SWIG_Python_NewPointerObj(void *ptr, swig_type_info *type, int flags) {
|
|||
if (!ptr) {
|
||||
return SWIG_Py_Void();
|
||||
} else if (!type) {
|
||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||
if (!PyErr_Occurred()) {
|
||||
PyErr_SetString(PyExc_TypeError, "Swig: null type passed to NewPointerObj");
|
||||
}
|
||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||
return NULL;
|
||||
} else {
|
||||
int own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0;
|
||||
|
|
@ -872,7 +867,6 @@ void *SWIG_ReturnGlobalTypeList(void *);
|
|||
SWIGRUNTIME swig_module_info *
|
||||
SWIG_Python_GetModule(void) {
|
||||
static void *type_pointer = (void *)0;
|
||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||
/* first check if module already created */
|
||||
if (!type_pointer) {
|
||||
#ifdef SWIG_LINK_RUNTIME
|
||||
|
|
@ -886,7 +880,6 @@ SWIG_Python_GetModule(void) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||
return (swig_module_info *) type_pointer;
|
||||
}
|
||||
|
||||
|
|
@ -898,27 +891,21 @@ 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))
|
||||
|
|
|
|||
|
|
@ -1,24 +1,22 @@
|
|||
#if defined(SWIG_PYTHON_NO_THREADING)
|
||||
# if defined(SWIG_PYTHON_THREADING)
|
||||
# undef SWIG_PYTHON_THREADING
|
||||
#if defined(SWIG_PYTHON_NO_THREADS)
|
||||
# if defined(SWIG_PYTHON_THREADS)
|
||||
# undef SWIG_PYTHON_THREADS
|
||||
# endif
|
||||
#endif
|
||||
#if defined(SWIG_PYTHON_THREADING) /* Threading support is enabled */
|
||||
#if defined(SWIG_PYTHON_THREADS) /* 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
|
||||
# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads()
|
||||
# ifdef __cplusplus /* C++ code */
|
||||
class SWIG_Python_Thread_Block {
|
||||
bool status;
|
||||
PyGILState_STATE state;
|
||||
public:
|
||||
void begin() { if (!status) { state = PyGILState_Ensure(); status = true;} }
|
||||
public:
|
||||
void end() { if (status) { PyGILState_Release(state); status = false;} }
|
||||
SWIG_Python_Thread_Block() : status(false) { begin(); }
|
||||
~SWIG_Python_Thread_Block() { end(); }
|
||||
|
|
@ -26,8 +24,8 @@
|
|||
class SWIG_Python_Thread_Allow {
|
||||
bool status;
|
||||
PyThreadState *save;
|
||||
void begin() { if (!status) { status = true; save = PyEval_SaveThread(); } }
|
||||
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(); }
|
||||
|
|
@ -36,15 +34,15 @@
|
|||
# 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
|
||||
# else /* C code */
|
||||
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure()
|
||||
# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block)
|
||||
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread()
|
||||
# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow)
|
||||
# endif
|
||||
# else /* Old thread way, not implemented, user must provide it */
|
||||
# if !defined(SWIG_PYTHON_INITIALIZE_THREADING)
|
||||
# define SWIG_PYTHON_INITIALIZE_THREADING
|
||||
# if !defined(SWIG_PYTHON_INITIALIZE_THREADS)
|
||||
# define SWIG_PYTHON_INITIALIZE_THREADS
|
||||
# endif
|
||||
# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK)
|
||||
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
|
||||
|
|
@ -60,7 +58,7 @@
|
|||
# endif
|
||||
# endif
|
||||
#else /* No thread support */
|
||||
# define SWIG_PYTHON_INITIALIZE_THREADING
|
||||
# define SWIG_PYTHON_INITIALIZE_THREADS
|
||||
# define SWIG_PYTHON_THREAD_BEGIN_BLOCK
|
||||
# define SWIG_PYTHON_THREAD_END_BLOCK
|
||||
# define SWIG_PYTHON_THREAD_BEGIN_ALLOW
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
/* -------------------------------------------------------------------------
|
||||
* 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.
|
||||
|
|
@ -51,7 +51,7 @@ so, it works with old python versions.
|
|||
#define %pythondynamic %nopythonnondynamic
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
|
||||
Use %pythonmaybecall to flag a method like __add__ or __radd__, which
|
||||
|
|
@ -65,7 +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
|
||||
|
|
@ -111,7 +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
|
||||
*/
|
||||
|
|
@ -131,14 +131,15 @@ These methods "may be called" if needed.
|
|||
#define %nocallback %nopythoncallback
|
||||
#define %clearcallback %clearpythoncallback
|
||||
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
Thread support
|
||||
Thread support - Advance control
|
||||
|
||||
*/
|
||||
|
||||
#define %threads %feature("threads")
|
||||
#define %nothreads %feature("threads","0")
|
||||
#define %clearthreads %feature("threads","")
|
||||
#define %nothread %feature("nothread")
|
||||
#define %thread %feature("nothread","0")
|
||||
#define %clearnothread %feature("nothread","")
|
||||
|
||||
#define %nothreadblock %feature("nothreadblock")
|
||||
#define %threadblock %feature("nothreadblock","0")
|
||||
|
|
@ -149,7 +150,7 @@ These methods "may be called" if needed.
|
|||
#define %clearnothreadallow %feature("nothreadallow","")
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/*
|
||||
Directors
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ static String *real_classname;
|
|||
|
||||
/* Thread Support */
|
||||
static int threads = 0;
|
||||
static int nothreads = 0;
|
||||
|
||||
/* flags for the make_autodoc function */
|
||||
enum autodoc_t {
|
||||
|
|
@ -115,7 +116,7 @@ public:
|
|||
* ------------------------------------------------------------ */
|
||||
|
||||
int threads_enable(Node *n) const {
|
||||
return threads && GetFlagAttr(n, "feature:threads");
|
||||
return threads && !GetFlagAttr(n, "feature:nothread");
|
||||
}
|
||||
|
||||
int initialize_threads(String *f_init) {
|
||||
|
|
@ -124,7 +125,7 @@ public:
|
|||
}
|
||||
Printf(f_init,"\n");
|
||||
Printf(f_init,"/* Initialize threading */\n");
|
||||
Printf(f_init,"SWIG_PYTHON_INITIALIZE_THREADING;\n");
|
||||
Printf(f_init,"SWIG_PYTHON_INITIALIZE_THREADS;\n");
|
||||
|
||||
return SWIG_OK;
|
||||
}
|
||||
|
|
@ -133,9 +134,9 @@ public:
|
|||
if (!GetFlag(n, "feature:nothreadblock")) {
|
||||
String *bb = Getattr(n,"feature:threadbeginblock");
|
||||
if (bb) {
|
||||
Wrapper_add_local(f,"python_thread_state", bb);
|
||||
Append(f->code, bb);
|
||||
} else {
|
||||
Wrapper_add_local(f,"python_thread_state", "SWIG_PYTHON_THREAD_BEGIN_BLOCK");
|
||||
Append(f->code,"SWIG_PYTHON_THREAD_BEGIN_BLOCK;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -237,20 +238,11 @@ public:
|
|||
Preprocessor_define((DOH *) "SWIG_NORTTI", 0);
|
||||
Swig_mark_arg(i);
|
||||
} else if (strcmp(argv[i],"-threads") == 0) {
|
||||
Hash *features_hash = Swig_cparse_features();
|
||||
String *name = NewString("");
|
||||
String *fname = NewString("feature:threads");
|
||||
String *fvalue = NewString("1");
|
||||
Swig_feature_set(features_hash,name,0,fname,fvalue,0);
|
||||
threads = 1;
|
||||
Swig_mark_arg(i);
|
||||
Delete(name);
|
||||
Delete(fname);
|
||||
Delete(fvalue);
|
||||
} else if (strcmp(argv[i],"-nothreads") == 0) {
|
||||
/* Turn off thread suppor mode */
|
||||
threads = 0;
|
||||
Preprocessor_define((DOH *) "SWIG_PYTHON_NO_THREADING", 0);
|
||||
nothreads = 1;
|
||||
Swig_mark_arg(i);
|
||||
} else if (strcmp(argv[i],"-modern") == 0) {
|
||||
apply = 0;
|
||||
|
|
@ -375,8 +367,10 @@ public:
|
|||
Printf(f_runtime,"#define SWIG_DIRECTORS\n");
|
||||
}
|
||||
|
||||
if (threads) {
|
||||
Printf(f_runtime,"#define SWIG_PYTHON_THREADING\n");
|
||||
if (nothreads) {
|
||||
Printf(f_runtime,"#define SWIG_PYTHON_NO_THREADS\n");
|
||||
} else if (threads) {
|
||||
Printf(f_runtime,"#define SWIG_PYTHON_THREADS\n");
|
||||
}
|
||||
|
||||
/* Set module name */
|
||||
|
|
@ -1550,18 +1544,17 @@ public:
|
|||
Printf(f->code, " Swig::UnknownExceptionHandler dh;\n");
|
||||
} else {
|
||||
Printf(f->code, "{\n");
|
||||
if (allow_thread) thread_begin_allow(n, f);
|
||||
}
|
||||
|
||||
|
||||
if (allow_thread) thread_begin_allow(n, f);
|
||||
emit_action(n,f);
|
||||
if (allow_thread) thread_end_allow(n, f);
|
||||
|
||||
if (director_method) {
|
||||
Printf(f->code, "} catch (Swig::DirectorException&) {\n");
|
||||
Printf(f->code, " SWIG_fail;\n");
|
||||
Printf(f->code, "}\n");
|
||||
} else {
|
||||
if (allow_thread) thread_end_allow(n, f);
|
||||
Printf(f->code, "}\n");
|
||||
}
|
||||
|
||||
|
|
@ -3011,23 +3004,26 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
|
|||
}
|
||||
|
||||
int allow_thread = threads_enable(n);
|
||||
if (allow_thread) thread_begin_block(n, w);
|
||||
|
||||
|
||||
/* direct call to superclass if _up is set */
|
||||
Printf(w->code, "if (swig_get_up()) {\n");
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
if (pure_virtual) {
|
||||
Printf(w->code,
|
||||
"Swig::DirectorPureVirtualException::raise(\"%s.\");\n",Swig_method_call(super,l));
|
||||
} else {
|
||||
} else {
|
||||
if (allow_thread) thread_begin_allow(n, w);
|
||||
if (is_void) {
|
||||
Printf(w->code, "%s;\n", Swig_method_call(super,l));
|
||||
Printf(w->code, "return;\n");
|
||||
} else {
|
||||
Printf(w->code, "return %s;\n", Swig_method_call(super,l));
|
||||
}
|
||||
if (allow_thread) thread_end_allow(n, w);
|
||||
}
|
||||
Printf(w->code, "}\n");
|
||||
Printf(w->code, "} else {\n");
|
||||
|
||||
if (allow_thread) thread_begin_block(n, w);
|
||||
|
||||
|
||||
/* wrap complex arguments to PyObjects */
|
||||
Printv(w->code, wrap_args, NIL);
|
||||
|
|
@ -3040,13 +3036,11 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
|
|||
|
||||
|
||||
Printf(w->code, "if (!swig_get_self()) {\n");
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
Printf(w->code, " Swig::DirectorException::raise(\"'self' unitialized, maybe you forgot to call %s.__init__.\");\n", classname);
|
||||
Printf(w->code, "}\n");
|
||||
Wrapper_add_local(w, "method", "PyObject* method = 0");
|
||||
Printf(w->code, "method = swig_get_method(swig_method_index, swig_method_name);\n");
|
||||
Printf(w->code, "if (method == NULL) {\n");
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
Printf(w->code, " Swig::DirectorMethodException::raise(\"Method '%s.%s' doesn't exist\");\n", classname, pyname);
|
||||
Printf(w->code, "}\n");
|
||||
|
||||
|
|
@ -3072,18 +3066,15 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
|
|||
Printf(w->code, "if (result == NULL) {\n");
|
||||
Printf(w->code, " PyObject *error = PyErr_Occurred();\n");
|
||||
if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
Replaceall(tm, "$error", "error");
|
||||
Printv(w->code, Str(tm), "\n", NIL);
|
||||
} else {
|
||||
Printf(w->code, " if (error != NULL) {\n");
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
Printf(w->code, " Swig::DirectorMethodException::raise(\"Error detected when calling %s.%s\");\n",
|
||||
classname, pyname);
|
||||
Printf(w->code, " }\n");
|
||||
}
|
||||
Printf(w->code, "}\n");
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
Delete(tm);
|
||||
|
||||
/*
|
||||
|
|
@ -3170,6 +3161,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
|
|||
}
|
||||
|
||||
/* any existing helper functions to handle this? */
|
||||
if (allow_thread) thread_end_block(n, w);
|
||||
if (!is_void) {
|
||||
String* rettype = SwigType_str(return_type, 0);
|
||||
if (!SwigType_isreference(return_type)) {
|
||||
|
|
@ -3180,6 +3172,7 @@ int PYTHON::classDirectorMethod(Node *n, Node *parent, String *super) {
|
|||
Delete(rettype);
|
||||
}
|
||||
|
||||
Printf(w->code, "}\n");
|
||||
Printf(w->code, "}\n");
|
||||
|
||||
/* emit the director method */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue