ยปCore Development>Code coverage>Mac/Modules/autoGIL.c

Python code coverage for Mac/Modules/autoGIL.c

#countcontent
1n/a#include "Python.h"
2n/a#include <CoreFoundation/CFRunLoop.h>
3n/a
4n/a/* These macros are defined in Python 2.3 but not 2.2 */
5n/a#ifndef PyMODINIT_FUNC
6n/a#define PyMODINIT_FUNC void
7n/a#endif
8n/a#ifndef PyDoc_STRVAR
9n/a#define PyDoc_STRVAR(Var,Str) static char Var[] = Str
10n/a#endif
11n/a
12n/a
13n/a#undef AUTOGIL_DEBUG
14n/a
15n/astatic PyObject *AutoGILError;
16n/a
17n/a
18n/astatic void autoGILCallback(CFRunLoopObserverRef observer,
19n/a CFRunLoopActivity activity,
20n/a void *info) {
21n/a PyThreadState **p_tstate = (PyThreadState **)info;
22n/a
23n/a switch (activity) {
24n/a case kCFRunLoopBeforeWaiting:
25n/a /* going to sleep, release GIL */
26n/a#ifdef AUTOGIL_DEBUG
27n/a fprintf(stderr, "going to sleep, release GIL\n");
28n/a#endif
29n/a *p_tstate = PyEval_SaveThread();
30n/a break;
31n/a case kCFRunLoopAfterWaiting:
32n/a /* waking up, acquire GIL */
33n/a#ifdef AUTOGIL_DEBUG
34n/a fprintf(stderr, "waking up, acquire GIL\n");
35n/a#endif
36n/a PyEval_RestoreThread(*p_tstate);
37n/a *p_tstate = NULL;
38n/a break;
39n/a default:
40n/a break;
41n/a }
42n/a}
43n/a
44n/astatic void infoRelease(const void *info) {
45n/a /* XXX This should get called when the run loop is deallocated,
46n/a but this doesn't seem to happen. So for now: leak. */
47n/a PyMem_Free((void *)info);
48n/a}
49n/a
50n/astatic PyObject *
51n/aautoGIL_installAutoGIL(PyObject *self)
52n/a{
53n/a PyObject *tstate_dict = PyThreadState_GetDict();
54n/a PyObject *v;
55n/a CFRunLoopRef rl;
56n/a PyThreadState **p_tstate; /* for use in the info field */
57n/a CFRunLoopObserverContext context = {0, NULL, NULL, NULL, NULL};
58n/a CFRunLoopObserverRef observer;
59n/a
60n/a if (tstate_dict == NULL)
61n/a return NULL;
62n/a v = PyDict_GetItemString(tstate_dict, "autoGIL.InstalledAutoGIL");
63n/a if (v != NULL) {
64n/a /* we've already installed a callback for this thread */
65n/a Py_INCREF(Py_None);
66n/a return Py_None;
67n/a }
68n/a
69n/a rl = CFRunLoopGetCurrent();
70n/a if (rl == NULL) {
71n/a PyErr_SetString(AutoGILError,
72n/a "can't get run loop for current thread");
73n/a return NULL;
74n/a }
75n/a
76n/a p_tstate = PyMem_Malloc(sizeof(PyThreadState *));
77n/a if (p_tstate == NULL) {
78n/a PyErr_SetString(PyExc_MemoryError,
79n/a "not enough memory to allocate "
80n/a "tstate pointer");
81n/a return NULL;
82n/a }
83n/a *p_tstate = NULL;
84n/a context.info = (void *)p_tstate;
85n/a context.release = infoRelease;
86n/a
87n/a observer = CFRunLoopObserverCreate(
88n/a NULL,
89n/a kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting,
90n/a 1, 0, autoGILCallback, &context);
91n/a if (observer == NULL) {
92n/a PyErr_SetString(AutoGILError,
93n/a "can't create event loop observer");
94n/a return NULL;
95n/a }
96n/a CFRunLoopAddObserver(rl, observer, kCFRunLoopDefaultMode);
97n/a /* XXX how to check for errors? */
98n/a
99n/a /* register that we have installed a callback for this thread */
100n/a if (PyDict_SetItemString(tstate_dict, "autoGIL.InstalledAutoGIL",
101n/a Py_None) < 0)
102n/a return NULL;
103n/a
104n/a Py_INCREF(Py_None);
105n/a return Py_None;
106n/a}
107n/a
108n/aPyDoc_STRVAR(autoGIL_installAutoGIL_doc,
109n/a"installAutoGIL() -> None\n\
110n/aInstall an observer callback in the event loop (CFRunLoop) for the\n\
111n/acurrent thread, that will lock and unlock the Global Interpreter Lock\n\
112n/a(GIL) at appropriate times, allowing other Python threads to run while\n\
113n/athe event loop is idle."
114n/a);
115n/a
116n/astatic PyMethodDef autoGIL_methods[] = {
117n/a {
118n/a "installAutoGIL",
119n/a (PyCFunction)autoGIL_installAutoGIL,
120n/a METH_NOARGS,
121n/a autoGIL_installAutoGIL_doc
122n/a },
123n/a { 0, 0, 0, 0 } /* sentinel */
124n/a};
125n/a
126n/aPyDoc_STRVAR(autoGIL_docs,
127n/a"The autoGIL module provides a function (installAutoGIL) that\n\
128n/aautomatically locks and unlocks Python's Global Interpreter Lock\n\
129n/awhen running an event loop."
130n/a);
131n/a
132n/aPyMODINIT_FUNC
133n/ainitautoGIL(void)
134n/a{
135n/a PyObject *mod;
136n/a
137n/a if (PyErr_WarnPy3k("In 3.x, the autoGIL module is removed.", 1) < 0)
138n/a return;
139n/a
140n/a mod = Py_InitModule4("autoGIL", autoGIL_methods, autoGIL_docs,
141n/a NULL, PYTHON_API_VERSION);
142n/a if (mod == NULL)
143n/a return;
144n/a AutoGILError = PyErr_NewException("autoGIL.AutoGILError",
145n/a PyExc_Exception, NULL);
146n/a if (AutoGILError == NULL)
147n/a return;
148n/a Py_INCREF(AutoGILError);
149n/a if (PyModule_AddObject(mod, "AutoGILError",
150n/a AutoGILError) < 0)
151n/a return;
152n/a}