Mercurial > pymonkey
changeset 66:b49180c39d0a
Pymonkey now handles the GIL properly so that Python code can run while JS code does.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Sun, 26 Jul 2009 15:06:19 -0700 |
parents | f89a582c1276 |
children | b5160c82be65 |
files | context.c function.c test_pymonkey.py utils.h |
diffstat | 4 files changed, 50 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/context.c Sun Jul 26 13:09:58 2009 -0700 +++ b/context.c Sun Jul 26 15:06:19 2009 -0700 @@ -42,6 +42,7 @@ static JSBool PYM_operationCallback(JSContext *cx) { + PYM_PyAutoEnsureGIL gil; PYM_JSContextObject *context = (PYM_JSContextObject *) JS_GetContextPrivate(cx); @@ -66,6 +67,8 @@ static void PYM_reportError(JSContext *cx, const char *message, JSErrorReport *report) { + PYM_PyAutoEnsureGIL gil; + // Convert JS warnings into Python warnings. if (JSREPORT_IS_WARNING(report->flags)) { if (report->filename) @@ -138,9 +141,14 @@ } jsval val; - if (!JS_GetUCProperty(self->cx, object->obj, - JS_GetStringChars(jsString), - JS_GetStringLength(jsString), &val)) { + JSBool result; + Py_BEGIN_ALLOW_THREADS; + result = JS_GetUCProperty(self->cx, object->obj, + JS_GetStringChars(jsString), + JS_GetStringLength(jsString), &val); + Py_END_ALLOW_THREADS; + + if (!result) { // TODO: Get the actual JS exception. Any exception that exists // here will probably still be pending on the JS context. PyErr_SetString(PYM_error, "Getting property failed."); @@ -195,8 +203,13 @@ JS_BeginRequest(self->cx); jsval rval; - if (!JS_EvaluateScript(self->cx, object->obj, source, sourceLen, - filename, lineNo, &rval)) { + JSBool result; + Py_BEGIN_ALLOW_THREADS; + result = JS_EvaluateScript(self->cx, object->obj, source, sourceLen, + filename, lineNo, &rval); + Py_END_ALLOW_THREADS; + + if (!result) { PYM_jsExceptionToPython(self); JS_EndRequest(self->cx); return NULL; @@ -266,8 +279,14 @@ // TODO: This assumes that a JSFunction * is actually a subclass of // a JSObject *, which may or may not be regarded as an implementation // detail. - if (!JS_CallFunction(self->cx, obj->obj, (JSFunction *) fun->base.obj, - argc, argv, &rval)) { + JSBool result; + Py_BEGIN_ALLOW_THREADS; + result = JS_CallFunction(self->cx, obj->obj, + (JSFunction *) fun->base.obj, + argc, argv, &rval); + Py_END_ALLOW_THREADS; + + if (!result) { PYM_jsExceptionToPython(self); return NULL; }
--- a/function.c Sun Jul 26 13:09:58 2009 -0700 +++ b/function.c Sun Jul 26 15:06:19 2009 -0700 @@ -52,6 +52,7 @@ static void PYM_finalizeFunctionHolder(JSContext *cx, JSObject *obj) { + PYM_PyAutoEnsureGIL gil; PyObject *callable; if (PYM_getHeldFunction(cx, obj, &callable)) Py_DECREF(callable); @@ -95,6 +96,7 @@ jsval *argv, jsval *rval) { + PYM_PyAutoEnsureGIL gil; jsval callee = JS_ARGV_CALLEE(argv); jsval functionHolder; if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(callee), 0, &functionHolder)) {
--- a/test_pymonkey.py Sun Jul 26 13:09:58 2009 -0700 +++ b/test_pymonkey.py Sun Jul 26 15:06:19 2009 -0700 @@ -1,6 +1,8 @@ import sys import unittest import weakref +import time +import threading import pymonkey @@ -38,12 +40,12 @@ obj = cx.new_object() cx.init_standard_classes(obj) - # TODO: This isn't a very good test; we need to actually - # set up a signal or launch a separate thread to call - # this method as though it were a watchdog to limit the - # amount of time the JS can run. However, Pymonkey doesn't - # yet handle the GIL properly so this isn't possible. - cx.trigger_operation_callback() + def watchdog(): + time.sleep(0.1) + cx.trigger_operation_callback() + + thread = threading.Thread(target = watchdog) + thread.start() self.assertRaises( pymonkey.error,
--- a/utils.h Sun Jul 26 13:09:58 2009 -0700 +++ b/utils.h Sun Jul 26 15:06:19 2009 -0700 @@ -43,6 +43,20 @@ #include <jsdhash.h> #include <Python/Python.h> +class PYM_PyAutoEnsureGIL { +public: + PYM_PyAutoEnsureGIL() { + state = PyGILState_Ensure(); + } + + ~PYM_PyAutoEnsureGIL() { + PyGILState_Release(state); + } + +protected: + PyGILState_STATE state; +}; + typedef struct { JSDHashEntryStub base; void *value;