d设计事件循环

原文
结构化并发库具有严格的任务所有权概念.
或用D现有的析构器规则
异步api,最好地复制窗口API.可回调和同步.这里
我在arsd.http2中使用了类似模型,调用返回请求函数,可附加回调等,然后发送它,然后在需要时等待响应对象.我非常喜欢它,即使没有完整事件循环,也可用它,它只是根据需要一步步地执行事件循环.
我想扩展它到其他函数.但是有问题:谁负责创建这些响应和请求对象?在窗口API中,你传递指针给OVERLAPPED结构.node.jslibuv基础,也从外部传递对象指针,使你控制分配方式.
引出了问题:如果你创建了对象,为什么有个免费的读/写函数?Win32,libuv和其他人是因为在C中没有构造器和成员函数.在D中,有,因此可以把方法放在对象中.arsd.http2两样都有:client.request创建并返回请求对象,但,你也可在外部新建HttpRequest(尽管需要设置客户端才能使它正常工作,如cookie存储).
已习惯了这样的api:

ubyte[N] buffer;
auto ret = read(file, buffer.ptr, buffer.length);
//或
ubyte[N] buffer;
Request* req = malloc(Request.sizeof);
auto error = read(file, req, buffer.ptr, buffer.length);
auto response = get_async_result(req);

但可:

ubyte[N] buffer;
ReadRequest res = new ReadRequest(buffer[], new ResponseHolder());
auto response = res.get_result();

可能不必传入ResponseHolder,因为它只是请求对象的一部分.但是单独的缓冲区很好,因为这样可更轻松复用它,这是纤程一大优点.
既然需要在异步模式下分配请求对象,成员函数应很好.
顺便,我在示例中使用了new,但我倾向于@disable new();.
因此,代码如下所示:

void mytask() {
    auto timeout = scoped!Timeout(500.msecs);
    auto buffer = new ubyte[](1024*32);
    auto readRequest = scoped!ReadOperation(file, buffer);

    auto response = waitForFirstToComplete(readRequest, timeout);
    if(response is timeout)
        throw new Exception("读超时"); // 取消读取挂起,因为运行`readRequest`的析构器
    assert(response is readRequest);
    if(!readRequest.wasSuccessful)
        throw new Exception("读失败");

    auto data = readRequest.filledBuffer();
    //处理数据
    //函数返回时析构器取消超时
}
posted @ 2022-09-04 23:10  zjh6  阅读(22)  评论(0)    收藏  举报  来源