ncurses多线程读写的解决方法

问题描述:

这就是 http://invisible-island.net/上的内容ncurses/ncurses.faq.html#multithread

如果您有一个在多个线程中使用curses的程序,则几乎可以肯定会看到奇怪的行为.那是因为curses依赖于静态变量的输入和输出.使用一个线程进行输入而其他线程进行输出无法解决该问题,也无法提供额外的屏幕更新帮助.此常见问题解答不是有关线程编程的教程.

If you have a program which uses curses in more than one thread, you will almost certainly see odd behavior. That is because curses relies upon static variables for both input and output. Using one thread for input and other(s) for output cannot solve the problem, nor can extra screen updates help. This FAQ is not a tutorial on threaded programming.

具体地说,它提到即使输入和输出是在单独的线程上完成也不安全.如果我们在整个ncurses库中进一步使用互斥锁,这样一个线程最多一次可以调用任何ncurses函数,这是否安全?如果没有,那么在多线程应用程序中安全使用ncurses的其他便宜的解决方法是什么?

Specifically, it mentions it is not safe even if input and output are done on separate threads. Would it be safe if we further use a mutex for the whole ncurses library so that at most one thread can be calling any ncurses function at a time? If not, what would be other cheap workarounds to use ncurses safely in multi-thread application?

我之所以问这个问题,是因为我注意到一个真实的应用程序通常具有其自己的事件循环,但是依靠ncurses getch函数来获取键盘输入.但是,如果主线程在其自己的事件循环中处于等待块状态,则它没有机会调用getch.一种看似适用的解决方案是在另一个线程中调用getch,这尚未引起我任何问题,但是正如上面所说的,这实际上并不安全,并且已由另一个用户

I'm asking this question because I notice a real application often has its own event loop but relies on ncurses getch function to get keyboard input. But if the main thread is block waiting in its own event loop, then it has no chance to call getch. A seemingly applicable solution is to call getch in a different thread, which hasn't caused me a problem yet, but as what says above is actually not safe, and was verified by another user here. So I'm wondering what is the best way to merge getch into an application's own event loop.

我正在考虑将getch设置为非阻塞状态,并定期(每10-100毫秒)唤醒主线程,以检查是否有需要读取的内容.但这在关键事件之间增加了额外的延迟,并使应用程序的响应速度降低.另外,我不确定这是否会引起某些ncurses内部延迟(例如ESCDELAY)的任何问题.

I'm considering making getch non-blocking and waking up the main thread regularly (every 10-100 ms) to check if there is something to read. But this adds an additional delay between key events and makes the application less responsive. Also, I'm not sure if that would cause any problems with some ncurses internal delay such as ESCDELAY.

我正在考虑的另一种解决方案是直接轮询stdin.但是我想ncurses也应该做类似的事情,并且从两个不同的地方读取相同的流看起来很糟糕.

Another solution I'm considering is to poll stdin directly. But I guess ncurses should also be doing something like that and reading the same stream from two different places looks bad.

文本还提到了"ncursest"或"ncursestw"库,但是它们似乎不那么可用,例如,如果您使用的是curses的不同语言绑定.如果标准ncurses库有可行的解决方案,那就太好了.

The text also mentions the "ncursest" or "ncursestw" libraries, but they seem to be less available, for example, if you are using a different language binding of curses. It would be great if there is a viable solution with the standard ncurses library.

在没有线程支持的情况下,您无法在多个线程中使用curses函数.这是因为大多数curses调用都使用静态或全局数据.例如,getch函数调用refresh,它可以使用全局指针 curscr stdscr 来更新整个屏幕.线程支持配置的不同之处在于,将全局值转换为函数,并添加了互斥锁.

Without the thread-support, you're out of luck for using curses functions in more than one thread. That's because most of the curses calls use static or global data. The getch function for instance calls refresh which can update the whole screen—using the global pointers curscr and stdscr. The difference in the thread-support configuration is that global values are converted to functions and mutex's added.

如果您想从其他线程中读取 stdin 并在一个线程中运行 curses ,则可以通过检查 文件来使其正常工作描述符 (即 0 ),以提醒未决的活动并提醒运行curses的线程告诉其读取数据.

If you want to read stdin from a different thread and run curses in one thread, you probably can make that work by checking the file descriptor (i.e., 0) for pending activity and alerting the thread which runs curses to tell it to read data.