summaryrefslogtreecommitdiff
path: root/src/wins.c
diff options
context:
space:
mode:
authorFrederic Culot <calcurse@culot.org>2010-03-21 10:17:03 +0000
committerFrederic Culot <calcurse@culot.org>2010-03-21 10:17:03 +0000
commit6892b596222bdc5b2c0757a8f6cc79bcf2691d1a (patch)
tree6e2e78054a9aafaa72e82fd8117604f646877b0f /src/wins.c
parentcc77e839d86fda9871f5fde89350d51465ec208b (diff)
downloadcalcurse-6892b596222bdc5b2c0757a8f6cc79bcf2691d1a.zip
Avoid concurrent screen refreshes.
Diffstat (limited to 'src/wins.c')
-rwxr-xr-xsrc/wins.c80
1 files changed, 74 insertions, 6 deletions
diff --git a/src/wins.c b/src/wins.c
index 8cdd9da..cfe1050 100755
--- a/src/wins.c
+++ b/src/wins.c
@@ -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);