整洁code为异步IO [英] tidy code for asynchronous IO

查看:123
本文介绍了整洁code为异步IO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然异步IO(无阻塞描述选择/投票/ epoll的/ kqueue的等)不在网络上最记载的东西,也有很好的例子屈指可数。

Whilst asynchronous IO (non-blocking descriptors with select/poll/epoll/kqueue etc) is not the most documented thing on the web, there are a handful of good examples.

然而,所有这些例子中,已经确定由该调用返回的句柄,只是有一个 do_some_io(FD)存根。它们并不真正解释如何最好接近实际的异步IO在这样的方法

However, all these examples, having determined the handles that are returned by the call, just have a 'do_some_io(fd)' stub. They don't really explain how to best approach the actual asynchronous IO in such a method.

阻塞IO很整洁,简单的阅读code。非阻塞,异步IO是,在另一方面,有毛和杂乱。

Blocking IO is very tidy and straightforward to read code. Non-blocking, async IO is, on the other hand, hairy and messy.

有什么办法呢?什么是稳健和可读性?

What approaches are there? What are robust and readable?

void do_some_io(int fd) {
  switch(state) {
    case STEP1:
       ... async calls
       if(io_would_block)
          return;
       state = STEP2;
    case STEP2:
       ... more async calls
       if(io_would_block)
          return;
       state = STEP3;
    case STEP3:
       ...
  }
}

或者(AB)使用GCC的计算转移:

or perhaps (ab)using GCC's computed gotos:

#define concatentate(x,y) x##y
#define async_read_xx(var,bytes,line)       \
   concatentate(jmp,line):                  \
   if(!do_async_read(bytes,&var)) {         \
       schedule(EPOLLIN);                   \
       jmp_read = &&concatentate(jmp,line); \
       return;                              \
}

// macros for making async code read like sync code
#define async_read(var,bytes) \
    async_read_xx(var,bytes,__LINE__)

#define async_resume()            \
     if(jmp_read) {               \
         void* target = jmp_read; \
         jmp_read = NULL;         \
         goto *target;            \
     }

void do_some_io() {
   async_resume();
   async_read(something,sizeof(something));
   async_read(something_else,sizeof(something_else));
}

或许C ++异常和状态机,所以工人功能可以触发中止/恢复位,或者表驱动的状态机?

Or perhaps C++ exceptions and a state machine, so worker functions can trigger the abort/resume bit, or perhaps a table-driven state-machine?

它不是如何使它工作,它如何使维护了我追逐!

Its not how to make it work, its how to make it maintainable that I'm chasing!

推荐答案

我建议采取一看: HTTP:// WWW。 kegel.com/c10k.html ,第二次取像libevent的,现有的库看看Boost.Asio的已经做的工作​​,看看他们是如何工作的。

I suggest take a look on: http://www.kegel.com/c10k.html, second take a look on existing libraries like libevent, Boost.Asio that already do the job and see how they work.

的一点是,该方法可以是对每种类型的系统调用的不同:

The point is that the approach may be different for each type of system call:


  • 选择简单反应堆

  • epoll的既有边沿或电平触发,需要不同的方法接口

  • IOCP是摄需要其他的方法

建议:用好现有的库象Boost.Asio的为C ++或libevent的对C

Suggestion: use good existing library like Boost.Asio for C++ or libevent for C.

编辑:这是ASIO如何处理这种

This is how ASIO handles this

class connection {
   boost::asio:ip::tcp::socket socket_;
public:
   void run()
   {
         // for variable length chunks
         async_read_until(socket_,resizable_buffer,'\n',
               boost::bind(&run::on_line_recieved,this,errorplacehplder);
         // or constant length chunks
         async_read(socket_,buffer(some_buf,buf_size),
               boost::bind(&run::on_line_recieved,this,errorplacehplder);
   }
   void on_line_recieved(error e)
   {
        // handle it
        run();
   }

};

由于ASIO的工作原理摄通知您,当操作完成,
处理EWOULDBLOCK内部。

Because ASIO works as proactor it notifies you when operation is complete and handles EWOULDBLOCK internally.

如果你作为反应堆字,你可以模仿这种行为:

If you word as reactor you may simulate this behavior:

 class conn {
    // Application logic

    void run() {
       read_chunk(&conn::on_chunk_read,size);
    }
    void on_chunk_read() {
         /* do something;*/
    }

    // Proactor wrappers

    void read_chunk(void (conn::*callback),int size, int start_point=0) {
       read(socket,buffer+start,size)
       if( complete )
          (this->*callback()
       else {
          this -> tmp_size-=size-read;
          this -> tmp_start=start+read;
          this -> tmp_callback=callback
          your_event_library_register_op_on_readable(callback,socket,this);
       }
    }
    void callback()
    {
       read_chunk(tmp_callback,tmp_size,tmp_start);
    }
 }

类似的东西。

这篇关于整洁code为异步IO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