Skip to content

Commit

Permalink
merge 3.3-slp (Stackless python#117, st.watchdogs)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anselm Kruis committed Mar 17, 2017
2 parents bf7284a + af595e2 commit efa2504
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 43 deletions.
27 changes: 19 additions & 8 deletions Stackless/module/stacklessmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,20 +720,31 @@ get_thread_info(PyObject *self, PyObject *args)
PyThreadState *ts = PyThreadState_GET();
PyInterpreterState *interp = ts->interp;
long id = 0;
/* The additional optional argument flags is currently intentionally
* undocumented. The lower order flag bits are reserved for future public
* applications. If the flag bit 31 is set, the returned tuple contains
* the watchdog list as an additional item. The Stackless test suite uses
* this feature to ensure that the list is empty at start and end of each
* test.
*/
unsigned long flags=0;

if (!PyArg_ParseTuple(args, "|l:get_thread_info", &id))
if (!PyArg_ParseTuple(args, "|lk:get_thread_info", &id, &flags))
return NULL;
for (ts = interp->tstate_head; id && ts != NULL; ts = ts->next) {
if (ts->thread_id == id)
break;
if (id != -1) {
for (ts = interp->tstate_head; id && ts != NULL; ts = ts->next) {
if (ts->thread_id == id)
break;
}
if (ts == NULL)
RUNTIME_ERROR("Thread id not found", NULL);
}
if (ts == NULL)
RUNTIME_ERROR("Thread id not found", NULL);

return Py_BuildValue("(OOi)",
return Py_BuildValue((flags & (1ul<<31)) ? "(OOiO)": "(OOi)",
ts->st.main ? (PyObject *) ts->st.main : Py_None,
ts->st.runcount ? (PyObject *) ts->st.current : Py_None,
ts->st.runcount);
ts->st.runcount,
ts->st.watchdogs ? ts->st.watchdogs : Py_None);
}

static PyObject *
Expand Down
27 changes: 27 additions & 0 deletions Stackless/unittests/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,33 @@ def require_one_thread(testcase):
return testcase


def get_current_watchdog_list():
# The second argument of get_thread_info() is intentionally undocumented.
# See C source.
watchdog_list = stackless.get_thread_info(-1, 1 << 31)[3]
if isinstance(watchdog_list, list):
return watchdog_list
# The watchdog list has not been created. Force its creation.
# First clear the scheduler. We do not want to run any tasklets
scheduled = []
t = stackless.current.next
while t not in (None, stackless.current):
scheduled.append(t)
t = t.next
for t in scheduled:
t.remove()
try:
stackless.run() # creates the watchdog list
finally:
for t in scheduled:
t.insert()
if scheduled:
assert stackless.current.next == scheduled[0]
watchdog_list = stackless.get_thread_info(-1, 1 << 31)[3]
assert isinstance(watchdog_list, list)
return watchdog_list


class StacklessTestCaseMixin(object):
def skipUnlessSoftswitching(self):
if not stackless.enable_softswitch(None):
Expand Down
36 changes: 1 addition & 35 deletions Stackless/unittests/test_watchdog.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import stackless

from support import test_main # @UnusedImport
from support import StacklessTestCase, require_one_thread
from support import StacklessTestCase, require_one_thread, get_current_watchdog_list


# Helpers
Expand All @@ -16,40 +16,6 @@ def is_soft():
return softswitch


def get_current_watchdog_list():
import gc
result = []

def _tasklet(tlet):
if tlet is not None:
assert tlet.paused
gc.collect()
referrers = gc.get_referrers(tlet)
for obj in referrers:
if isinstance(obj, list):
result.append(obj)
assert len(result) == 1, "found %d list references, expected 1" % len(result)
else:
stackless.tasklet(_tasklet)(stackless.current)
stackless.run()
scheduled = []
t = stackless.current.next
while t not in (None, stackless.current):
scheduled.append(t)
t = t.next
for t in scheduled:
t.remove()
stackless.tasklet(_tasklet)(None)
try:
stackless.run()
finally:
for t in scheduled:
t.insert()
if scheduled:
assert stackless.current.next == scheduled[0]
return result[0]


class SimpleScheduler(object):
""" Not really scheduler as such but used here to implement
autoscheduling hack and store a schedule count. """
Expand Down

0 comments on commit efa2504

Please sign in to comment.