File: callback_in_thread.c

package info (click to toggle)
pypy3 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,848 kB
  • sloc: python: 1,291,746; ansic: 74,281; asm: 5,187; cpp: 3,017; sh: 2,533; makefile: 544; xml: 243; lisp: 45; csh: 21; awk: 4
file content (89 lines) | stat: -rw-r--r-- 2,750 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/* A test module that spawns a thread and run a function there */

#include <Python.h>
#include <pthread.h>

struct thread_data {
    PyInterpreterState *interp;
    PyObject *callback;
};

static void *thread_function(void* ptr) {
    struct thread_data *data = (struct thread_data *)ptr;
    PyInterpreterState *interp = data->interp;
    /* Assuming you have access to an interpreter object, the typical
     * idiom for calling into Python from a C thread is: */

    PyThreadState *tstate;
    PyObject *result;

    /* interp is your reference to an interpreter object. */
    tstate = PyThreadState_New(interp);
    PyEval_AcquireThread(tstate);

    /* Perform Python actions here.  */
    result = PyObject_CallFunction(data->callback,
				   "l", (long)pthread_self());
    if (!result)
	PyErr_Print();
    else
	Py_DECREF(result);

    Py_DECREF(data->callback);

    /* XXX Python examples don't mention it, but docs say that
     * PyThreadState_Delete requires it. */
    PyThreadState_Clear(tstate);

    /* Release the thread. No Python API allowed beyond this point. */
    PyEval_ReleaseThread(tstate);

    /* You can either delete the thread state, or save it
       until you need it the next time. */
    PyThreadState_Delete(tstate);

    free(data);
    return NULL;
}

static PyObject *
run_callback(PyObject *self, PyObject *callback)
{
    pthread_t thread;
    struct thread_data *data = malloc(sizeof(struct thread_data));
    Py_INCREF(callback);
    data->interp = PyThreadState_Get()->interp;
    data->callback = callback;
    pthread_create(&thread, NULL, thread_function, (void*)data);
    Py_RETURN_NONE;
}


static PyMethodDef module_functions[] = {
    {"callInThread", (PyCFunction)run_callback, METH_O, NULL},
    {NULL,        NULL}    /* Sentinel */
};

#ifdef __GNUC__
extern __attribute__((visibility("default")))
#else
extern __declspec(dllexport)
#endif

PyMODINIT_FUNC
initcallback_in_thread(void)
{
    PyObject *m;
    m = Py_InitModule("callback_in_thread", module_functions);
    if (m == NULL)
        return;
    PyEval_InitThreads();
}

/* 
cc -g -O0 -c callback_in_thread.c -I /usr/include/python2.6 -fPIC && ld -g -O0 callback_in_thread.o --shared -o callback_in_thread.so && gdb --args ~/python/cpython2.7/python -c "from __future__ import print_function; import threading, time; from callback_in_thread import callInThread; callInThread(print); time.sleep(1)"


cc -g -O0 -c callback_in_thread.c -I ~/pypy/pypy/include -fPIC && ld -g -O0 callback_in_thread.o --shared -o callback_in_thread.pypy-19.so && gdb --args ~/pypy/pypy/pypy/pypy-c -c "from __future__ import print_function; import threading, time; from callback_in_thread import callInThread; callInThread(print); time.sleep(1)"

 */