1

I'm trying to write code where the screen is divided into two windows and one of them is modified by a different thread, but output seems to be very random. Could anyone help? Upper piece of console should be modified by main, and lower by thread k.

#include <stdio.h>
#include <ncurses.h>
#include <unistd.h>
#include <thread>
#define WIDTH 30
#define HEIGHT 10 

int startx = 0;
int starty = 0;
void kupa (int score_size, int parent_x, int parent_y)
{
    int i = 0;
    WINDOW *dupa = newwin(score_size, parent_x, parent_y - score_size, 0);
    while(true)
    {

        i++;

        mvwprintw(dupa, 0 , 0, "You chose choice %d with choice string", i);
        wrefresh(dupa);  
        sleep(5);
        wclear(dupa);
    }
    delwin(dupa);
}
int main ()
{
      int parent_x, parent_y;
      int score_size =10;
      int counter =0 ;
      initscr();
      noecho();
      curs_set(FALSE);
      getmaxyx(stdscr, parent_y, parent_x);
      WINDOW *field = newwin(parent_y - score_size, parent_x, 0, 0);
      std::thread k (kupa, score_size, parent_x, parent_y);
      while(true) {
          mvwprintw(field, 0, counter, "Field");
          wrefresh(field);
          sleep(5);
          wclear(field);
          counter++;
      }
      k.join();
      delwin(field);
}
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
sweet_sugar
  • 1,390
  • 3
  • 13
  • 22
  • 1
    What *exactly* is the issue you are having? Errors? What happens? What do you mean by "random"? A little more information would be *very* helpful... – hlt Apr 09 '15 at 18:16

2 Answers2

3

The underlying curses/ncurses library is not thread-safe (see for example What is meant by “thread-safe” code? which discusses the term). In the case of curses, this means that the library's WINDOW structures such as stdscr are global variables which are not guarded by mutexes or other methods. The library also has internal static data which is shared across windows. You can only get reliable results for multithreaded code using one of these strategies:

  • do all of the window management (including input) within one thread
  • use mutexes, semaphores or whatever concurrency technique seems best to manage separate threads which "own" separate windows. To succeed here, a thread would have to own the whole screen from the point where the curses library blocks while waiting for input, until it updates the screen and resumes waiting for input. That is harder than it sounds.

ncurses 5.7 and up can be compiled to provide rudimentary support for reentrant code and some threaded applications. To do this, it uses mutexes wrapped around its static data, makes the global variables into "getter" functions, and adds functions which explicitly pass the SCREEN pointer which is implied in many calls. For more detail, see the manual page.

Some of ncurses' test-programs illustrate the threading support (these are programs in the test subdirectory of the sources):

  • ditto shows use_screen.
  • test_opaque execises the "getters" for WINDOW properties
  • rain shows use_window
  • worm shows use_window
Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
1

I am not sure what you want to do but this behaviour is quite normal. The thread that is active writes to the window and when the system makes a task switch the other thread writes to the window. Normal behaviour is to use only one thread that writes to the window. Other threads are supposed to do only some work. Anyway, if you are using more than one thread you have to synchronize them using events, mutexes, queues, semaphores or other methods.

watfy
  • 124
  • 1
  • 2