Python高级编程之生成器(Generator)与coroutine(四):一个简单的多任务系统
啊,终于要把这一个系列写完整了,好高兴啊
在前面的三篇文章中介绍了Python的Python的Generator和coroutine(协程)相关的编程技术,接下来这篇文章会用Python的coroutine技术实现一个简单的多任务的操作系统
代码如下,可看注释
#-*-coding:utf-8 -*-
'''
用Python和coroutine实现一个简单的多任务系统
'''
# ##Step 1:Define Tasks###################################
import select
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 def run(self):
return self.target.send(self.sendval)
# ############################################### # ##Step 2:The Scheduler#########################
import Queue
class Scheduler(object):
def __init__(self):
self.ready = Queue.Queue()
self.taskmap = {} # 正在等待的Tasks,key是taskid
self.exit_waiting = {} # 异步IO
# Holding areas for tasks blocking on I/O.These are
# dictionaries mapping file descriptions to tasks
# 键值为文件描述符
self.read_waiting = {}
self.write_waiting = {} def iotask(self):
while True:
if self.ready.empty():
# 如果ready为空,表示没有正在等待执行的队列
# timeout 为None,表示不关心任何文件描述符的变化
self.iopool(None)
else:
# ready不为空,则设置select函数不管文件描述符是否发生变化都立即返回
self.iopool(0)
yield def new(self,target):
newtask = Task(target)
self.taskmap[newtask.tid] = newtask
self.schedule(newtask)
return newtask.tid def schedule(self,task):
# 把task放到任务队列中去
self.ready.put(task) def exit(self,task):
print "Task %d terminated" %task.tid
del self.taskmap[task.tid]
# Notify other tasks waiting for exit
# 把正在等待的任务加入到正在执行的队列中去
for task in self.exit_waiting.pop(task.tid,[]):
self.schedule(task) def waitforexit(self,task,waittid):
'''
让一个任务等待另外一个任务,把这个任务加入到exit_waiting中去
返回True表示这个task正在等待队列中
'''
if waittid in self.taskmap:
self.exit_waiting.setdefault(waittid,[]).append(task)
return True
else:
return False def waitforread(self,task,fd):
'''
functions that simply put a task into to
one of the above dictionaries
'''
self.read_waiting[fd] = task def waitforwrite(self,task,fd):
self.write_waiting[fd] = task def iopool(self,timeout):
'''
I/O Polling.Use select() to determine which file
descriptors can be used.Unblock any associated task
'''
if self.read_waiting or self.write_waiting:
# 获取I/O事件,一旦获取到,就放入到执行队列中取,等待执行
r,w,e = select.select(self.read_waiting,
self.write_waiting,[],timeout)
for fd in r:
self.schedule(self.read_waiting.pop(fd)) for fd in w:
self.schedule(self.write_waiting.pop(fd)) def mainloop(self):
self.new(self.iotask()) # Launch I/O polls
while self.taskmap:
task = self.ready.get()
try:
result = task.run()
# 如果task执行的是System call,则对当前环境进行保存
# 然后在执行System Call
if isinstance(result,SystemCall):
# 把当前的环境保存,即保存当前运行的task和sched
result.task = task
result.sched = self
result.handle()
continue
except StopIteration:
self.exit(task)
# print("task is over")
continue
self.schedule(task)
# ##Step 2:The Scheduler######################### # ##SystemCall#########################
class SystemCall(object):
'''
所有系统调用的基类,继承自该类的类要重写handle函数
'''
def handle(self):
pass class GetTid(SystemCall):
'''
获取任务ID
'''
def handle(self):
self.task.sendval = self.task.tid
self.sched.schedule(self.task) class NewTask(SystemCall):
'''
新建一个Task
'''
def __init__(self,target):
self.target = target def handle(self):
# 在这里把target封装成Task
# 是在这里把新生成的task加入到执行队列当中去
tid = self.sched.new(self.target)
self.task.sendval = tid
# 把执行这个系统调用的父task重新加入到执行队列中去
# 这一点很关键,因为判断一个task是否结束是通过taskmap的
# 这个task只是暂时被挂起,要重新放到queue中去
self.sched.schedule(self.task) class KillTask(SystemCall):
'''
杀死一个Task
'''
def __init__(self,tid):
self.tid = tid def handle(self):
task = self.sched.taskmap.get(self.tid,None)
# task指的是要被kill掉的那个task
# self.task指的是发起KillTask这个系统调用task
if task:
task.target.close()
self.task.sendval = None
else:
self.task.sendval = False
# target.close()只是产生一个StopIteration异常
self.sched.schedule(self.task) class WaitTask(SystemCall):
'''
让任务进行等待 系统调用
'''
def __init__(self,tid):
self.tid = tid def handle(self):
result = self.sched.waitforexit(self.task,self.tid)
self.task.sendval = result
# 如果等待的是一个不存在的task,则立即返回
if not result:
self.sched.schedule(self.task) class ReadWait(SystemCall):
'''
异步读 系统调用
'''
def __init__(self,f):
self.f = f def handle(self):
fd = self.f.fileno()
self.sched.waitforread(self.task,fd) class WriteWait(SystemCall):
'''
异步写 系统调用
'''
def _init__(self,f):
self.f = f def handle(self):
fd = self.f.fileno()
self.sched.waitforwrite(self.task,fd)
Python高级编程之生成器(Generator)与coroutine(四):一个简单的多任务系统的更多相关文章
- Python高级编程之生成器(Generator)与coroutine(二):coroutine介绍
原创作品,转载请注明出处:点我 上一篇文章Python高级编程之生成器(Generator)与coroutine(一):Generator中,我们介绍了什么是Generator,以及写了几个使用Gen ...
- Python高级编程之生成器(Generator)与coroutine(一):Generator
转载请注明出处:点我 这是一系列的文章,会从基础开始一步步的介绍Python中的Generator以及coroutine(协程)(主要是介绍coroutine),并且详细的讲述了Python中coro ...
- Python高级编程之生成器(Generator)与coroutine(三):coroutine与pipeline(管道)和Dataflow(数据流_
原创作品,转载请注明出处:点我 在前两篇文章中,我们介绍了什么是Generator和coroutine,在这一篇文章中,我们会介绍coroutine在模拟pipeline(管道 )和控制Dataflo ...
- python高级编程技巧
由python高级编程处学习 http://blog.sina.com.cn/s/blog_a89e19440101fb28.html Python列表解析语法[]和生成 器()语法类似 [expr ...
- 第十一章:Python高级编程-协程和异步IO
第十一章:Python高级编程-协程和异步IO Python3高级核心技术97讲 笔记 目录 第十一章:Python高级编程-协程和异步IO 11.1 并发.并行.同步.异步.阻塞.非阻塞 11.2 ...
- python高级编程之选择好名称:完
由于时间关系,python高级编程不在放在这边进行学习了,如果需要的朋友可以看下面的网盘进行下载 # # -*- coding: utf-8 -*- # # python:2.x # __author ...
- python高级编程之列表推导式
1. 一个简单的例子 在Python中,如果我们想修改列表中所有元素的值,可以使用 for 循环语句来实现. 例如,将一个列表中的每个元素都替换为它的平方: >>> L = [1, ...
- python高级编程:有用的设计模式3
# -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#访问者:有助于将算法从数据结构中分离出来"&qu ...
- python高级编程:有用的设计模式2
# -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...
随机推荐
- SqlServer强制断开数据库已有连接的方法(转)
在master数据库中执行如下代码 declare @i INT declare cur cursor for select spid from sysprocesses where db_name ...
- Google Map 学习过程中的代码
<!DOCTYPE html><html> <head> <title>Simple click event</title> <met ...
- 【js】appendChild
appendChild主要是用来追加节点插入到最后:循环的时候由于不停的搬家导致length在改变. 使用for循环 <!Doctype html> <html xmlns= ...
- Open SSH原理
OpenSSH(免费的 SSH 的实现)类似于 telnet 或rsh,ssh 客户程序也可以用于登录到远程机器.所要求的只是该远程机器正在运行 sshd,即 ssh 服务器进程.但是,与 telne ...
- Android中如何实现文件下载
最近做一个项目需要从服务器下载图片到本地sdcard,上网查找了一些例子,下面这个比较合适,原文内容如下: 我们在开发中经常需要从服务器下载文件,下载的内容可能有交换的信息,缓存的图片,程 ...
- Python find() 方法
描述 Python find() 方法从字符串中找出某个子字符串第一个匹配项的索引位置,该方法与index() 方法一样,只不过如果子字符串不在字符串中不会报异常,而是返回-1. 语法 find() ...
- 关于FSMC地址线的理解
http://www.openedv.com/thread-33759-1-1.html (出处: OpenEdv-开源电子网)
- MySQL变量的定义与赋值
MySQL存储过程中,定义变量有两种方式:1.使用set或select直接赋值,变量名以 @ 开头.例如:set @var=1;可以在一个会话的任何地方声明,作用域是整个会话,称为会话变量. 2.以 ...
- 【Android】3.12 兴趣点( POI)搜索功能
分类:C#.Android.VS2015.百度地图应用: 创建日期:2016-02-04 一.简介 POI(Point of Interest),中文可以翻译为“兴趣点”.在地理信息系统中,一个POI ...
- 利用 FormData 对象发送 Key/Value 对的异步请求
使用Key/Value对和FormData能够轻易地通过XMLHttpRequest指定要传递什么数据,它是一个非常强大的发送数据到服务器的方法. 基础 通常的方法是你创建一个 FormData 对象 ...