Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Select 计划一个异步事件,该事件将在stdin在boost::asio中有等待数据时完成?_Select_Boost_Boost Asio_Stdin_Ncurses - Fatal编程技术网

Select 计划一个异步事件,该事件将在stdin在boost::asio中有等待数据时完成?

Select 计划一个异步事件,该事件将在stdin在boost::asio中有等待数据时完成?,select,boost,boost-asio,stdin,ncurses,Select,Boost,Boost Asio,Stdin,Ncurses,我将boost::asio与ncurses一起用于命令行游戏。游戏需要以固定的时间间隔在屏幕上绘制,必要时也会执行其他操作(如网络或文件操作)。所有这些事情都可以通过boost::asio上的async\u read()/async\u write()或等效工具来完成 然而,我还需要读取键盘输入,我认为它来自标准输入法。在ncurses中读取输入的常用方法是调用getch(),可以将其配置为阻塞(等待有字符可供使用)或非阻塞(返回无字符可用的sentinel值)模式 使用阻塞模式将需要在单独的线

我将boost::asio与ncurses一起用于命令行游戏。游戏需要以固定的时间间隔在屏幕上绘制,必要时也会执行其他操作(如网络或文件操作)。所有这些事情都可以通过boost::asio上的
async\u read()
/
async\u write()
或等效工具来完成

然而,我还需要读取键盘输入,我认为它来自标准输入法。在ncurses中读取输入的常用方法是调用
getch()
,可以将其配置为阻塞(等待有字符可供使用)或非阻塞(返回无字符可用的sentinel值)模式

使用阻塞模式将需要在单独的线程上运行
getch()
,这对ncurses不起作用。然而,使用非阻塞模式会导致我的应用程序在循环中消耗CPU时间,直到用户按下键盘。我已经阅读了答案,它建议我们可以在
select()
调用中将
stdin
添加到文件描述符列表中,直到其中一个文件描述符有新数据为止


因为我使用的是boost::asio,所以不能直接使用
select()
。我无法调用
async\u read
,因为这将消耗字符,使
getch()
无需读取。boost::asio中是否有类似于
async\u read
,但只检查输入的存在而不使用它?

我认为您应该能够使用posix流描述符来监视文件描述符
0
上的输入:

ba::posix::stream_descriptor d(io, 0);
input_loop = [&](error_code ec) {
    if (!ec) {
        program.on_input();
        d.async_wait(ba::posix::descriptor::wait_type::wait_read, input_loop);
    }
};
在那里,
program::on_input()
将调用
getch()
,无
timeout()
,直到返回
ERR

struct Program {
    Program() {
        initscr();
        ESCDELAY = 0;
        timeout(0);
        cbreak(); 

        noecho();
        keypad(stdscr, TRUE); // receive special keys

        clock   = newwin(2, 40, 0, 0);
        monitor = newwin(10, 40, 2, 0);

        syncok(clock, true);    // automatic updating
        syncok(monitor, true);

        scrollok(monitor, true); // scroll the input monitor window
    }
    ~Program() {
        delwin(monitor);
        delwin(clock);
        endwin();
    }

    void on_clock() {
        wclear(clock);

        char buf[32];
        time_t t = time(NULL);
        if (auto tmp = localtime(&t)) {
            if (strftime(buf, sizeof(buf), "%T", tmp) == 0) {
                strncpy(buf, "[error formatting time]", sizeof(buf));
            }
        } else {
            strncpy(buf, "[error getting time]", sizeof(buf));
        }

        wprintw(clock, "Async: %s", buf);
        wrefresh(clock);
    }

    void on_input() {
        for (auto ch = getch(); ch != ERR; ch = getch()) {
            wprintw(monitor, "received key %d ('%c')\n", ch, ch);
        }
        wrefresh(monitor);
    }

    WINDOW *monitor = nullptr;
    WINDOW *clock = nullptr;
};
使用以下
main
程序,您可以运行它10秒钟(因为
program
还不知道如何退出):

intmain(){
程序;
名称空间ba=boost::asio;
使用boost::system::error\u代码;
使用名称空间std::literals;
ba::io_服务io;
std::功能输入环路、时钟环路;
//在标准输入上准备就绪时读取输入
ba::posix::流描述符d(io,0);
输入循环=[&](错误代码ec){
如果(!ec){
program.on_input();
d、 异步等待(ba::posix::描述符::等待类型::等待读取,输入循环);
}
};
//为了好玩,让我们也更新一下时间
ba:高分辨率定时器tim(io);
时钟循环=[&](错误代码ec){
如果(!ec){
program.on_clock();
tim.从现在起过期(100ms);
异步等待(时钟循环);
}
};
输入循环(错误代码{});
时钟循环(错误代码{});
io.运行(10秒);
}
这项工作:

