Ejemplo n.º 1
0
int main(int argc, char **argv)
{
    PyObject *gameModule, *utilModule, *func, *ret, *args;
    PyTaskletObject *tasklet;
    int i;

    Py_SetProgramName(argv[0]);
    Py_Initialize();

    niceChannel = PyChannel_New(NULL);

    utilModule = Py_InitModule("util", util_methods);
    gameModule = PyImport_ImportModule("game");
    if (gameModule == NULL) {
        CheckForErrors();
    }

    /*
    Allow the startup script "game.py" to start some
    tasklets in its Run method.  I initially tried calling
    it directly as a function but it seemed to be called
    twice.
    */
    func = PyObject_GetAttrString(gameModule, "Run");
    if (func == NULL) {
        CheckForErrors();
    }
    tasklet = PyTasklet_New(NULL, func);
    Py_DECREF(func);
    PyTasklet_SetBlockTrap(tasklet, 1);
    args = PyTuple_New(0);
    PyTasklet_Setup(tasklet, args, NULL);
    Py_DECREF(args);
    PyTasklet_Run(tasklet);

    while (1) {
        for (i = niceChannel->balance; i < 0; i++) {
            PyChannel_Send(niceChannel, Py_None);
            CheckForErrors();
        }

        do {
            ret = PyStackless_RunWatchdog(2000000);
            if (ret != NULL && ret != Py_None) {
                PyTasklet_Kill((PyTaskletObject *)ret);
                CheckForErrors();
            }
            Py_XDECREF(ret);
        } while (!ret);
        CheckForErrors();
    }

    Py_DECREF(utilModule);
    Py_DECREF(gameModule);

    Py_DECREF(niceChannel);

    Py_Finalize();
    return 0;
}
Ejemplo n.º 2
0
void slp_kill_tasks_with_stacks(PyThreadState *ts)
{
	int count = 0;

	while (1) {
		PyCStackObject *csfirst = slp_cstack_chain, *cs;
		PyTaskletObject *t, *task;
		PyTaskletObject **chain;

		if (csfirst == NULL)
			break;
		for (cs = csfirst; ; cs = cs->next) {
			if (count && cs == csfirst) {
				/* nothing found */
				return;
			}
			++count;
			if (cs->task == NULL)
				continue;
			if (ts != NULL && cs->tstate != ts)
				continue;
			break;
		} 
		count = 0;
		t = cs->task;
		Py_INCREF(t);

		/* We need to ensure that the tasklet 't' is in the scheduler
		 * tasklet chain before this one (our main).  This ensures
		 * that this one is directly switched back to after 't' is
		 * killed.  The reason we do this this is because if another
		 * tasklet is switched to, this is of course it being scheduled
		 * and run.  Why we do not need to do this for tasklets blocked
		 * on channels is that when they are scheduled to be run and
		 * killed, they will be implicitly placed before this one,
		 * leaving it to run next.
		 */
		if (!t->flags.blocked && t != cs->tstate->st.main) {
			if (t->next && t->prev) { /* it may have been removed() */
				chain = &t;
				SLP_CHAIN_REMOVE(PyTaskletObject, chain, task, next, prev)
			}
			chain = &cs->tstate->st.main;
			task = cs->task;
			SLP_CHAIN_INSERT(PyTaskletObject, chain, task, next, prev);
			cs->tstate->st.current = cs->tstate->st.main;
			t = cs->task;
		}

		Py_INCREF(t); /* because the following steals a reference */
		PyTasklet_Kill(t);
		PyErr_Clear();

		if (t->f.frame == 0) {
			/* ensure a valid tstate */
			t->cstate->tstate = slp_initial_tstate;
		}
		Py_DECREF(t);
	}
Ejemplo n.º 3
0
static void
kill_finally (PyObject *ob)
{
    PyThreadState *ts = PyThreadState_GET();
    PyTaskletObject *self = (PyTaskletObject *) ob;
    int is_mine = ts == self->cstate->tstate;

    /* this could happen if we have a refcount bug, so catch it here.
    assert(self != ts->st.current);
    It also gets triggered on interpreter exit when we kill the tasks
    with stacks (PyStackless_kill_tasks_with_stacks) and there is no
    way to differentiate that case.. so it just gets commented out.
    */

    self->flags.is_zombie = 1;
    while (self->f.frame != NULL) {
        PyTasklet_Kill(self);
        if (!is_mine)
            return; /* will be killed elsewhere */
    }
}