Anonymous avatar Anonymous committed afd99f0

native condition

Comments (0)

Files changed (4)

cherrypy/__init__.py

     _console_control_handler.subscribe()
     del win32
 except ImportError:
-    engine = process.bus
+    try:
+        from cherrypy.process import unix
+        engine = unix.UnixBus()
+        del unix
+    except ImportError:
+        engine = process.bus
 
 
 # Timeout monitor

cherrypy/process/unix.py

+from unix_threading import NativeEvent
+from cherrypy.process import wspbus
+
+class UnixBus(wspbus.Bus):
+    def __init__(self):
+        self.events = {}
+        wspbus.Bus.__init__(self)
+
+    def _get_state_event(self, state):
+        try:
+            return self.events[state]
+        except KeyError:
+            event = NativeEvent()
+            self.events[state] = event
+            return event
+    
+    def _get_state(self):
+        return self._state
+    def _set_state(self, value):
+        self._state = value
+        event = self._get_state_event(value)
+        event.set()
+        event.clear()
+    state = property(_get_state, _set_state)
+    
+    def wait(self, state, interval=0.1):
+        # Don't wait for an event that beat us to the punch ;)
+        if self.state != state:
+            event = self._get_state_event(state)
+            event.wait()
+

cherrypy/process/unix_threading/__init__.py

+import threading
+from unix_threading import _pthread_cond
+
+class NativeEvent(threading._Event):
+    def __init__(self):
+        threading._Event.__init__(self)
+        self.__cond = _pthread_cond.Condition()
+

cherrypy/process/unix_threading/_pthread_cond.c

+#include "Python.h"
+#include "pthread.h"
+#include "structmember.h"
+
+
+typedef struct {
+  PyObject_HEAD
+  int set;
+  pthread_cond_t cond;
+  pthread_mutex_t lock;
+} ConditionObject;
+
+
+static int cond_init( ConditionObject* self, PyObject* args, PyObject* kwargs );
+static void cond_free( ConditionObject* self );
+static PyObject* cond_acquire( ConditionObject* self );
+static PyObject* cond_release( ConditionObject* self );
+static PyObject* cond_wait( ConditionObject* self, PyObject* args );
+static PyObject* cond_notify( ConditionObject* self );
+static PyObject* cond_notifyAll( ConditionObject* self );
+
+static PyMemberDef cond_members[] = { 
+  {NULL} 
+};
+
+static PyMethodDef cond_methods[] = {
+  { "acquire", (PyCFunction)cond_acquire, METH_NOARGS, "" },
+  { "release", (PyCFunction)cond_release, METH_NOARGS, "" },
+  { "wait", (PyCFunction)cond_wait, METH_VARARGS, "" },
+  { "notify", (PyCFunction)cond_notify, METH_NOARGS, "" },
+  { "notifyAll", (PyCFunction)cond_notifyAll, METH_NOARGS, "" },
+  { NULL }
+};
+
+static PyTypeObject ConditionType  = {
+  PyObject_HEAD_INIT(NULL)
+  0,                         /*ob_size*/
+  "_pthread_cond.Condition", /*tp_name*/
+  sizeof(ConditionObject),   /*tp_basicsize*/
+  0,                         /*tp_itemsize*/
+  (destructor)cond_free,     /*tp_dealloc*/
+  0,                         /*tp_print*/
+  0,                         /*tp_getattr*/
+  0,                         /*tp_setattr*/
+  0,                         /*tp_compare*/
+  0,                         /*tp_repr*/
+  0,                         /*tp_as_number*/
+  0,                         /*tp_as_sequence*/
+  0,                         /*tp_as_mapping*/
+  0,                         /*tp_hash */
+  0,                         /*tp_call*/
+  0,                         /*tp_str*/
+  0,                         /*tp_getattro*/
+  0,                         /*tp_setattro*/
+  0,                         /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,        /*tp_flags*/
+  "",                        /* tp_doc */
+  0,		               /* tp_traverse */
+  0,		               /* tp_clear */
+  0,		               /* tp_richcompare */
+  0,		               /* tp_weaklistoffset */
+  0,		               /* tp_iter */
+  0,		               /* tp_iternext */
+  cond_methods,              /* tp_methods */
+  cond_members,              /* tp_members */
+  0,                         /* tp_getset */
+  0,                         /* tp_base */
+  0,                         /* tp_dict */
+  0,                         /* tp_descr_get */
+  0,                         /* tp_descr_set */
+  0,                         /* tp_dictoffset */
+  (initproc)cond_init,       /* tp_init */
+  0,                         /* tp_alloc */
+  0,                         /* tp_new */
+};
+
+static int cond_init( ConditionObject* self, PyObject* args, PyObject* kwargs ) {
+  self->set = 0;
+  int err = pthread_mutex_init( &self->lock, NULL );
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return -1;
+  }
+  err = pthread_cond_init( &self->cond, NULL );
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return -1;
+  }
+  return 0;
+}
+
+static void cond_free( ConditionObject* self ) {
+  pthread_mutex_destroy( &self->lock );
+  pthread_cond_destroy( &self->cond );
+}
+
+static PyObject* cond_acquire( ConditionObject* self ) {
+  int err = 0;
+  Py_BEGIN_ALLOW_THREADS;
+  err = pthread_mutex_lock( &self->lock );
+  Py_END_ALLOW_THREADS;
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* cond_release( ConditionObject* self ) {
+  int err = pthread_mutex_unlock( &self->lock );
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* cond_wait( ConditionObject* self, PyObject* args ) {
+  // for now timed waits are not supported (it's ignored)
+  int err = 0;
+  while( !self->set && err != EINVAL ) {
+    Py_BEGIN_ALLOW_THREADS;
+    err = pthread_cond_wait( &self->cond, &self->lock );
+    Py_END_ALLOW_THREADS;
+  }
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* cond_notify( ConditionObject* self ) {
+  self->set = 1;
+  int err = 0; 
+  Py_BEGIN_ALLOW_THREADS;
+  err = pthread_cond_signal( &self->cond );
+  Py_END_ALLOW_THREADS;
+  self->set = 0;
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyObject* cond_notifyAll( ConditionObject* self ) {
+  self->set = 1;
+  int err = 0; 
+  Py_BEGIN_ALLOW_THREADS;
+  err = pthread_cond_broadcast( &self->cond );
+  Py_END_ALLOW_THREADS;
+  self->set = 0;
+  if( err != 0 ) {
+    PyErr_SetFromErrno( PyExc_OSError );
+    return NULL;
+  }
+  Py_RETURN_NONE;
+}
+
+static PyMethodDef module_methods[] = {
+  {NULL}
+};
+
+PyMODINIT_FUNC
+init_pthread_cond(void)
+{
+  ConditionType.tp_new = PyType_GenericNew;
+  if( PyType_Ready( &ConditionType ) < 0 ) {
+    return;
+  }
+  PyObject* mod = Py_InitModule( "_pthread_cond", module_methods );
+  if( mod == NULL ) {
+    return;
+  }
+  Py_INCREF( &ConditionType );
+  PyModule_AddObject( mod, "Condition", (PyObject*)&ConditionType );
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.