这实际上只是一个协议栈。控制对象将创建数据处理对象(元素),并将它们与第一个元素链接在一起,第一个元素以任意大小的块从文件中读取数据,然后调用堆栈中的下一个元素对数据执行它需要做的任何操作,依此类推,直到将数据写入输出文件的最后一个元素。类似于System-V流,但在用户空间。
首先想到的是一组类,每个类都遵循一个协议,其中包含初始化、从流中读取数据、向流中写入数据以及刷新或关闭流的方法。每个元素都需要有一个指向下一个元素的(id)指针,该指针将在初始化时设置。NSStream听起来很有希望,但它似乎面向单一的数据源/接收器,而不是将数据处理元素推送到协议栈上。NSStreamDelegate协议只有-(空)流:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
有没有什么东西可以做到这一点?对于接口和实现有什么更好的建议吗?
发布于 2014-02-14 14:13:26
我将使用GCD dispatch_io_read异步处理文件中的数据,在处理程序块中处理数据,然后使用dispatch_io_write将数据异步写入文件。
您显然知道,SVr4 streams使用模块,每个模块都可以在函数调用链中处理数据,或者将消息放在队列中由另一个控制线程处理。这个控制线程基本上就是一个消息队列。
您可以使用GCD分派队列完成几乎相同的任务。如果您想提前配置它们,并对它们的执行有更多的控制,可以看看NSOperationQueue。
编辑
既然您表示对类似SVr4 STREAMS的应用编程接口感兴趣,我可以给出这段未经测试的代码。它允许你在一个流上推送任务,然后放入/putnext一段数据。
同步操作在调用者的线程中同步执行。异步操作使用GCD异步执行。注意:这只是我的一个建议,但它应该会给你一些想法……它并不代表真正的STREAMS API,但如果你正在寻找这样的东西,如果你不想使用NSOperation和朋友,这应该会帮助你。
标题...
@class Task;
typedef void(^TaskBlock)(Task *task, NSData *data);
@interface Task : NSObject
- (instancetype)initWithName:(NSString*)name
next:(Task*)nextTask
block:(TaskBlock)block;
- (void)put:(NSData*)data;
- (void)putNext:(NSData *)data;
@end
@interface STREAM : NSObject
@end实现...
@implementation Task {
dispatch_queue_t _queue;
TaskBlock _block;
Task *_next;
}
- (instancetype)initWithName:(NSString*)name
next:(Task*)nextTask
block:(TaskBlock)block
{
if (self = [super init]) {
if (name) {
_queue = dispatch_queue_create(
[name cStringUsingEncoding:NSASCIIStringEncoding],
DISPATCH_QUEUE_SERIAL);
}
_block = block;
_next = nextTask;
}
return self;
}
- (void)put:(NSData*)data
{
if (_queue) {
dispatch_async(_queue, ^{
_block(self, data);
});
} else {
_block(self, data);
}
}
- (void)putNext:(NSData *)data
{
if (_next) {
[_next put:data];
}
}
@end
@implementation STREAM {
Task *_head;
}
- (instancetype)init
{
if (self = [super init]) {
_head = [[Task alloc] initWithName:nil
next:nil
block:^(Task *module, NSData *data) {
// Do nothing
}];
}
return self;
}
- (STREAM*)pushSyncBlock:(TaskBlock)block
{
_head = [[Task alloc] initWithName:nil next:_head block:block];
return self;
}
- (STREAM*)pushAsyncBlock:(TaskBlock)block
{
_head = [[Task alloc] initWithName:@"STREAMTaskQueue"
next:_head
block:block];
return self;
}
- (void)put:(NSData *)data
{
[_head put:data];
}
@end和一个示例用法...
STREAM *stream = [[STREAM alloc] init];
[[[[stream pushAsyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the LAST block executed
[task putNext:data];
}] pushAsyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the THIRD block executed
[task putNext:data];
}] pushSyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the SECOND block executed
[task putNext:data];
}] pushAsyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the FIRST block executed
[task putNext:data];
}];
[stream put:nil];STREAMS API总是将模块推送到流上,但您可以通过执行以下操作将API更改为上面代码的正确顺序...
[[[[stream pushFrontAsyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the FIRST block executed
[task putNext:data];
}] pushFrontAsyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the SECOND block executed
[task putNext:data];
}] pushFrontSyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the THIRD block executed
[task putNext:data];
}] pushFrontAsyncBlock:^(Task *task, NSData *data) {
// Do something with the data -- this is the LAST block executed
[task putNext:data];
}];https://stackoverflow.com/questions/21771544
复制相似问题