diff options
author | Frederic Culot <calcurse@culot.org> | 2010-03-21 10:17:03 +0000 |
---|---|---|
committer | Frederic Culot <calcurse@culot.org> | 2010-03-21 10:17:03 +0000 |
commit | 6892b596222bdc5b2c0757a8f6cc79bcf2691d1a (patch) | |
tree | 6e2e78054a9aafaa72e82fd8117604f646877b0f /src/wins.c | |
parent | cc77e839d86fda9871f5fde89350d51465ec208b (diff) | |
download | calcurse-6892b596222bdc5b2c0757a8f6cc79bcf2691d1a.zip |
Avoid concurrent screen refreshes.
Diffstat (limited to 'src/wins.c')
-rwxr-xr-x | src/wins.c | 80 |
1 files changed, 74 insertions, 6 deletions
@@ -1,4 +1,4 @@ -/* $calcurse: wins.c,v 1.31 2010/03/21 09:21:07 culot Exp $ */ +/* $calcurse: wins.c,v 1.32 2010/03/21 10:17:04 culot Exp $ */ /* * Calcurse - text-based organizer @@ -51,6 +51,74 @@ static unsigned sbarwidth; static enum win slctd_win; static int layout; +/* + * The screen_mutex mutex and wins_refresh(), wins_wrefresh(), wins_doupdate() + * functions are used to prevent concurrent updates of the screen. + * It was observed that the display could get screwed up when mulitple threads + * tried to refresh the screen at the same time. + * + * Note (2010-03-21): + * Since recent versions of ncurses (5.7), rudimentary support for threads are + * available (use_screen(), use_window() for instance - see curs_threads(3)), + * but to remain compatible with earlier versions, it was chosen to rely on a + * screen-level mutex instead. + */ +static pthread_mutex_t screen_mutex = PTHREAD_MUTEX_INITIALIZER; + +static unsigned +screen_acquire (void) +{ + if (pthread_mutex_lock (&screen_mutex) != 0) + return 0; + else + return 1; +} + +static void +screen_release (void) +{ + (void)pthread_mutex_unlock (&screen_mutex); +} + +int +wins_refresh (void) +{ + int rc; + + if (!screen_acquire ()) + return ERR; + rc = refresh (); + screen_release (); + + return rc; +} + +int +wins_wrefresh (WINDOW *win) +{ + int rc; + + if (!win || !screen_acquire ()) + return ERR; + rc = wrefresh (win); + screen_release (); + + return rc; +} + +int +wins_doupdate (void) +{ + int rc; + + if (!screen_acquire ()) + return ERR; + rc = doupdate (); + screen_release (); + + return rc; +} + /* Get the current layout. */ int wins_layout (void) @@ -236,7 +304,7 @@ wins_scrollwin_display (struct scrollwin *sw) wnoutrefresh (sw->win.p); pnoutrefresh (sw->pad.p, sw->first_visible_line, 0, sw->pad.y, sw->pad.x, sw->win.h - sw->pad.y + 1, sw->win.w - sw->win.x); - doupdate (); + wins_doupdate (); } void @@ -520,7 +588,7 @@ wins_update (void) if (notify_bar ()) notify_update_bar (); wmove (win[STA].p, 0, 0); - doupdate (); + wins_doupdate (); } /* Reset the screen, needed when resizing terminal for example. */ @@ -528,7 +596,7 @@ void wins_reset (void) { endwin (); - refresh (); + wins_refresh (); curs_set (0); wins_reinit (); wins_update (); @@ -559,13 +627,13 @@ wins_launch_external (const char *file, const char *cmd) endwin (); ui_mode = UI_CMDLINE; clear (); - refresh (); + wins_refresh (); (void)system (p); reset_prog_mode (); clearok (curscr, TRUE); curs_set (0); ui_mode = UI_CURSES; - refresh (); + wins_refresh (); if (notify_bar ()) notify_start_main_thread (); mem_free (p); |