c++ - Multithreaded console I/O -


i'm using console in multithreaded application. right now, accepts output (printf , like) , far have no issues. however, want able support console input well, , life gets complicated.

to forewarn, i'm unfamiliar more complicated nuances of working console input , output. experience in subject doesn't go further printf/cout, scanf/cin, , using setconsoletextattribute() change color (on windows).

i prefer keep program cross-compatible possible, i'm not opposed having write platform-specific code, long can find viable alternatives other platforms.

conceptually, i'd console run on it's own thread, can lock while waiting cin without freezing whole program or 1 of other threads. thread send console output thread output in clean manner (probably using thread-safe queue), , input console reads send command off appropriate thread.

my first problem while i'm typing input, output show in middle of i'm typing. solution handle reserve bottom line of console input, , have output go second last line, pushing input line down. how can this?

wellp, solved using pdcurses. in case else wants similar, here's how did it. first, initialize console thusly:

console::console(bool makeconsole) {     if (makeconsole == false)         return;      if (self)         throw ("you need 1 console - not make another!\n");     self = this;  #ifdef win32     allocconsole(); #endif     initscr();      inputline = newwin(1, cols, lines - 1, 0);     outputlines = newwin(lines - 1, cols, 0, 0);      if (has_colors())     {         start_color();         (int = 1; <= color_white; ++i)         {             init_pair(i, i, color_black);         }     }     else         wprintw(outputlines, "terminal cannot print colors.\n");      scrollok(outputlines, true);     scrollok(inputline, true);      leaveok(inputline, true);     nodelay(inputline, true);     cbreak();     noecho();     keypad(inputline, true);      initcommands();      hello("starting %s.\n", app_name);     hellomore("version %i.%i.%i.\n\n", app_majorver, app_minorver, app_revision); } 

next, function responsible handling output. it's simple, don't need special keep thread-safe. might not have encountered issues it, easy fix slap mutex on it.

void console::sendformattedmsg(short prefixcolor, const char* prefix, short color, const char* format, ...) {     if (!self)         return;      va_list args;     va_start(args, format);      if (has_colors())     {         if (prefix)         {             wattron(outputlines, a_bold | color_pair(prefixcolor));             wprintw(outputlines, prefix);         }          if (color == color_white)             wattroff(outputlines, a_bold);         wattron(outputlines, color_pair(color));         vwprintw(outputlines, format, args);          wattroff(outputlines, a_bold | color_pair(color));     }     else     {         wprintw(outputlines, prefix);         vwprintw(outputlines, format, args);     }      wrefresh(outputlines);     va_end(args); } 

and finally, input. 1 required quite bit of fine-tuning.

void console::inputloop(void) {     static string input;      wattron(inputline, a_bold | color_pair(color_white));     wprintw(inputline, "\n> ");     wattroff(inputline, a_bold | color_pair(color_white));      wprintw(inputline, input.c_str());     wrefresh(inputline);      char c = wgetch(inputline);     if (c == err)         return;      switch (c)     {     case '\n':         if (input.size() > 0)         {             sendformattedmsg(color_white, "> ", color_white, input.c_str());             cprint("\n");              executecommand(&input[0]);             input.clear();         }         break;      case 8:     case 127:         if (input.size() > 0) input.pop_back();         break;      default:         input += c;         break;     } } 

this run every frame same thread handles window messages. disabled wgetch()'s blocking behavior using nodelay(), eliminating need have console input running in it's own thread. disable echoing , echo input manually. enabling scrolling on input window allows me clear it's contents using simple "\n", replacing updated contents if user has typed anything. supports 1 expect simple, multi-threaded terminal capable typing input receiving output multiple threads.


Comments

Popular posts from this blog

php - SPIP: From Tag directly to an article -

jquery - isAjaxRequest always return false -

ruby on rails - In a controller spec, how to find a specific tag in the generated view? -