クロスプラットフォーム (windows と unix+xcb) の terminal+graphics_window アプリケーションを使用していますが、負荷が高いと画像が消える可能性がある入力プロンプトで長時間待機するまで、ほとんど問題なく動作します。:(
ループのたびにイベント ハンドラー関数を呼び出すインタープリター (ポストスクリプト インタープリター) 用のメインループ (REPL) があります。イベント ハンドラーは、通常はウィンドウのメッセージ/イベント ループを 1 回繰り返します。しかし、入力は通常の C i/o で処理されるため、ブロックされたときにイベント ハンドラが呼び出されることはありませんfgetc()。
グラフィックウィンドウは出力専用です。ボタンはなく、Raise、Map、Expose などのイベントに応答するだけで済みます。
コール スタックの奥深くにある入力読み取りループ中にイベント ハンドラが呼び出されるようにするにはどうすればよいですか? これは、POSIX API と win32 API の両方で実装できる必要があります。
オプションは
- Unix では比較的単純なノンブロッキング I/O 。
窓の痛みのように見える - ポーリング
- 入力スレッド
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;
}