Embeded Multi-Threaded Python: PyEval_InitThread(), PyEval_SaveThread(),...
Frederic Giacometti
frederic.giacometti at arakne.com
Thu Sep 20 00:49:24 EDT 2001
"Nicolas Duchastel" <nicolas at otelnet.com> wrote in message
news:8e0ac4fb.0109191313.5fef1454 at posting.google.com...
> Thanks for the quick response.... but.....
>
> I actually RTFM-ed it; that's why my question is so detailed.
CYSPE ?? (Translation: Can you speak English ?)
What is this funky RTFM verb ???
> The doc seem to be conflicting in some areas and lacks some important
> information.
>
> For example, Chapter 8 states that Py_Initialized() can be called
> before or after PyEval_InitThreads(); so which is best ? what are the
> implications ? any nuance between these two ways ? any examples ?
This is not conflicting, it just states the order dones not matter; which is
true.
What's missing in the documentation is the indication that
PyEval_InitThreads() creates and initialize the global lock; and thus must
have been called before any real thread operation is engaged.
The code of PyEval_InitThreads is only a couple of lines long. Looking at it
might help you, too.
> Also, chapter 8.1 does indicated 4 different ways to do locking:
> C_Function_ToCallPythonCode()
> {
> PyThreadState* save = PyEval_SaveThread(); // LOCK
> PyImport_ImportModule( ...); // load another module
> PyRun_SimpleString(...); // execute a 1 line of Python code
> PyPObject_CallMethod(....); // execute a full Python method
> PyEval_RestoreThread(save); // UNLOCK
But they don't refer to the same locks.... For instance, there is a global
interpreter lock, and an import lock; these are two different locks.
So, yes, you're locking, but you're not locking the same thing. Not all
locks are the same, you know :))
> }
> OR
> C_Function_ToCallPythonCode()
> {
> PyEval_AcquireLock(); // LOCK
> PyImport_ImportModule( ...); // load another module
> PyRun_SimpleString(...); // execute a 1 line of Python code
> PyPObject_CallMethod(....); // execute a full Python method
> PyEval_ReleaseLock(); // UNLOCK
> }
> OR
> C_Function_ToCallPythonCode()
> {
> PyEval_AcquireThread(??); // LOCK
> PyImport_ImportModule( ...); // load another module
> PyRun_SimpleString(...); // execute a 1 line of Python code
> PyPObject_CallMethod(....); // execute a full Python method
> PyEval_ReleaseThread(??); // UNLOCK
There are two global interpreter lock/thread function/macro sets: one which
is source-compatible with single-threaded Python builds, and another one
which is not.
In addition to this, PyEval_InitThread() does some acrobaties to dynamically
enable/disable thread on python extension modules, so that the same module
can work on mutli-threaded and single-threaded python engine; non of this
being actually documented, of course :))
As resultat des courses, when you invoke binary extensions from the 'python'
command, the PyEval_InitThread() is only executed upon loading a module
requiring threads (e.g. the threads module).
If you create your own binary module which might work on its own thread,
you'll also want to insert a PyEval_InitThread() call in the module
initialisation function.
Voila...
> }
> OR
> C_Function_ToCallPythonCode()
> {
> Py_BEGIN_ALLOW_THREADS
> PyImport_ImportModule( ...); // load another module
> PyRun_SimpleString(...); // execute a 1 line of Python code
> PyPObject_CallMethod(....); // execute a full Python method
> Py_END_ALLOW_THREADS
> }
>
> So which one should I use ?
You should use the macros, preferably to explicit function calls, whenever
you can...
> Also, image my 2 distinct thread B and C executing the 1st snipplet of
> code above, if the call to PyObject_CallMethod() is VERY long and
> takes ages,...
Python takes care of it, don't worry :)))
> chapter 8 says
>
> "In order to support multi-threaded Python programs, the
> interpreter regularly releases and reacquires the lock --
> by default, every ten bytecode instructions."
>
> Does that thus mean that a 2nd thread running this 1st snipplet
> above will be interupted in the middle of its work in
> PyObject_CallMethod() and another thread will have a go at it.
That's what thread switching is about, doesn't it ?
> If so, what happens to the ThreadState object when the 2nd thread
> calls PyEval_SaveThread() ? if it doesn't swap it, it will run with
> the 1st thread's ThreadState object. If it does swap it, when this
> 2nd thread will also get interupted, won't the 1st thread get back
> to run and thus it will run with the 2nd thread's object !?
> I mean, I must be missing someting !?
No (or maybe a little imagination :)): Just think of the Python virtual
machine as a single process ressource shared between the native threads.
> Also, what about the things I was asking with regards to the actual OS
> thread's ID ? i.e. does it matter that my code starts in one thread
> and then works from another thread ? do I need to create ThreadState
> objects for each threads ?
?????
> Thus,.. please RTFP (where P is for Posting rather than Manual)
Qu'es aqueo ????
>
> Thanks,
De rien.
> Nicolas
FG
More information about the Python-list
mailing list