第四章 管道和缓冲器

第四章 管道和缓冲器

本文译自 《TangoRefMan_Sep_1_2008.odt 》

 

管道和缓冲器是tango IO 的基础。

 

 管道(conduits)

 

Tango IO 是面向流的:每个数据最终被描述为一个Tango概念叫管道(conduits),包括InputStream和OutputStream。 例如,有一些管道用于文件、套接字(sockets)和控制台等的交互操作。一些管道要求明确的连接到终点,而另一些连接不明确(socket conduits是明确连接的一个变体)。文件和控制台管道通常是不明确地连接。有一些扩展让不同步读、写操作成为可能,通过各种具体操作系统方便的支持(见tanog.io.selector)。

 

管道是双向的,支持邻近的读和写,通过关联一个输入流(InputStream)进行读操作,通过关联一个输出流(OutputStream)进行写操作,访问分别通过管道的input()方法和output()方法。通常应用程序的交互作用是用管道流的read/write方法。每个方法接受一个无类型数组然后返回一个整数数组,描述构成量(quantitypopulated)和消耗量(consumed)。

 

注意在有些情况下,返回值少于数组长度(array-length)提供的值。实际上,保留常量IConduit.Eof返回流程末尾(end-of-flow)状态:

 

InputStream input();

OutputStream output();

 

InputStream

 

void clear();

Iconduit conduit();

uint read (void[] dst);

 

OutputStream

 

void  flush();

Iconduit   conduit();

uint  write(void[] src);

OutputStream  copy(InputStream src);

 

输出流方法(OutputStream)提供完整刷新一个数组并复制另一个管道的内容。这两种方法,可以同时完成,取决于管道末端(end-point)。

 

管道支持流过滤器的概念:一个或多个过滤器被绑到管道上,流过过滤器的数据会被拦截和改变。文件过滤器通过这些管道方法用颠倒顺序连接。返回上一个绑定的过滤器:

 

InputStream  attach(InpuStream filteer);

OutputStream  attach(OutpuStream filter);

 

管道过滤器像预期的一样链接在一起,如,一个过滤器read()方法调用它的祖先的read()方法。然而,如果看起来适合,过滤器会更改流向。过滤器基类在tango.io.Conduit模块中。

 

值得注意的是这些过滤器被有效地包容在管道自身之中,而不是把过滤器暴露出来作为IO活动的大门,这就允许管道细节(如socket属性、文件搜寻)隐藏在更少的界面之后。

 

再次提醒,管道不再需要使用时,应该被应用程序明确地关闭,以便于执行管道的清除行为并释放任何捆绑的过滤器。

 

管道异常

 

作为一个规则,管道不要乱扔异常,因为有些错误情况经常被认为是有效的。例如,IConduit.Eof一般完好无损地传回给应用程序。不过,如果底层操作系统检测到一些故障类型,异常还是会抛出。

 

 

缓冲器(Buffers)

 

缓冲一个管道应用到那里的内容相当于滑动窗口(sliding window),并且简化大多数通用操作如记号解析(token-parsing)和输出一系列相关事件,缓冲器也能提高可靠的IO应用程序的处理能力。例如 :缓冲使下面的管道读写大块的数据而不是分散的小块数据元素,它提供一个临时的空间给可靠的算法高效率地改变流内容;并且支持高效率地数据记录内容映射到用户内存。缓冲器是全双工的,它保持不同的读写存储位置——因此,当写到一个缓冲器的末尾附近时,可同时读另一个的开始部分。

 

缓冲器提供了必要的功能来处理许多类型的缓冲活动,从简单的附加操作到更平凡的生产/消费之间的管道带宽的平衡。同时也支持多个客户端。如,多于一个的reader和/或writer可能被捆绑到一个缓冲器,并且缓冲器将维护一个穿越它们(缓冲器)的常见的状态,这是非常方便的。例如 ,一个应用程序必须涉及一个混合或交叉存取(mixed or interleaved)协议(protocol)-----这样的客户端会连续操作,与并发形成对照。当使用一个没有协定的客户端时,缓冲器自身的数据类型是不可知的。这是一个聪明的数组,冲洗和/或通过管道回填本身是必要的。

 

一个缓冲器通常捆绑到一个管道,它能轻松的单独使用。如基于内存的累加器。在这些情况下,缓冲器客户端用完全相同的方式被添加,用相同的方式操作,有一个区别:一个没有绑定管道的缓冲器在填满容积时不能自动的被清仓,因此,这种情况发生时将抛出一个异常。不断增长的缓存可以用来处理这个情景。

 

一个缓冲器的通常用法包含下列方法:

 

Ibuffer append (void[] src);

uint read(void[] dst);

void[] slice();

Ibuffer fill();

Ibuffer flush();

Ibuffer clear();

Iconduit conduit();

 

这些方法通常是不常见:

 

bool truncate(uint extent);

bool truncate(uint extent);

bool next(uint delegate(void[] tokenizer);

Void[] getContent();

Ibuffer setContent(void[] content);

Ibuffer copy(Iconduit src);

Iconduit compress();

 

另一个缓冲器变体包装操作系统设施陈列内存映射文件(memory-mapped files)。缓冲内存(通常)被直接映射到一个大文件中,那个文件可以被看作刚才的那个缓冲器,或更确切地作为一个无类型数组(void [])。

 

缓冲器异常

 

当没有连接到一个管道,一个缓冲区溢出状态可能会发生,导致一个异常被抛出。在适当的地方,用一个扩大的缓冲器正确管理溢出条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值