fixed python async mode with the improved api

This commit is contained in:
Unbit
2013-04-25 14:28:38 +02:00
parent 4e865c4525
commit bbad505044
3 changed files with 54 additions and 22 deletions
+46 -21
View File
@@ -2,6 +2,7 @@
#include <greenlet/greenlet.h>
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct ugreenlet {
int enabled;
@@ -10,15 +11,22 @@ struct ugreenlet {
PyGreenlet **gl;
} ugl;
struct uwsgi_option greenlet_options[] = {
static struct uwsgi_option greenlet_options[] = {
{"greenlet", no_argument, 0, "enable greenlet as suspend engine", uwsgi_opt_true, &ugl.enabled, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
static void gil_greenlet_get() {
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
}
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
static void gil_greenlet_release() {
PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key));
}
static PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
async_schedule_to_req_green();
Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]);
@@ -28,45 +36,66 @@ PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
PyMethodDef uwsgi_greenlet_request_method[] = {{"uwsgi_greenlet_request", py_uwsgi_greenlet_request, METH_VARARGS, ""}};
static inline void greenlet_schedule_to_req() {
static void greenlet_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
uint8_t modifier1 = uwsgi.wsgi_req->uh->modifier1;
// ensure gil
UWSGI_GET_GIL
if (!uwsgi.wsgi_req->suspended) {
ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL);
uwsgi.wsgi_req->suspended = 1;
}
// call it in the main core
if (uwsgi.p[modifier1]->suspend) {
uwsgi.p[modifier1]->suspend(NULL);
}
PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
if (uwsgi.p[modifier1]->resume) {
uwsgi.p[modifier1]->resume(NULL);
}
}
static inline void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
// ensure gil
UWSGI_GET_GIL
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
}
PyGreenlet_Switch(ugl.main, NULL, NULL);
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
}
uwsgi.wsgi_req = wsgi_req;
}
static int greenlet_init() {
return 0;
}
static void greenlet_init_apps(void) {
if (!ugl.enabled) {
return;
}
if (!ugl.enabled) return;
if (uwsgi.async <= 1) {
uwsgi_log("the greenlet loop engine requires async mode\n");
uwsgi_log("the greenlet suspend engine requires async mode\n");
exit(1);
}
if (uwsgi.has_threads) {
up.gil_get = gil_greenlet_get;
up.gil_release = gil_greenlet_release;
}
// blindy call it as the stackless gil engine is already set
UWSGI_GET_GIL
PyGreenlet_Import();
@@ -77,15 +106,11 @@ static void greenlet_init_apps(void) {
uwsgi.schedule_to_main = greenlet_schedule_to_main;
uwsgi.schedule_to_req = greenlet_schedule_to_req;
return;
}
struct uwsgi_plugin greenlet_plugin = {
.name = "greenlet",
.init = greenlet_init,
.init_apps = greenlet_init_apps,
.options = greenlet_options,
};
+3 -1
View File
@@ -293,8 +293,9 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
struct uwsgi_app *wi;
if (wsgi_req->async_status == UWSGI_AGAIN) {
if (wsgi_req->async_force_again) {
wi = &uwsgi_apps[wsgi_req->app_id];
wsgi_req->async_force_again = 0;
UWSGI_GET_GIL
// get rid of timeout
if (wsgi_req->async_timed_out) {
@@ -388,6 +389,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
while (wi->response_subhandler(wsgi_req) != UWSGI_OK) {
if (uwsgi.async > 1) {
UWSGI_RELEASE_GIL
wsgi_req->async_force_again = 1;
return UWSGI_AGAIN;
}
else {
+5
View File
@@ -84,6 +84,11 @@ static void stackless_init_apps(void) {
if (!usl.enabled) return;
if (uwsgi.async <= 1) {
uwsgi_log("the stackless suspend engine requires async mode\n");
exit(1);
}
if (uwsgi.has_threads) {
up.gil_get = gil_stackless_get;
up.gil_release = gil_stackless_release;