chapter9_2 管道与过滤器

  一个关于协同程序的经典示例就是“生产者-消费者”的问题。

一个不断产生值,一个不断消费这些值。比如:

function producer()
    while true do
        local x = io.read()         --produce new value
        send(x)                        --send it to consumer
    end
end

function consumer()
    while true do
        local x = receive()        --receive value from producer
        io.write(x,"\n")            --consumer it
    end
end

如何将send和receive匹配起来,这是一个典型的“谁有主循环”的问题。由于两则都有一个主循环,并且都将对方视为一个可调用的服务。

协同程序被称为一种匹配生产者和消费者的理想工具,一对resume-yield完全一改典型的调用者与被调用者之间的关系。

当一个协同程序调用yield时,它不是进入一个新的函数,而是从一个resume调用中返回。

同样对于resume,也不是启动一个新函数,而是从一次yield调用中返回。

两者都认为自己是主动方,对方是被动。

receive唤醒生产者,使它产生一个新值。而send则产生一个新值返还给消费者:

function receive()
    local status,value = coroutine.resume(producer)
    return value
end

function send(x)
    coroutine.yield(x)
end

因此,生产者现在一定是一个协同程序:

producer = coroutine.create( function ()
        while true do
        local x = io.read()        --产生新值
            send(x)
        end
    end)

在这种设计中,程序通过调用消费者来启动,当消费者需要一个新值时,唤醒生产者。

生产者返回一个新值后停止运行,并等待消费者的再次唤醒。这种设计称为“消费者驱动(consumer-driven)”。

还有一种就是使用“生产者驱动”设计,消费者是一个协同程序。

过滤器

  过滤器是一种位于生产者和消费者之间的处理功能,可用于对数据的一些变换。

过滤器既是一个消费者又是一个生产者,它唤醒一个生产者促使其产生新值,又将变换后的值传递给消费者。

例如,在上面的代码中添加一个过滤器,在每行起始处插一个行号:

function receive(prod)
    local status,value = coroutine.resume(prod)
    return value
end

function send(x)
    coroutine.yield(x)
end

function producer()
    return coroutine.create(function ()
        while true do
            local x = io.read()        --产生一个新值
            send(x)
        end
    end)
end

function filter(prod)
    return coroutine.create(function ()
        for line = 1,math.huge do
            local x = receive(prod)    --获得一个新值
            x = string.format("%5d %s",line,x)
            send(x)                    -- send it to consumer
        end
     end)
end

function consumer(prod)
    while true do
        local x = receive(prod)     --获得一个新值
        io.write(x,"\n")            --消费一个新值
    end
end

接下来运行代码,然后启动消费者:

p = producer ()
f = filter(p)
consumer(f)

--或者更简单
consumer(filter(producer()))

在pipe中每个任务都在各自独立的进程中运行,而在协同程序中每项任务都在各自独立的协同程序中运行。

pipe在消费者与生产者之间提供一个缓冲器,因此它们的运行速度允许存在一定差异。但是,在pipe中进程间切换代价很高。

而在协同程序中,切换代价小得多(差不多等于函数调用)。

时间: 2024-07-30 10:19:41

chapter9_2 管道与过滤器的相关文章

面向模式的软件体系结构(3)--管道与过滤器

看了一整晚,不甚理解管道/过滤器.常见的案例Linux命令管道是比较好理解的,但加之混乱的主动/被动的动态概念,就不太好理解了.暂先整理笔记,后面再回顾. 这是看的第2类体系结构,不是有所收获:大致可抽象出一些常见设计的范式 1.体系结构现过程关键点:拆.定义接口/格式.合.出错处理 2.优点关注:重用度  "考虑到一般变更的设计是优秀系统深化的一个主要助推器" [概述] 管道和过滤器(Pipes and Filters)为处理数据流的系统提供了一种结构.每个处理步骤封装在一个过滤器组

管道与过滤器风格

