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