I have a built-in Python program that runs in a stream in C.
When the Python interpreter switches the context of the thread (giving control to another thread), I would like to receive a notification in order to perform some necessary operations.
Py_AddPendingCall seems to be exactly what I'm looking for. However, the API docs are pretty brief about this function, and I'm confused about how it is supposed to use Py_AddPendingCall . I am reading documents, I understand that:
- The worker thread calls
Py_AddPendingCall and the handler assigns the function. - When the Python interpreter starts, it calls the handler function when it gives control to another thread.
- The handler itself is executed in the main interpreter thread, with GIL acquired
I googled around, for example, code showing how to use Py_AddPendingCall , but I can not find anything. My own attempt to use it just doesn't work. The handler just does not get called.
My working thread code:
#include <pthread.h> #include <stdlib.h> #include <stdio.h> const char* PYTHON_CODE = "while True:\n" " for i in range(0,10): print(i)\n" "\n"; int handler(void* arg) { printf("Pending Call invoked!\n"); abort(); } void* worker_thread(void*) { PyGILState_STATE state = PyGILState_Ensure(); int res = Py_AddPendingCall(&func, nullptr); cout << "Result: " << res << endl; PyRun_SimpleString(CODE); PyGILState_Release(state); return 0; } int main() { Py_Initialize(); PyEval_InitThreads(); PyEval_ReleaseLock(); pthread_t threads[4]; for (int i = 0; i < 4; ++i) pthread_create(&threads[i], 0, worker_thread, 0); for (int i = 0; i < 4; ++i) pthread_join(threads[i], 0); Py_Finalize(); }
In this example, worker_thread is called in C as the pthread worker thread. In this test, I run 4 worker threads, so some context switching should happen. This loop is infinite, but the pending call handler is never called.
So, can anyone provide a minimal working example that shows how to use Py_AddPendingCall ?
source share