在管道/过滤器风格的软件体系结构中,每个构件都有一组输入和输出,构件读输入的数据流,经过内部处理,然后产生输出数据流.这个过程通常通过对输入流的变换及增量计算来完成,所以在输入被完全消费之前,输出便产生了.因此,这里的构件被称为过滤器,这种风格的连接件就象是数据流传输的管道,将一个过滤器的输出传到另一过滤器的输入.此风格特别重要的过滤器必须是独立的实体,它不能与其它的过滤器共享数据,而且一个过滤器不知道它上游和下游的标识.一个管道/过滤器网络输出的正确性并不依赖于过滤器进行增量计算过程的顺序.

云计算设计模式(十五)——管道和过滤器模式

云计算设计模式(十五)——管道和过滤器模式 分解,执行复杂处理成一系列可重复使用分立元件的一个任务.这种模式可以允许执行的处理进行部署和独立缩放任务元素提高性能,可扩展性和可重用性. 背景和问题 一个应用程序可能需要执行各种关于它处理的信息不同复杂的任务.一个简单,但不灵活的方式来实施这个应用程序可以执行此处理为单一模块.然而,这种方法有可能减少用于重构代码,对其进行优化,或者重新使用它,如果是在应用程序中其他地方所需要的相同的处理的部件的机会. 图1通过使用单片式的方式示出了与处理数据的问题.

迷你MVVM框架 avalonjs 学习教程16、过滤器

avalon的过滤器是参考自angular与rivets.它也被称做管道文本过滤器,它的处理对象只能是文本(字符串),它只能用在文本绑定中,并且只能是双花括号形式.下面是各大家的过滤器比较: rivetsjs <span rv-text="event.startDate | date"></span> <input rv-value="item.price | currency"> <span rv-text="b

过滤器--起步阶段

过滤器 1)使用AngularJS过滤器可以实现对字符串的大小写转换.货币格式的转换.数组的过滤等等. 用法:管道字符(|)+过滤器名. 1.过滤器uppercase.lowercase对字符串转换大.小写,如下所示: <div ng-app=""> 请输入: <input type="text" ng-model="name"> <p>结果为: {{ name | uppercase}}</p>

Asp.Net Core 轻松学-被低估的过滤器

前言 ????过滤器,从我们开始开发 Asp.Net 应用程序开始,就一直伴随在我们左右:Asp.Net Core 提供多种类型的过滤器,以满足多种多样的业务应用场景:并且在 Asp.Net Core 本身,过滤器的应用也非常广泛:但是,在实际的业务场景中,大部分开发人员只使用到其中 1 到 2 种类型,当然,这其中大部分可能性是由于业务场景的适用性使然,本文尝试简单介绍 Asp.Net Core 中提供的各种过滤器,以及实际的应用场景,希望对您有所帮助. 1. 介绍 1.1 作用范围 过滤器的

Angular复习笔记(一)

指令:ng-app 标记在dom上,就作用于该dom结构 =========================================== 定义初始值  指令:ng-init <div ng-app="" ng-init="quantity=1;price=5"> {{quantity}}{{price}} </div>  ——>   15 =========================================== 数

3月9日作业

一.信息系统集成有哪些特点. (1)信息系统集成要以满足用户需求为根本出发点. (2)信息系统集成不只是设备选择和供应,更重要的,它是具有高技术含量的工程 过程,要面向用户需求提供全面解决方案,其核心是软件. (3)系统集成的最终交付物是一个完整的系统而不是一个分立的产品. (4)系统集成包括技术.管理和商务等各项工作,是一项综合性的系统工程.技术 是系统集成工作的核心,管理和商务活动是系统集成项目成功实施的保障. 二.信息系统的生命周期的开发阶段又包括哪些阶段. (1)总体规划阶段:是系统开发

开发之技能

软件开发之技能梳理 编程开发本质是运用程序和计算机来解决现实中的各种问题,因此,编程开发人员的才智发挥载体是计算机或者说计算设备,直接武器是程序.程序员用来进行编程开发所需要的技能,归结起来主要如下: 1.  理解计算模型和框架: 顺序计算.并发计算 (并行计算.分布式计算): 理解应用所基于的计算模型和框架是非常重要的.传统应用通常基于顺序计算,而现代商业应用,比如云计算,通常基于分布式计算架构: 大规模的科学计算应用, 比如基因序列计算, 则基于并行计算. 2.  高效的数据处理:熟悉常用数