#include "cReactor.h"
static PyObject *AlreadyCalledException, *AlreadyCancelledException;
staticforward PyTypeObject cDelayedCallType;
cDelayedCall *
cDelayedCall_new(int delay_ms,
PyObject *callable,
PyObject *args,
PyObject *kw)
{
cDelayedCall *call;
struct timeval call_time;
/* Calc the call time. */
gettimeofday(&call_time, NULL);
call_time.tv_usec += (delay_ms * 1000);
call_time.tv_sec += call_time.tv_usec / 1000000;
call_time.tv_usec = call_time.tv_usec % 1000000;
/* Make the new DelayedCall object. */
call = PyObject_New(cDelayedCall, &cDelayedCallType);
memcpy(&call->call_time, &call_time, sizeof(call_time));
call->reactor = NULL;
call->called = 0;
Py_INCREF(callable);
call->callable = callable;
/* var args */
if (!args)
{
call->args = PyTuple_New(0);
}
else
{
Py_INCREF(args);
call->args = args;
}
/* keyword args */
if (!kw)
{
call->kw = PyDict_New();
}
else
{
Py_INCREF(kw);
call->kw = kw;
}
return call;
}
static void
cDelayedCall_dealloc(PyObject *self)
{
cDelayedCall *call = (cDelayedCall *)self;
Py_DECREF(call->callable);
Py_XDECREF(call->args);
Py_XDECREF(call->kw);
free(call);
}
static PyObject *
cDelayedCall_getTime(PyObject *self, PyObject *args)
{
cDelayedCall *call = (cDelayedCall *)self;
double call_time;
if (!PyArg_ParseTuple(args, ":getTime"))
return NULL;
if (!call->reactor) {
/* not scheduled */
if (call->called) {
PyErr_SetString(AlreadyCalledException, "");
return NULL;
} else {
PyErr_SetString(AlreadyCancelledException, "");
return NULL;
}
}
call_time = call->call_time.tv_sec + call->call_time.tv_usec / 1000000;
return PyFloat_FromDouble(call_time);
}
static PyObject *
cDelayedCall_cancel(PyObject *self, PyObject *args)
{
int rc;
cDelayedCall *call = (cDelayedCall *)self;
if (!call->reactor) {
/* not scheduled */
if (call->called) {
PyErr_SetString(AlreadyCalledException, "");
return NULL;
} else {
PyErr_SetString(AlreadyCancelledException, "");
return NULL;
}
}
rc = cReactorUtil_RemoveDelayedCall(call->reactor, call);
if (rc != 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cDelayedCall_delay(PyObject *self, PyObject *args)
{
cDelayedCall *call = (cDelayedCall *)self;
PyObject *delay_obj = NULL;
int delay_ms = 0;
int rc;
if (!PyArg_ParseTuple(args, "O:delay", &delay_obj))
return NULL;
if (delay_obj)
{
delay_ms = cReactorUtil_ConvertDelay(delay_obj);
if (delay_ms < 0)
{
return NULL;
}
}
if (!call->reactor) {
/* not scheduled */
if (call->called) {
PyErr_SetString(AlreadyCalledException, "");
return NULL;
} else {
PyErr_SetString(AlreadyCancelledException, "");
return NULL;
}
}
/* self.time += secondsLater */
call->call_time.tv_usec += (delay_ms * 1000);
call->call_time.tv_sec += call->call_time.tv_usec / 1000000;
call->call_time.tv_usec = call->call_time.tv_usec % 1000000;
rc = cReactorUtil_ReInsertDelayedCall(call->reactor, call);
if (rc != 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cDelayedCall_reset(PyObject *self, PyObject *args)
{
cDelayedCall *call = (cDelayedCall *)self;
PyObject *delay_obj = NULL;
int delay_ms = 0;
int rc;
if (!PyArg_ParseTuple(args, "O:reset", &delay_obj))
return NULL;
if (delay_obj)
{
delay_ms = cReactorUtil_ConvertDelay(delay_obj);
if (delay_ms < 0)
{
return NULL;
}
}
if (!call->reactor) {
/* not scheduled */
if (call->called) {
PyErr_SetString(AlreadyCalledException, "");
return NULL;
} else {
PyErr_SetString(AlreadyCancelledException, "");
return NULL;
}
}
/* self.time = time() + secondsFromNow */
gettimeofday(&call->call_time, NULL);
call->call_time.tv_usec += (delay_ms * 1000);
call->call_time.tv_sec += call->call_time.tv_usec / 1000000;
call->call_time.tv_usec = call->call_time.tv_usec % 1000000;
rc = cReactorUtil_ReInsertDelayedCall(call->reactor, call);
if (rc != 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
cDelayedCall_active(PyObject *self, PyObject *args)
{
cDelayedCall *call = (cDelayedCall *)self;
if (!PyArg_ParseTuple(args, ":active"))
return NULL;
if (call->called)
return PyInt_FromLong(0);
else
return PyInt_FromLong(1);
}
static PyMethodDef cDelayedCall_methods[] =
{
/* IDelayedCall */
{ "getTime", cDelayedCall_getTime, METH_VARARGS, "getTime" },
{ "cancel", cDelayedCall_cancel, METH_VARARGS, "cancel" },
{ "delay", cDelayedCall_delay, METH_VARARGS, "delay" },
{ "reset", cDelayedCall_reset, METH_VARARGS, "reset" },
{ "active", cDelayedCall_active, METH_VARARGS, "active" },
{ NULL, NULL, METH_VARARGS, NULL },
};
static PyObject *
cDelayedCall_getattr(PyObject *self, char *attr_name)
{
PyObject *obj;
/* check for a method with the given name. */
obj = Py_FindMethod(cDelayedCall_methods, self, attr_name);
if (obj)
return obj;
/* If we didn't find anything raise PyExc_AttributeError. */
PyErr_SetString(PyExc_AttributeError, attr_name);
return NULL;
}
/* todo: make a __str__ method that includes a description of the callable
and args. It should also show how many seconds into the future the call
will be fired. */
/* The cDelayedCall type. */
static PyTypeObject cDelayedCallType =
{
PyObject_HEAD_INIT(NULL)
0,
"cDelayedCall", /* tp_name */
sizeof(cDelayedCall), /* tp_basicsize */
0, /* tp_itemsize */
cDelayedCall_dealloc, /* tp_dealloc */
NULL, /* tp_print */
cDelayedCall_getattr, /* tp_getattr */
NULL, /* tp_setattr */
NULL, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
NULL, /* tp_as_mapping */
NULL, /* tp_hash */
NULL, /* tp_call */
NULL, /* tp_str */
NULL, /* tp_getattro */
NULL, /* tp_setattro */
NULL, /* tp_as_buffer */
0, /* tp_flags */
NULL, /* tp_doc */
NULL, /* tp_traverse */
NULL, /* tp_clear */
NULL, /* tp_richcompare */
0, /* tp_weaklistoffset */
};
void
cDelayedCall_init(void)
{
cDelayedCallType.ob_type = &PyType_Type;
AlreadyCalledException =
cReactorUtil_FromImport("twisted.internet.error",
"AlreadyCalled");
if (!AlreadyCalledException) {
PyErr_Print();
return;
}
AlreadyCancelledException =
cReactorUtil_FromImport("twisted.internet.error",
"AlreadyCancelled");
if (!AlreadyCancelledException) {
PyErr_Print();
return;
}
}
syntax highlighted by Code2HTML, v. 0.9.1