Thread to watch keyboard during main's infinite loop

Daren Scot Wilson darenw at darenscotwilson.com
Thu May 7 00:13:00 UTC 2020


I'm writing a simple command line tool to send data by UDP once 
per second forever, to test some software on another machine.  
Not actually forever, of course, but until ^C or I hit 'Q'. I 
want to tap keys to make other things happen, like change the 
data or rate of sending.

Not sure of the best way to do this. Thought I'd try a thread 
whose job is just to loop, calling readln() or getch() or 
something similar, and setting a global variables according to 
what key was tapped.  The loop in the main thread can then break, 
or do some other action, according to the value of that variable.

Code I have written is below, stripped to just the stuff relevant 
to key watching. It doesn't work.  When it runs, it prints 
"Repetitive work" over and over, but never see anything appear in 
"cmd [ ]".  When I tap 'A' I expect to see "cmd [A]" and a line 
of several 'A'.  This does not happen.  But the writeln in 
cmdwatcher() does show whatever I typed just fine.

How to fix this, or redesign the whole thing to work?

Note that I'm coming from science and fine art. My know-how in 
computer science is uneven, and I probably have gaps in my 
knowledge about threads.


import std.stdio;
import core.stdc.stdio;  // for getchar().  There's nothing 
similar in D std libs?
import std.concurrency;
import core.thread; // just for sleep()

bool running=true;
char command = '?';

void cmdwatcher()
{
     writeln("Key Watcher");
     while (running)  {
         char c = cast(char)getchar();
         if (c>=' ')  {
             command = c;
             writefln("     key %c  %04X", c, c);
         }
     }
}

void main()
{
     writeln("Start main");
     spawn(&cmdwatcher);

     while (running) {
         writeln("Repetitive work");
         Thread.sleep( dur!("msecs")( 900 ) );

         char cmd = command;  // local copy can't change during 
rest of this loop
         command = ' ';
         writefln("cmd [%c]  running %d", cmd, running);

         switch (cmd)
         {
             case 'A':
                     writeln("A A A A A");
                     break;

             case 'Q':
                     writeln("Quitting");
                     running=false;
                     break;
             default:
                 break;
         }
     }
}







More information about the Digitalmars-d-learn mailing list