Как приостановить / возобновить обработку команды Lua - PullRequest
2 голосов
/ 27 мая 2011

Я пишу клиент, который может общаться с несколькими серверами и обрабатывать пользовательские команды на stdin или, в конечном итоге, из файла, используя Lua.Сервер - это пользовательское приложение, поэтому я обрабатываю все сообщения обратно в C, где весь код протокола уже написан.Вот немного псевдокода того, что у меня сейчас есть:

int main(int argc, char **argv) {
  /* setup fd list, vars, etc */
  ...
  while (1) {
    /* 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
}

Итак, вот моя проблема: если пользователь на stdin печатает что-то вроде wait_for_remote_message(xyz), как мне остановиться в этой точке, вернутьиз lua_pcall и перейдите в цикл select, чтобы ждать больше данных?И затем, как process_remote возобновит команду Lua с этого момента вперед?

Я могу представить решение, включающее pthreads, но для этого приложения это кажется излишним и вводит много дополнительной сложности.

Я также могу представить решение, в котором цикл while(1)/select перемещается в функцию, и из wait_for_remote_message(xyz) я возвращаюсь к C и вызываю эту функцию с добавлением stdin в какой-то список исключений.

Есть ли лучшие способы сделать это?

1 Ответ

4 голосов
/ 27 мая 2011

Это звучит как идеальное использование для сопрограмм Lua, где вы можете вызвать yield, чтобы приостановить выполнение, а затем возобновить позже.

Проверьте http://www.lua.org/pil/9.html для подробностей

Вы можете сделать что-то вроде

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...