On Feb 3, 2009, at 12:51 PM, Victor Lin wrote:


It seems that my program can't call to Python's function from thread
directly, because there is Global Interpreter Lock. The python's GIL
is so complex, I have no idea how it works. I'm sorry, what I can do
is to ask. My question is. What should I do before and after I call a
Python function from threads?


Hi Victor,
I asked a similar question yesterday and have gotten no response yet -- I hope you'll have better luck. I'm writing a C extension that wants to implement a callback in a new thread. Here's what I think I've learned from reading the threads API doc. Please note that this is a classic case of the blind leading the blind! I'm sure some (most? all?) of the ideas below are wrong, but I'm hoping that thinking through some of this "out loud" will help both of us. Or maybe some more knowledgeable person will take pity on/be appalled by my ignorance and come to our rescue. =)

Python's infamous GIL doesn't exist when a program is single-threaded. Before a new thread is created, the main thread must call PyEval_InitThreads() to create the GIL. However, "It is not safe to call this function when it is unknown which thread (if any) currently has the global interpreter lock." Therefore my extension must do this:

i_have_the_gil = 0;
if (!PyEval_ThreadsInitialized()) {
   PyEval_InitThreads();
/* "...when this function initializes the lock, it also acquires it." */
   i_have_the_gil = 1;
}

That ensures that the GIL is created.

My extension will be calling from a newly-created C thread. The *Python* thread doesn't exist yet; so next I have to create it. Therefore --

if (!i_have_the_gil)
   PyEval_AcquireLock();

// Might not actually be the main thread but conceptually
// it is OK to assume so here.
main_thread = PyThreadState_Get();

callback_thread = PyThreadState_New(main_thread->interp);

PyThreadState_Swap(callback_thread);

gstate = PyGILState_Ensure();

call_callback_function();

// Now unwind the above

PyGILState_Release(gstate);

PyThreadState_Swap(main_thread);

PyThreadState_Clear(callback_thread);

PyThreadState_Delete(callback_thread);

PyEval_ReleaseLock();


I haven't yet tested this! But hopefully it is the right idea and just needs a little fine tuning.

I found this discussion useful:
http://mail.python.org/pipermail/python-list/2006-November/413088.html

It includes the quote, "The current thread state API doc, as you read it from top to bottom now, is in fact totally confusing for anyone who didn't develop Python himself"

I like! =)

Cheers
Philip



--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to