-
Notifications
You must be signed in to change notification settings - Fork 89
Interactive Chord Example
caseymarquis edited this page Jul 23, 2012
·
1 revision
What we have here is a basic client-server model where commands are entered in one thread and processed in another. It provides an interactive example of how to use chords. It might be a good idea to compile and play with it before analyzing it.
It has four main parts:
- initialization code
- a chord
- a method run in a client thread where commands are entered
- a method run in a server thread where commands are processed
using System.Console;
using System.Threading;
using Nemerle.Concurrency;
module EntryPoint{
public Main() : void{
_ = ClientServerCalculator(); //Go to the class's constructor to follow along.
}
}
class ClientServerCalculator
{
serverThread : Thread;
clientThread : Thread;
mutable running : bool = true;
mutable suspended : bool = false;
public this() {
serverThread = Thread(ThreadStart(this.RunServerLoop)); //Starts RunServerLoop in its own thread.
clientThread = Thread(ThreadStart(this.EnterCmdLoop)); //Starts EnterCmdLoop in its own thread.
serverThread.Start(); //Start the threads
while(!serverThread.IsAlive){Thread.Sleep(10)}
clientThread.Start();
}
[ChordMember]
private Add (a : int, b : int) : void;
[ChordMember]
private Mul(c : int, d : int) : void;
[ChordMember]
private Suspend() : void;
[ChordMember]
private Exit() : void;
//Get() is a chord. When called it will halt thread execution until one of its chord
//members has been called, and then return.
private Get () : string
chord {
| Suspend => suspended = true; "Suspend Command"
| Add => $"Add Command\n$a + $b = $(a + b)"
| Mul => $"Mul Command\n$c * $d = $(c * d)"
| Exit => "Exit Command"
}
private RunServerLoop() : void{
match(running){
| false => () //Exit
| true => match(suspended){
| false =>{ //Process commands.
def got = Get(); //Will halt thread execution until a chord member has been called
WriteLine("Command Received:");
WriteLine(got);
RunServerLoop();
}
| true => Thread.Sleep(100); RunServerLoop() //Do nothing
}
}
}
private EnterCmdLoop() : void {
Thread.Sleep(200);//Gives the server a chance to write to the console before client does.
Write("\nServer State: ");
match(suspended){
| true => Write("Suspended (Server will queue commands.)")
| false => Write("Processing Commands")
}
Write("\nAvailable commands for server are add, mul, suspend, resume, exit\nYour Command:");
match(ReadLine()){
| "add" => Add(InputNumber(),InputNumber()); EnterCmdLoop()
| "mul" => Mul(InputNumber(),InputNumber()); EnterCmdLoop()
| "suspend" when(suspended == false) => Suspend(); EnterCmdLoop()
| "suspend" => WriteLine("Server Already Suspended"); EnterCmdLoop()
| "resume" when(suspended == true) => suspended = false; WriteLine("Server Resuming"); EnterCmdLoop()
| "resume" => WriteLine("Server Already Running"); EnterCmdLoop()
| "exit" => {running = false; Exit()}
| _ => WriteLine("\nCommand not found.\n"); EnterCmdLoop()
}
}
private InputNumber() : int{ //Returns a number from console input.
Write("Input an integer:");
try{
int.Parse(ReadLine());
}
catch{
| _ => {WriteLine("\nError! Not a number."); InputNumber();}
}
}
}