changeset 1446:feb70913ce98

cdefer: Implemented Share in C.
author Marcel Keller <mkeller@cs.au.dk>
date Thu, 17 Jun 2010 17:38:32 +0200
parents efe63f85605a
children 2921ecae2a23
files viff/cdefer.c
diffstat 1 files changed, 344 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/viff/cdefer.c	Wed Jun 16 14:00:18 2010 +0200
+++ b/viff/cdefer.c	Thu Jun 17 17:38:32 2010 +0200
@@ -36,6 +36,12 @@
     } while (0)
 #endif
 
+/* be compatible with Python < 2.6 */
+
+#ifndef Py_TYPE
+#define Py_TYPE(ob)             (((PyObject*)(ob))->ob_type)
+#endif
+
 PyObject * failure_class = NULL;
 PyObject * already_called = NULL;
 PyObject * debuginfo_class = NULL;
@@ -225,10 +231,12 @@
 static int cdefer_Deferred___init__(cdefer_Deferred *self, PyObject *args,
                                     PyObject *kwargs)
 {
+    /*
     static char *argnames[] = {NULL};
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", argnames)) {
         return -1;
     }
+    */
     if (is_debug) {
         self->debuginfo = PyObject_CallObject(debuginfo_class, NULL);
         if (!self->debuginfo) {
@@ -835,6 +843,334 @@
     {NULL}  /* Sentinel */
 };
 
+/* VIFF */
+
+typedef struct {
+    cdefer_Deferred deferred;
+    PyObject *runtime;
+    PyObject *field;
+} cdefer_Share;
+
+static struct PyMemberDef cdefer_Share_members[] = {
+  {"runtime", T_OBJECT_EX, offsetof(cdefer_Share, runtime), 0, 0},
+  {"field", T_OBJECT_EX, offsetof(cdefer_Share, field), 0, 0},
+  {0, 0, 0, 0, 0}
+};
+
+static int cdefer_Share_init(cdefer_Share *self, PyObject *args,
+			     PyObject *kwargs)
+{
+    PyObject *runtime, *field, *value = NULL;
+    PyObject *result, *tmp;
+    static char *argnames[] = {"runtime", "field", "value", NULL};
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O", argnames,
+				     &runtime, &field, &value))
+        return -1;
+
+    if (field == Py_None) {
+	PyErr_SetString(PyExc_AssertionError,
+			"Cannot construct share without a field.");
+	return -1;
+    }
+
+    if (!PyCallable_Check(field)) {
+	PyErr_SetString(PyExc_AssertionError,
+			"The field is not callable, wrong argument?");
+	return -1;
+    }
+
+    Py_INCREF(Py_None);
+    if (cdefer_Deferred___init__(&self->deferred, Py_None, Py_None) < 0)
+	return -1;
+    Py_DECREF(Py_None);
+
+    tmp = self->runtime;
+    Py_INCREF(runtime);
+    self->runtime = runtime;
+    Py_XDECREF(tmp);
+
+    tmp = self->field;
+    Py_INCREF(field);
+    self->field = field;
+    Py_XDECREF(tmp);
+
+    if (value != NULL) {
+	result = PyObject_CallMethodObjArgs((PyObject *)&self->deferred,
+					    Py_BuildValue("s", "callback"),
+					    value, NULL);
+
+	if (result)
+	    Py_DECREF(result);
+	else
+	    return -1;
+    }
+
+    return 0;
+}
+
+static void cdefer_Share_dealloc(PyObject *o) {
+    cdefer_Share *self;
+    self = (cdefer_Share *)o;
+    Py_XDECREF(self->runtime);
+    Py_XDECREF(self->field);
+    cdefer_Deferred_dealloc((PyObject *)&self->deferred);
+}
+
+static int cdefer_Share_traverse(PyObject *o, visitproc visit, void *arg) {
+    cdefer_Share *self;
+    self = (cdefer_Share *)o;
+    Py_VISIT(self->runtime);
+    Py_VISIT(self->field);
+    return cdefer_Deferred_traverse((PyObject *)&self->deferred, visit, arg);
+}
+
+static int cdefer_Share_clear(PyObject *o) {
+    cdefer_Share *self;
+    self = (cdefer_Share *)o;
+    Py_CLEAR(self->runtime);
+    Py_CLEAR(self->field);
+    return cdefer_Deferred_clear((PyObject *)&self->deferred);
+}
+
+static PyTypeObject cdefer_ShareType;
+
+static PyObject *cdefer_split_result(PyObject *noarg,
+				     PyObject *args) {
+    PyObject *result, *clone, *res;
+
+    if(PyArg_UnpackTuple(args, "split_result", 2, 2, &result, &clone) < 0)
+	return NULL;
+
+    res = PyObject_CallMethodObjArgs(clone, PyString_FromString("callback"),
+			       result, NULL);
+
+    if (!res)
+	return NULL;
+
+    Py_INCREF(result);
+    return result;
+}
+
+PyMethodDef split_result_def = {"split_result",
+				(PyCFunction)cdefer_split_result,
+				METH_VARARGS, 0};
+
+static PyObject *cdefer_Share_clone(cdefer_Share *self, PyObject *noarg) {
+    PyObject *clone, *result, *split_result;
+
+    clone = PyObject_CallFunctionObjArgs((PyObject *)&cdefer_ShareType,
+					 self->runtime, self->field, NULL);
+
+    if (!clone)
+	return NULL;
+
+    split_result = PyCFunction_New(&split_result_def, NULL);
+
+    if (!split_result)
+	return NULL;
+
+    Py_INCREF(Py_None);
+    result = cdefer_Deferred__addCallbacks(&(self->deferred),
+					   split_result, Py_None,
+					   Py_BuildValue("(O)", clone), Py_None,
+					   Py_None, Py_None);
+
+    if (!result)
+	return NULL;
+
+    return clone;
+}
+
+static struct PyMethodDef cdefer_Share_methods[] = {
+    {"clone", (PyCFunction)cdefer_Share_clone, METH_NOARGS, 0},
+    {0, 0, 0, 0}
+};
+
+#define SYM_BIN_OP(FUNCNAME, NBNAME, SHORTNAME)	\
+static PyObject *FUNCNAME(PyObject *self, PyObject *other) { \
+    if (Py_TYPE(self)->tp_as_number != NULL && \
+	Py_TYPE(self)->tp_as_number->NBNAME == FUNCNAME) \
+	return PyObject_CallMethodObjArgs(((cdefer_Share *)self)->runtime, \
+					  PyString_FromString(#SHORTNAME), \
+					  self, other, NULL); \
+    else \
+	return PyObject_CallMethodObjArgs(((cdefer_Share *)other)->runtime, \
+					  PyString_FromString(#SHORTNAME), \
+					  other, self, NULL); \
+}
+
+SYM_BIN_OP(cdefer_Share_add, nb_add, add)
+SYM_BIN_OP(cdefer_Share_mul, nb_multiply, mul)
+SYM_BIN_OP(cdefer_Share_xor, nb_xor, xor)
+
+static PyObject *cdefer_Share_sub(PyObject *self, PyObject *other) {
+    if (Py_TYPE(self)->tp_as_number != NULL &&
+	Py_TYPE(self)->tp_as_number->nb_subtract == cdefer_Share_sub)
+	return PyObject_CallMethodObjArgs(((cdefer_Share *)self)->runtime,
+					  PyString_FromString("sub"),
+					  self, other, NULL);
+    else
+	return PyObject_CallMethodObjArgs(((cdefer_Share *)other)->runtime,
+					  PyString_FromString("sub"),
+					  self, other, NULL);
+}
+
+static PyObject *cdefer_Share_pow(PyObject *self, PyObject *other, PyObject *modulus) {
+    if (Py_TYPE(self)->tp_as_number != NULL &&
+	Py_TYPE(self)->tp_as_number->nb_power == cdefer_Share_pow)
+	return PyObject_CallMethodObjArgs(((cdefer_Share *)self)->runtime,
+					  PyString_FromString("pow"),
+					  self, other, NULL);
+    else {
+	Py_INCREF(Py_NotImplemented);
+	return Py_NotImplemented;
+    }
+}
+
+static PyObject *cdefer_Share_richcompare(PyObject *self,
+					  PyObject *other, int op) {
+    PyObject *first, *second, *tmp = NULL;
+
+    if (Py_TYPE(self)->tp_richcompare == cdefer_Share_richcompare) {
+	first = self;
+	second = other;
+    } else {
+	first = other;
+	second = self;
+    }
+
+    switch(op) {
+    case Py_EQ:
+    case Py_NE:
+	tmp = PyObject_CallMethodObjArgs(((cdefer_Share *)first)->runtime,
+					 PyString_FromString("equal"),
+					 first, second, NULL);
+	break;
+
+    case Py_GE:
+    case Py_LT:
+	tmp = PyObject_CallMethodObjArgs(((cdefer_Share *)first)->runtime,
+					 PyString_FromString("greater_than_equal"),
+					 self, other, NULL);
+	break;
+
+    case Py_LE:
+    case Py_GT:
+	tmp = PyObject_CallMethodObjArgs(((cdefer_Share *)first)->runtime,
+					 PyString_FromString("greater_than_equal"),
+					 other, self, NULL);
+	break;
+    }
+
+    switch(op) {
+    case Py_EQ:
+    case Py_GE:
+    case Py_GT:
+	return tmp;
+
+    case Py_NE:
+    case Py_LT:
+    case Py_LE:
+	if (!tmp)
+	    return NULL;
+	else
+	    return PyNumber_Subtract(PyInt_FromLong(1), tmp);
+    }
+
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+}
+
+static PyNumberMethods share_as_number = {
+        (binaryfunc)cdefer_Share_add,   /*nb_add*/
+        (binaryfunc)cdefer_Share_sub,   /*nb_subtract*/
+        (binaryfunc)cdefer_Share_mul,   /*nb_multiply*/
+        0,                              /*nb_divide*/
+        0,                              /*nb_remainder*/
+        0,                              /*nb_divmod*/
+        (ternaryfunc)cdefer_Share_pow,  /*nb_power*/
+        0,                              /*nb_negative*/
+        0,                              /*tp_positive*/
+        0,                              /*tp_absolute*/
+        0,                              /*tp_nonzero*/
+        0,                              /*nb_invert*/
+        0,                              /*nb_lshift*/
+        0,                              /*nb_rshift*/
+        0,                              /*nb_and*/
+        (binaryfunc)cdefer_Share_xor,   /*nb_xor*/
+        0,                              /*nb_or*/
+        0,                              /*nb_coerce*/
+        0,                              /*nb_int*/
+        0,                              /*nb_long*/
+        0,                              /*nb_float*/
+        0,                              /*nb_oct*/
+        0,                              /*nb_hex*/
+        0,                              /* nb_inplace_add */
+        0,                              /* nb_inplace_subtract */
+        0,                              /* nb_inplace_multiply */
+        0,                              /* nb_inplace_divide */
+        0,                              /* nb_inplace_remainder */
+        0,                              /* nb_inplace_power */
+        0,                              /* nb_inplace_lshift */
+        0,                              /* nb_inplace_rshift */
+        0,                              /* nb_inplace_and */
+        0,                              /* nb_inplace_xor */
+        0,                              /* nb_inplace_or */
+        0,                              /* nb_floor_divide */
+        0,                              /* nb_true_divide */
+        0,                              /* nb_inplace_floor_divide */
+        0                               /* nb_inplace_true_divide */
+};
+
+static PyTypeObject cdefer_ShareType = {
+    PyObject_HEAD_INIT(NULL)
+    0,                          /*ob_size*/
+    "cdefer.Share",             /*tp_name*/
+    sizeof(cdefer_Share),       /*tp_basicsize*/
+    0,                          /*tp_itemsize*/
+    (destructor)cdefer_Share_dealloc,      /*tp_dealloc*/
+    0,                          /*tp_print*/
+    0,                          /*tp_getattr*/
+    0,                          /*tp_setattr*/
+    0,                          /*tp_compare*/
+    0,                          /*tp_repr*/
+    &share_as_number,           /*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|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+    0,                          /*tp_doc*/
+    (traverseproc)cdefer_Share_traverse,   /*tp_traverse*/
+    (inquiry)cdefer_Share_clear,           /*tp_clear*/
+    (richcmpfunc)cdefer_Share_richcompare, /*tp_richcompare*/
+    0,                          /*tp_weaklistoffset*/
+    0,                          /*tp_iter*/
+    0,                          /*tp_iternext*/
+    cdefer_Share_methods,       /*tp_methods*/
+    cdefer_Share_members,       /*tp_members*/
+    0,                          /*tp_getset*/
+    &cdefer_DeferredType,       /*tp_base*/
+    0,                          /*tp_dict*/
+    0,                          /*tp_descr_get*/
+    0,                          /*tp_descr_set*/
+    0,                          /*tp_dictoffset*/
+    (initproc)cdefer_Share_init,          /*tp_init*/
+    0,                          /*tp_alloc*/
+    0,                          /*tp_new*/
+    PyObject_GC_Del,            /*tp_free*/
+    0,                          /*tp_is_gc*/
+    0,                          /*tp_bases*/
+    0,                          /*tp_mro*/
+    0,                          /*tp_cache*/
+    0,                          /*tp_subclasses*/
+    0,                          /*tp_weaklist*/
+};
+
 #ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
 #define PyMODINIT_FUNC void
 #endif
@@ -892,6 +1228,14 @@
         goto Error;
     }
 
+    /* VIFF */
+
+    if (PyType_Ready(&cdefer_ShareType) < 0)
+	return;
+
+    Py_INCREF(&cdefer_ShareType);
+    PyModule_AddObject(m, "Share", (PyObject *)&cdefer_ShareType);
+
     return;
 Error:
     Py_XDECREF(f);