Views
Scheduling
Introduction
There is a simple scheduler built into Stackless Python. It schedules registered tasklets in order, rotating through the list giving each tasklet a turn.
When a tasklet is created, it is automatically appended to the end of this list. However, the scheduler needs to be manually called in order to make it work. The simplest way is to simply run it using the provided method exposed in the stackless module. This schedules each registered tasklet in turn until there are no tasklets remaining in the list.
Example - Running the scheduler:
stackless.run()
Heres a more complicated example which demonstrates creating some initial tasklets, shows the order in which they are run and that the scheduler exits when they exit.
Example - Scheduling some tasklets:
def f(i):
print i
stackless.tasklet(f)(1)
stackless.tasklet(f)(2)
stackless.run()
Output:
1 2
Cooperative Scheduling
Starting the scheduler in the way shown above runs the tasklets in a cooperative manner. It is the responsibility of each tasklet to get itself rescheduled so that other tasklets can have a turn, as they are not interrupted in any way by the scheduler. This can be done by calling the schedule method. The following example shows some potentially long running tasklets yielding to each other.
Example - Scheduling cooperatively:
def InfiniteLoop(i):
while 1:
stackless.schedule()
print "schedule", i
stackless.tasklet(InfiniteLoop)(1)
stackless.tasklet(InfiniteLoop)(2)
stackless.run()
Output:
schedule 0 schedule 1 schedule 0 schedule 1 ...
Preemptive Scheduling
If preemptive scheduling is prefered, then this can be achieved by telling the scheduler to run for only a specific number of instructions.
Example - Running the scheduler until 1000 instructions have been executed:
instructionCount = 1000 stackless.run(instructionCount)
In order to illustrate this with a more practical example, we will just look at the cooperatively scheduled example rewritten to yield implicitly rather than explicitly. In order to do so, we need to manage the schedulers run method.
Example - Scheduling preemptively:
def InfiniteLoop(i):
while 1:
print "schedule", i
stackless.tasklet(InfiniteLoop)(1)
stackless.tasklet(InfiniteLoop)(2)
# The current main thread of execution counts as one running tasklet, so
# we know that if it is the only one remaining, we can exit.
while stackless.getruncount() != 1:
t = stackless.run(1000)
# If we got a tasklet back, it was the one that was interrupted.
# we need to reinsert it for rescheduling.
if t:
t.insert()
Output:
schedule 1 ... repeated until 1000 instructions have passed schedule 2 ... repeated until 1000 instructions have passed ...
While preemptive scheduling might be useful in some specific situations, in general the predictibility of cooperative scheduling is invaluable.
Stackless Python