gpt4 book ai didi

c - 多线程应用程序中的 ncurses

转载 作者:太空狗 更新时间:2023-10-29 15:32:37 25 4
gpt4 key购买 nike

我有一个多线程应用程序,它在单个线程上使用 ncurses 向用户报告信息。我的代码基本上是这样的:

const unsigned int      refresh_cycle = 180;
unsigned int refresh_count = refresh_cycle;

while(killswitch != 1) {

if (refresh_count >= refresh_cycle) {
// critical section which obtains some data worked on by a thread. only does this once every refresh cycle times
// mtx lock, fetch, mtx unlock
refresh_count = 0;
}
refresh_count++;

// get input

// draw some stuff

// refresh
}

我注意到 ncurses 窗口刷新了很多很多次。对于可能每秒仅刷新 15-30 次的用户来说,远远超出实际需要。

但现在我担心这可能会从正在工作的线程之一“窃取”不必要的处理能力。这是一个合理的断言吗?

我是否应该使用 usleep() 构建一种帧限制器,否则会过火吗?

最佳答案

根据评论,如果在刷新之间您需要处理用户输入,那么最简单的方法可能是在 STDIN_FILENO 上调用 select()适当的小超时。当 select() 返回时,无论是因为有用户输入还是因为它超时,在那个时候进行刷新。

下面是一个示例,可让您了解如何进行设置,并显示 select() 返回的时间和次数,以便您可以直观地了解正在发生的事情。尝试让它运行一段时间,然后尝试按住一个键,观察 select() 已返回 [n] 次 消息在每种情况下的行为。代码中的注释解释了正在发生的事情:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/select.h>
#include <ncurses.h>

/* struct to store curses info for cleanup */

struct curinfo {
WINDOW * main_window;
int old_cursor;
};

/* curses helper functions */

void start_curses(struct curinfo * info);
void stop_curses(struct curinfo * info);

/* main function */

int main(int argc, char * argv[])
{
/* Set default timeout */

int secs = 0;
int usecs = 500000;

/* Set timeout based on command line args, if provided */

if ( argc > 1 ) {
if ( !strcmp(argv[1], "veryshort") ) {
secs = 0;
usecs = 200000;
}
else if ( !strcmp(argv[1], "short") ) {
secs = 1;
usecs = 0;
}
else if ( !strcmp(argv[1], "medium") ) {
secs = 2;
usecs = 0;
}
else if ( !strcmp(argv[1], "long") ) {
secs = 5;
usecs = 0;
}
}

struct curinfo cinfo;
start_curses(&cinfo);

int input = '0'; /* Set to something printable */
int num_sel = 0; /* Number of times select() has returned */

while ( input != 'q' && input != 'Q' ) {

/* Output messages */

mvprintw(3, 3, "select() has returned %d times", num_sel);
mvprintw(4, 3, "Last character input was %c", input);
mvprintw(5, 3, "Press 'q' to quit");
refresh();

/* select() modifies the fd_sets passed to it,
* so zero and set them prior to each call. */

fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);

/* Same deal for the struct timeval, select() may
* modify it, it may not, so recreate to be portable. */

struct timeval tv;
tv.tv_sec = secs;
tv.tv_usec = usecs;

/* Store the return so we can check it */

int status = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);

/* Check for error */

if ( status == -1 ) {

/* select() returned with an error. */

if ( errno != EINTR ) {

/* If interrupted by a signal, no problem,
* keep going. Otherwise, let's just quit. */

stop_curses(&cinfo);
perror("error calling select()");
return EXIT_FAILURE;
}
}
else if ( FD_ISSET(STDIN_FILENO, &fds) ) {

/* Only call getch() if input is ready.
* getch() will not block when we do it this way. */

if ( (input = getch()) == ERR ) {
stop_curses(&cinfo);
fprintf(stderr, "ERR returned from getch()\n");
return EXIT_FAILURE;
}
}

/* Increment number of times select() has returned */

++num_sel;
}

stop_curses(&cinfo);

return 0;
}

/* Starts curses and populates the passed struct */

void start_curses(struct curinfo * info)
{
if ( (info->main_window = initscr()) == NULL ) {
fprintf(stderr, "Error calling initscr()\n");
exit(EXIT_FAILURE);
}

keypad(stdscr, TRUE);
timeout(0);
raw();
nonl();
noecho();
info->old_cursor = curs_set(0);
refresh();
}

/* Stops curses and cleans up */

void stop_curses(struct curinfo * info)
{
delwin(info->main_window);
curs_set(info->old_cursor);
endwin();
refresh();
}

关于c - 多线程应用程序中的 ncurses,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26579937/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com