static PyObject * pycall(CLazyLinker * self, Py_ssize_t node_idx, int verbose) { // call thunk to see which inputs it wants PyObject * thunk = PyList_GetItem(self->thunks, node_idx); // refcounting - thunk is borrowed PyObject * rval = NULL; if (self->do_timing) { double t0 = pytime(NULL); if (verbose) fprintf(stderr, "calling via Python (node %i)\n", (int)node_idx); rval = PyObject_CallObject(thunk, NULL); if (rval) { double t1 = pytime(NULL); double ti = PyFloat_AsDouble( PyList_GetItem(self->call_times, node_idx)); PyList_SetItem(self->call_times, node_idx, PyFloat_FromDouble(t1 - t0 + ti)); PyObject * count = PyList_GetItem(self->call_counts, node_idx); long icount = PyInt_AsLong(count); PyList_SetItem(self->call_counts, node_idx, PyInt_FromLong(icount + 1)); } } else { if (verbose) { fprintf(stderr, "calling via Python (node %i)\n", (int)node_idx); } rval = PyObject_CallObject(thunk, NULL); } return rval; }
static PyObject * sleepInCpp(PyObject *self, PyObject *seconds) { double time_to_wait, wait_until; time_to_wait = PyFloat_AsDouble(seconds); if (PyErr_Occurred()) return NULL; wait_until = pytime() + time_to_wait; while (pytime() < wait_until) { /* let other processes run */ printf("sleepInCpp activated\n"); if (wrap(PyStackless_Schedule(Py_None, 0))) return NULL; } Py_INCREF(Py_None); return Py_None; }
static int c_call(CLazyLinker * self, Py_ssize_t node_idx, int verbose) { void * ptr_addr = self->thunk_cptr_fn[node_idx]; int (*fn)(void*) = (int (*)(void*))(ptr_addr); if (verbose) fprintf(stderr, "calling non-lazy shortcut (node %i)\n", (int)node_idx); int err = 0; if (self->do_timing) { double t0 = pytime(NULL); err = fn(self->thunk_cptr_data[node_idx]); double t1 = pytime(NULL); double ti = PyFloat_AsDouble(PyList_GetItem(self->call_times, node_idx)); PyList_SetItem(self->call_times, node_idx, PyFloat_FromDouble(t1 - t0 + ti)); PyObject * count = PyList_GetItem(self->call_counts, node_idx); long icount = PyInt_AsLong(count); PyList_SetItem(self->call_counts, node_idx, PyInt_FromLong(icount+1)); } else { err = fn(self->thunk_cptr_data[node_idx]); } if (err) { // cast the argument to a PyList (as described near line 226 of cc.py) PyObject * __ERROR = ((PyObject**)self->thunk_cptr_data[node_idx])[0]; assert (PyList_Check(__ERROR)); assert (PyList_Size(__ERROR) == 3); PyObject * err_type = PyList_GetItem(__ERROR, 0); //stolen ref PyObject * err_msg = PyList_GetItem(__ERROR, 1); //stolen ref PyObject * err_trace = PyList_GetItem(__ERROR, 2); //stolen ref PyList_SET_ITEM(__ERROR, 0, Py_None); Py_INCREF(Py_None); //clobbers old ref PyList_SET_ITEM(__ERROR, 1, Py_None); Py_INCREF(Py_None); //clobbers old ref PyList_SET_ITEM(__ERROR, 2, Py_None); Py_INCREF(Py_None); //clobbers old ref assert(!PyErr_Occurred()); // because CLinker hid the exception in __ERROR aka data PyErr_Restore(err_type, err_msg, err_trace); //steals refs to args } if (err) set_position_of_error(self, node_idx); return err; }