开发者

How to suspend/resume processing of a Lua command

I'm writing a client that can talk to multiple servers and processes user commands on stdin or eventually from a file using Lua. The server is a custom application, so I'm handling all the communication back in C where all the code for the protocol has already been written. Here's a bit of pseudo-code of what I have now:

int main(int argc, char **argv) {
  /* setup fd list, vars, etc */
  ...
  while (1) {
    开发者_JAVA技巧/* process list of file descriptors to create read/write fd sets */
    ...
    select(max, &read_fds, &write_fds, NULL, NULL);
    for each file descriptor {
      if (read fd is set) {
        read data into a buffer
        if (current fd is stdin)
          process_stdin()
        else if (current fd is from server connection)
          process_remote()
      }
      if (write fd is set) {
        write data on non-blocking fd
      }
    }
  }
}

int process_stdin() {
  luaL_loadbuffer(L, stdin_buffer, len, "stdin");
  lua_pcall(L, 0, 0, 0);
}

int process_remote() {
  parse buffer into message from remote system
  if message is complete, call Lua with either a new message notification or resume
}

So here's my problem: If the user on stdin types something like wait_for_remote_message(xyz), how do I stop at that point, return from the lua_pcall and go into the select loop to wait for more data? And then, how would process_remote resume the Lua command from that point forward?

I can imagine a solution involving pthreads, but that feels like overkill for this application and introduces a lot of extra complexity.

I can also imagine a solution where the while(1)/select loop is moved into a function and from the wait_for_remote_message(xyz) I jump back to C and call this function with stdin added to some kind of exclusion list.

Are there any better ways to do this?


This sounds like a perfect use for Lua coroutines, where you can call yield to suspend execution, and then resume later.

Check out http://www.lua.org/pil/9.html for details

You might do something like

int process_stdin() {
    lua_State coroutine =  lua_newthread(L);

    luaL_loadbuffer(coroutine, stdin_buffer, len, "stdin");
    if (lua_resume(coroutine, 0) == LUA_YIELD) {
     // store coroutine somewhere global
    }
}

int process_remote() {
    // parse buffer into message from remote system

    // push the message onto the Lua stack
    lua_resume(coroutine, 1);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