Monday, November 12, 2007

Building Games in Small Pieces - The Scheduler

I've just uploaded fibra to the cheeseshop. This is another small piece of code which I find very useful in developing simulations and games.

Fibra is the scheduler I used in ICCARUS to simulate concurrency. It uses Python generators as 'tasklets' which are iterated cooperatively. It does a job which is very similar to another library I've written, but is different in that it is very light weight, and uses a plugin system to provide extra functionality, such as sleeping, deferring execution, spawning into a real thread etc. To achieve this, it uses new Python 2.5 generator methods, so I decided to split it out of the older nanothreads module and create a new package.

Usually, I have a global scheduler available in the game, so any part of the code can defer a function call, or install a new tasklet. I usually iterate the scheduler just after I handle GUI events.

It's nothing new, its been done before, but I imagine with the right plugins, it could achieve much of what people want when they talk about concurrent Python.

This is a simple example:

import fibraimport fibra.plugins.sleep

def sleeper(x): while True: print x yield x

def normal(): while True: yield None

s = fibra.Schedule()#tell the schedule that Sleep, float and int objects should be#handled by the SleepPlugins.register_plugin(fibra.plugins.sleep.SleepPlugin(), (fibra.plugins.sleep.Sleep, float, int))#the SleepPlugin provides a new method which lets us defer#as tasklets start for X seconds.s.defer(4, sleeper(0.5))#install a sleep tasks that will only iterate once ever 2 secondss.install(sleeper(2))#install a normal task that will iterate on every ticks.install(normal())#iterate the schedulerwhile True: s.tick()