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;
}
}
}