我有一个跨平台的应用程序(Windows和Unix + xcb),它包含终端和图形窗口,并且大多数情况下都正常工作,但如果您在输入提示符处等待时间过长,在重负载下图像可能会消失。 :(
我为解释器(Postscript解释器)编写了一个主循环(REPL),每次在其循环中调用事件处理程序函数。该事件处理程序执行通常是窗口消息/事件循环的迭代之一。但是输入使用普通的C I/O处理,因此当在fgetc()
阻塞时,事件处理程序永远不会被调用。
图形窗口仅输出内容。它没有按钮,并且只需要响应Raise、Map、Expose等事件。
如何安排在调用堆栈中更深的输入读取循环期间调用事件处理程序?这需要能够使用POSIX和win32 API实现。
选项似乎是
- 非阻塞I/O
在Unix中相对简单,看起来在Windows上很麻烦 - 轮询
- 输入线程
pthreads? - 窗口线程
pthreads?
这些选项中是否有任何一个比其他选项更容易实现?
如果我可以一直使用Unix,那么这似乎就能解决所有问题:
#include <errno.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
void idleproc () { /* simulates calling the event handler
(ie. one slice of the window loop) */
//printf("idle\n");
putchar('.');
}
int idlefgetc (FILE *stream) {
int ret;
do {
ret = fgetc(stream);
idleproc();
} while(ret == EOF &&
(errno == EAGAIN || errno == EINTR));
return ret;
}
int setraw (FILE *stream) {
struct termios tbuf;
if (tcgetattr(fileno(stream), &tbuf) == -1)
return -1;
tbuf.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
tbuf.c_oflag &= ~OPOST;
tbuf.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tbuf.c_cflag &= ~(CSIZE | PARENB);
tbuf.c_cflag |= CS8;
if (tcsetattr(fileno(stream), TCSANOW, &tbuf) == -1)
return -1;
return 0;
}
int setnonblocking (FILE *stream) {
int flags;
if (setraw(stream) != 0)
return -1;
if (!((flags = fcntl(fileno(stream), F_GETFL)) & O_NONBLOCK)) {
flags |= O_NONBLOCK;
fcntl(fileno(stream), F_SETFL, flags);
}
return 0;
}
int main (int argc, char **argv) {
if (setnonblocking(stdin)) {
perror(argv[0]);
return 0;
}
printf("'%d'\n", idlefgetc(stdin));
system("stty sane");
return 0;
}
getch
的技术,该技术在我的答案中有描述。 - luser droog