예제 #1
0
static gr_param
g_switch(greenlet* target, gr_param data)
{
	/* _consumes_ a reference to the args tuple and kwargs dict,
	   and return a new tuple reference */

	/* check ts_current */
	if (!STATE_OK)
		return 0;


	/* find the real target by ignoring dead greenlets,
	   and if necessary starting a greenlet. */
	while (1) 
	{
		if (PyGreenlet_ACTIVE(target)) 
		{
			ts_target = target;
			ts_target->data = data;
			g_switchstack();
			break;
		}

		if (!PyGreenlet_STARTED(target)) 
		{
			void* dummymarker;
			ts_target = target;
			ts_target->data = data;
			g_initialstub(&dummymarker);
			break;
		}
		target = target->parent;
	}
    return ts_current->data;
}
예제 #2
0
stacklet_handle stacklet_new(stacklet_thread_handle thrd,
                             stacklet_run_fn run, void *run_arg)
{
    long stackmarker;
    _check((char *)NULL < (char *)&stackmarker);
    if (thrd->g_current_stack_stop <= (char *)&stackmarker)
        thrd->g_current_stack_stop = ((char *)&stackmarker) + 1;

    thrd->g_current_stack_marker = (char *)&stackmarker;
    g_initialstub(thrd, run, run_arg);
    return thrd->g_source;
}
예제 #3
0
파일: greenlet.c 프로젝트: vietlq/greenlet
static PyObject *
g_switch(PyGreenlet* target, PyObject* args, PyObject* kwargs)
{
	/* _consumes_ a reference to the args tuple and kwargs dict,
	   and return a new tuple reference */
	PyObject* run_info;

	/* check ts_current */
	if (!STATE_OK) {
		Py_XDECREF(args);
		Py_XDECREF(kwargs);
		return NULL;
	}
	run_info = green_statedict(target);
	if (run_info == NULL || run_info != ts_current->run_info) {
		Py_XDECREF(args);
		Py_XDECREF(kwargs);
		PyErr_SetString(PyExc_GreenletError, run_info
				? "cannot switch to a different thread"
				: "cannot switch to a garbage collected greenlet");
		return NULL;
	}

	ts_passaround_args = args;
	ts_passaround_kwargs = kwargs;

	/* find the real target by ignoring dead greenlets,
	   and if necessary starting a greenlet. */
	while (target) {
		if (PyGreenlet_ACTIVE(target)) {
			ts_target = target;
			if (g_switchstack() < 0) {
				g_passaround_clear();
				return NULL;
			}
			break;
		}
		if (!PyGreenlet_STARTED(target)) {
			int err;
			void* dummymarker;
			ts_target = target;
			err = g_initialstub(&dummymarker);
			if (err == 1) {
				continue; /* retry the switch */
			}
			else if (err < 0) {
				g_passaround_clear();
				return NULL;
			}
			break;
		}
		target = target->parent;
	}

	/* We need to figure out what values to pass to the target greenlet
	   based on the arguments that have been passed to greenlet.switch(). If
	   switch() was just passed an arg tuple, then we'll just return that.
	   If only keyword arguments were passed, then we'll pass the keyword
	   argument dict. Otherwise, we'll create a tuple of (args, kwargs) and
	   return both. */
	if (ts_passaround_kwargs == NULL)
	{
		g_passaround_return_args();
	}
	else if (PyDict_Size(ts_passaround_kwargs) == 0)
	{
		g_passaround_return_args();
	}
	else if (PySequence_Length(ts_passaround_args) == 0)
	{
		g_passaround_return_kwargs();
	}
	else
	{
		PyObject *tuple = PyTuple_New(2);
		if (tuple == NULL) {
			g_passaround_clear();
			return NULL;
		}
		PyTuple_SET_ITEM(tuple, 0, ts_passaround_args);
		PyTuple_SET_ITEM(tuple, 1, ts_passaround_kwargs);
		ts_passaround_args = NULL;
		ts_passaround_kwargs = NULL;
		return tuple;
	}
}
예제 #4
0
static PyObject *
g_switch(PyGreenlet* target, PyObject* args, PyObject* kwargs)
{
	/* _consumes_ a reference to the args tuple and kwargs dict,
	   and return a new tuple reference */
	int err = 0;
	PyObject* run_info;

	/* check ts_current */
	if (!STATE_OK) {
		Py_XDECREF(args);
		Py_XDECREF(kwargs);
		return NULL;
	}
	run_info = green_statedict(target);
	if (run_info == NULL || run_info != ts_current->run_info) {
		Py_XDECREF(args);
		Py_XDECREF(kwargs);
		PyErr_SetString(PyExc_GreenletError, run_info
		                ? "cannot switch to a different thread"
		                : "cannot switch to a garbage collected greenlet");
		return NULL;
	}

	ts_passaround_args = args;
	ts_passaround_kwargs = kwargs;

	/* find the real target by ignoring dead greenlets,
	   and if necessary starting a greenlet. */
	while (target) {
		if (PyGreenlet_ACTIVE(target)) {
			ts_target = target;
			err = g_switchstack();
			break;
		}
		if (!PyGreenlet_STARTED(target)) {
			void* dummymarker;
			ts_target = target;
			err = g_initialstub(&dummymarker);
			if (err == 1) {
				continue; /* retry the switch */
			}
			break;
		}
		target = target->parent;
	}

	/* For a very short time, immediately after the 'atomic'
	   g_switchstack() call, global variables are in a known state.
	   We need to save everything we need, before it is destroyed
	   by calls into arbitrary Python code. */
	args = ts_passaround_args;
	ts_passaround_args = NULL;
	kwargs = ts_passaround_kwargs;
	ts_passaround_kwargs = NULL;
	if (err < 0) {
		/* Turn switch errors into switch throws */
		assert(ts_origin == NULL);
		Py_CLEAR(kwargs);
		Py_CLEAR(args);
	} else {
		PyGreenlet *origin;
#if GREENLET_USE_TRACING
		PyGreenlet *current;
		PyObject *tracefunc;
#endif
		origin = ts_origin;
		ts_origin = NULL;
#if GREENLET_USE_TRACING
		current = ts_current;
		if ((tracefunc = PyDict_GetItem(current->run_info, ts_tracekey)) != NULL) {
			Py_INCREF(tracefunc);
			if (g_calltrace(tracefunc, args ? ts_event_switch : ts_event_throw, origin, current) < 0) {
				/* Turn trace errors into switch throws */
				Py_CLEAR(kwargs);
				Py_CLEAR(args);
			}
			Py_DECREF(tracefunc);
		}
#endif
		Py_DECREF(origin);
	}

	/* We need to figure out what values to pass to the target greenlet
	   based on the arguments that have been passed to greenlet.switch(). If
	   switch() was just passed an arg tuple, then we'll just return that.
	   If only keyword arguments were passed, then we'll pass the keyword
	   argument dict. Otherwise, we'll create a tuple of (args, kwargs) and
	   return both. */
	if (kwargs == NULL)
	{
		return args;
	}
	else if (PyDict_Size(kwargs) == 0)
	{
		Py_DECREF(kwargs);
		return args;
	}
	else if (PySequence_Length(args) == 0)
	{
		Py_DECREF(args);
		return kwargs;
	}
	else
	{
		PyObject *tuple = PyTuple_New(2);
		if (tuple == NULL) {
			Py_DECREF(args);
			Py_DECREF(kwargs);
			return NULL;
		}
		PyTuple_SET_ITEM(tuple, 0, args);
		PyTuple_SET_ITEM(tuple, 1, kwargs);
		return tuple;
	}
}