Why has no one written a threadsafe branch of the ncurses library?

ぃ、小莉子 提交于 2019-11-28 11:40:31

问题


NCurses appears to be a popular library. One of its weaknesses is, that it is not threadsafe. It should not be hard to wrap shared ressources in mutexes.

Is there a specific reason, why noone has started a threadsafe branch? (Legal issues, introducing a platform dependency, ...)

Edit: I do not mean the use_screen or use_window functions. These apparently require the user to change his NCurses-based code. It should be possible to add a mutex to the shared resources within the NCurses itself, and all accessing functions acquire the mutex before doing something with the window. I am imagining something like this within NCurses:

#if __cplusplus >= 201103L
#include <mutex>
#define THREADSAFE
#endif
...
#ifdef THREADSAFE
std::recursive_mutex  mxCurscr;
#endif
...
int doupdate(void)
{
#ifdef THREADSAFE
mxCurscr.lock();
#endif
... // <-- Access the screen here.
#ifdef THREADSAFE
mxCurscr.unlock()
#endif
}
  • This does not rely on anything but the C++11 standard.
  • This is compatible with older compilers. (But no threadsafety then.)
  • It should not take more than one or two days to make the modifications.
  • This satisfies the demand for a threadsafe NCurses.
  • The user of the NCurses library will not have to bother.
  • The work is being done one time for all users, instead of having every user implementing its own thread-safety.

So, where is the catch?


回答1:


It's already been done (in ncurses 5.7, released November 2008), but not much used. See the curs_threads manual page for instance. It is not a feature in the default configuration because it

  • changes the ABI (application binary interface), and
  • adds some restrictions on how standard variables are used.



回答2:


Thread-safe code looks like this.

#include <stdio.h>
#include <ncurses.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>

pthread_mutex_t MUTEX;  /* mutex for sync display */

#define LOCK pthread_mutex_lock(&MUTEX)
#define UNLOCK pthread_mutex_unlock(&MUTEX)

typedef struct _WIN_struct {
    int startx, starty;
    int height, width;
} WIN;

WIN winTitle;      /* title win */
WIN winMenu;   /* Main menu win */
WIN winNews;       /* win news */

WINDOW *create_newwin(int height, int width, int starty, int startx) {
    WINDOW *local_win;
    local_win = newwin(height, width, starty, startx);
    box(local_win, 0, 0);
    wrefresh(local_win);
    return local_win;
}

char *getTimeNow() {
    time_t rawtime;
    struct tm *timeinfo;
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    return asctime(timeinfo);
}

void *threadfunc_title(void *p) {
    WINDOW *windowTitle;
    LOCK;
    windowTitle = create_newwin(winTitle.height, winTitle.width, winTitle.starty, winTitle.startx);
    UNLOCK;

    /* show title and time */
    for (;;) {
        sleep(1);
    }

}

void *threadfunc_menu(void *p) {
    WINDOW *windowMenu;
    LOCK;
    windowMenu = create_newwin(winMenu.height, winMenu.width, winMenu.starty, winMenu.startx);
    UNLOCK;

    for (;;) {
        /* now do nothing */
        sleep(1);
    }

}

void *threadfunc_news(void *p) {
    WINDOW *windowNews;
    LOCK;
    windowNews = create_newwin(winNews.height, winNews.width, winNews.starty, winNews.startx);
    UNLOCK;

    for (;;) {
        sleep(1);
    }
}

void initWin(WIN *p_win, int height, int width, int starty, int startx) {
    p_win->height = height;
    p_win->width = width;
    p_win->starty = starty;
    p_win->startx = startx;
}


int main(int argc, char *argv[])
{
    pthread_t pidTitle;
    pthread_t pidMenu;
    pthread_t pidNews;

    initscr();
    start_color();
    cbreak();
    keypad(stdscr, TRUE);
    noecho();

    /* init location */
    initWin(&winTitle, LINES*0.25, COLS, 0 , 0);
    initWin(&winMenu, LINES*0.75, COLS*0.60, LINES*0.25, 0);
    initWin(&winNews, LINES*0.75, COLS*0.40, LINES*0.25, COLS*0.60);

    pthread_create(&pidTitle, NULL, threadfunc_title, NULL);
    pthread_create(&pidMenu, NULL, threadfunc_menu, NULL);
    pthread_create(&pidNews, NULL, threadfunc_news, NULL);

    pthread_join(pidTitle, NULL);
    pthread_join(pidMenu, NULL);
    pthread_join(pidNews, NULL);

    endwin();
    return 0;
}


来源:https://stackoverflow.com/questions/29910562/why-has-no-one-written-a-threadsafe-branch-of-the-ncurses-library

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!