# ------------------------------------------------------------ # pyos5.py - The Python Operating System # # Step 5: Added system calls for simple task management # ------------------------------------------------------------ # ------------------------------------------------------------ # === Tasks === # ------------------------------------------------------------ class Task(object): taskid = 0 def __init__(self,target): Task.taskid += 1 self.tid = Task.taskid # Task ID self.target = target # Target coroutine self.sendval = None # Value to send # Run a task until it hits the next yield statement def run(self): return self.target.send(self.sendval) # ------------------------------------------------------------ # === Scheduler === # ------------------------------------------------------------ from Queue import Queue class Scheduler(object): def __init__(self): self.ready = Queue() self.taskmap = {} def new(self,target): newtask = Task(target) self.taskmap[newtask.tid] = newtask self.schedule(newtask) return newtask.tid def exit(self,task): print "Task %d terminated" % task.tid del self.taskmap[task.tid] def schedule(self,task): self.ready.put(task) def mainloop(self): while self.taskmap: task = self.ready.get() try: result = task.run() if isinstance(result,SystemCall): result.task = task result.sched = self result.handle() continue except StopIteration: self.exit(task) continue self.schedule(task) # ------------------------------------------------------------ # === System Calls === # ------------------------------------------------------------ class SystemCall(object): def handle(self): pass # Return a task's ID number class GetTid(SystemCall): def handle(self): self.task.sendval = self.task.tid self.sched.schedule(self.task) # Create a new task class NewTask(SystemCall): def __init__(self,target): self.target = target def handle(self): tid = self.sched.new(self.target) self.task.sendval = tid self.sched.schedule(self.task) # Kill a task class KillTask(SystemCall): def __init__(self,tid): self.tid = tid def handle(self): task = self.sched.taskmap.get(self.tid,None) if task: task.target.close() self.task.sendval = True else: self.task.sendval = False self.sched.schedule(self.task) # ------------------------------------------------------------ # === Example === # ------------------------------------------------------------ if __name__ == '__main__': def foo(): mytid = yield GetTid() while True: print "I'm foo", mytid yield def main(): child = yield NewTask(foo()) # Launch new task for i in xrange(5): yield yield KillTask(child) # Kill the task print "main done" sched = Scheduler() sched.new(main()) sched.mainloop()