完整列表
#包括
#包括
#包括
#包括“ncurses.h”
#定义CTRL\u R 18
#定义CTRL\U C 3
#定义选项卡9
#定义换行符10
#定义返回13
#定义逃逸27
#定义退格127
#定义最多72个
#定义左75
#定义权利77
#下定义80
结构程序{
程序(){
initscr();
ESCDELAY=0;
超时(0);
cbreak();
noecho();
键盘(stdscr,TRUE);//接收特殊键
时钟=纽温(2,40,0,0);
monitor=newwin(10,40,2,0);
syncok(时钟,真);//自动更新
syncok(监视器,真);
scrollok(监视器,true);//滚动输入监视器窗口
}
~Program(){
德尔温(班长);
德尔温(时钟);
endwin();
}
在时钟()上无效{
wclear(时钟);
char-buf[32];
时间t=时间(空);
if(自动tmp=localtime(&t)){
if(strftime(buf,sizeof(buf),“%T”,tmp)==0){
strncpy(buf,“[错误格式化时间]”,sizeof(buf));
}
}否则{
strncpy(buf,“[获取时间时出错]”,sizeof(buf));
}
wprintw(时钟,“异步:%s”,buf);
(时钟);
}
输入时无效(){
for(auto ch=getch();ch!=ERR;ch=getch()){
wprintw(监视器,“已接收密钥%d(“%c”)\n”,ch,ch);
}
新鲜水(监测);;
}
窗口*监视器=空PTR;
窗口*时钟=空PTR;
};
int main(){
程序;
名称空间ba=boost::asio;
使用boost::system::error\u代码;
使用名称空间std::literals;
ba::io_服务io;
std::功能输入环路、时钟环路;
//在标准输入上准备就绪时读取输入
ba::posix::流描述符d(io,0);
输入循环=[&](错误代码ec){
如果(!ec){
program.on_input();
d、 异步等待(ba::posix::描述符::等待类型::等待读取,输入循环);
}
};
//为了好玩,让我们也更新一下时间
ba:高分辨率定时器tim(io);
时钟循环=[&](错误代码ec){
如果(!ec){
program.on_clock();
tim.从现在起过期(100ms);
异步等待(时钟循环);
}
};
输入循环(错误代码{});
时钟循环(错误代码{});
io.运行(10秒);
}

这似乎在这里起作用,我没有意识到
boost::asio::posix::stream\u descriptor
had
async\u wait()
。对于Windows,我使用了
boost::asio::Windows::object\u handle(ctx,GetStdHandle(STD\u INPUT\u handle))
,它有一个类似的
async\u wait()
函数。在较旧的Boost版本中,存在仍然需要
async\u读取
async\u写入
。因此,新的界面显然更好(据我所知,这是网络TS的一部分)
int main() {
    Program program;

    namespace ba = boost::asio;
    using boost::system::error_code;
    using namespace std::literals;

    ba::io_service io;
    std::function<void(error_code)> input_loop, clock_loop;

    // Reading input when ready on stdin
    ba::posix::stream_descriptor d(io, 0);
    input_loop = [&](error_code ec) {
        if (!ec) {
            program.on_input();
            d.async_wait(ba::posix::descriptor::wait_type::wait_read, input_loop);
        }
    };

    // For fun, let's also update the time
    ba::high_resolution_timer tim(io);
    clock_loop = [&](error_code ec) {
        if (!ec) {
            program.on_clock();
            tim.expires_from_now(100ms);
            tim.async_wait(clock_loop);
        }
    };

    input_loop(error_code{});
    clock_loop(error_code{});
    io.run_for(10s);
}
#include <boost/asio.hpp>
#include <boost/asio/posix/descriptor.hpp>
#include <iostream>
#include "ncurses.h"

#define CTRL_R    18
#define CTRL_C    3
#define TAB       9
#define NEWLINE   10
#define RETURN    13
#define ESCAPE    27
#define BACKSPACE 127
#define UP        72
#define LEFT      75
#define RIGHT     77
#define DOWN      80

struct Program {
    Program() {
        initscr();
        ESCDELAY = 0;
        timeout(0);
        cbreak(); 

        noecho();
        keypad(stdscr, TRUE); // receive special keys

        clock   = newwin(2, 40, 0, 0);
        monitor = newwin(10, 40, 2, 0);

        syncok(clock, true);    // automatic updating
        syncok(monitor, true);

        scrollok(monitor, true); // scroll the input monitor window
    }
    ~Program() {
        delwin(monitor);
        delwin(clock);
        endwin();
    }

    void on_clock() {
        wclear(clock);

        char buf[32];
        time_t t = time(NULL);
        if (auto tmp = localtime(&t)) {
            if (strftime(buf, sizeof(buf), "%T", tmp) == 0) {
                strncpy(buf, "[error formatting time]", sizeof(buf));
            }
        } else {
            strncpy(buf, "[error getting time]", sizeof(buf));
        }

        wprintw(clock, "Async: %s", buf);
        wrefresh(clock);
    }

    void on_input() {
        for (auto ch = getch(); ch != ERR; ch = getch()) {
            wprintw(monitor, "received key %d ('%c')\n", ch, ch);
        }
        wrefresh(monitor);
    }

    WINDOW *monitor = nullptr;
    WINDOW *clock = nullptr;
};

int main() {
    Program program;

    namespace ba = boost::asio;
    using boost::system::error_code;
    using namespace std::literals;

    ba::io_service io;
    std::function<void(error_code)> input_loop, clock_loop;

    // Reading input when ready on stdin
    ba::posix::stream_descriptor d(io, 0);
    input_loop = [&](error_code ec) {
        if (!ec) {
            program.on_input();
            d.async_wait(ba::posix::descriptor::wait_type::wait_read, input_loop);
        }
    };

    // For fun, let's also update the time
    ba::high_resolution_timer tim(io);
    clock_loop = [&](error_code ec) {
        if (!ec) {
            program.on_clock();
            tim.expires_from_now(100ms);
            tim.async_wait(clock_loop);
        }
    };

    input_loop(error_code{});
    clock_loop(error_code{});
    io.run_for(10s);
}