Rendezvous: Difference between revisions
Content added Content deleted
(→{{header|Go}}: updated to use new WaitGroup feature. also improved exception message.) |
(added F#) |
||
Line 221: | Line 221: | ||
Return -1 |
Return -1 |
||
}</lang> |
}</lang> |
||
=={{header|F_Sharp|F#}}== |
|||
The rendezvous mechanism is realized by using F#'s mailbox processors to implement active objects. |
|||
It is possible to extract the boilerplate code into a reusable helper class which should be considered when using active objects a lot. |
|||
<lang fsharp>open System |
|||
type PrinterCommand = Print of string |
|||
// a message is a command and a facility to return an exception |
|||
type Message = Message of PrinterCommand * AsyncReplyChannel<Exception option> |
|||
// thrown if we have no more ink (and neither has our possible backup printer) |
|||
exception OutOfInk |
|||
type Printer(id, ?backup:Printer) = |
|||
let mutable ink = 5 |
|||
// the actual printing logic as a private function |
|||
let print line = |
|||
if ink > 0 then |
|||
printf "%d: " id |
|||
Seq.iter (printf "%c") line |
|||
printf "\n" |
|||
ink <- ink - 1 |
|||
else |
|||
match backup with |
|||
| Some p -> p.Print line |
|||
| None -> raise OutOfInk |
|||
// use a MailboxProcessor to process commands asynchronously; |
|||
// if an exception occurs, we return it to the calling thread |
|||
let agent = MailboxProcessor.Start( fun inbox -> |
|||
async { |
|||
while true do |
|||
let! Message (command, replyChannel) = inbox.Receive() |
|||
try |
|||
match command with |
|||
| Print line -> print line |
|||
replyChannel.Reply None |
|||
with |
|||
| ex -> replyChannel.Reply (Some ex) |
|||
}) |
|||
// public printing method: |
|||
// send Print command and propagate exception if one occurs |
|||
member x.Print line = |
|||
match agent.PostAndReply( fun replyChannel -> Message (Print line, replyChannel) ) with |
|||
| None -> () |
|||
| Some ex -> raise ex |
|||
open System.Threading |
|||
do |
|||
let main = new Printer(id=1, backup=new Printer(id=2)) |
|||
(new Thread(fun () -> |
|||
try |
|||
main.Print "Humpty Dumpty sat on a wall." |
|||
main.Print "Humpty Dumpty had a great fall." |
|||
main.Print "All the king's horses and all the king's men" |
|||
main.Print "Couldn't put Humpty together again." |
|||
with |
|||
| OutOfInk -> printfn " Humpty Dumpty out of ink!" |
|||
)).Start() |
|||
(new Thread(fun () -> |
|||
try |
|||
main.Print "Old Mother Goose" |
|||
main.Print "Would ride through the air" |
|||
main.Print "On a very fine gander." |
|||
main.Print "Jack's mother came in," |
|||
main.Print "And caught the goose soon," |
|||
main.Print "And mounting its back," |
|||
main.Print "Flew up to the moon." |
|||
with |
|||
| OutOfInk -> printfn " Mother Goose out of ink!" |
|||
)).Start() |
|||
Console.ReadLine() |> ignore</lang> |
|||
Example output: |
|||
<pre>1: Old Mother Goose |
|||
1: Humpty Dumpty sat on a wall. |
|||
1: Would ride through the air |
|||
1: Humpty Dumpty had a great fall. |
|||
1: On a very fine gander. |
|||
2: All the king's horses and all the king's men |
|||
2: Jack's mother came in, |
|||
2: Couldn't put Humpty together again. |
|||
2: And caught the goose soon, |
|||
2: And mounting its back, |
|||
Mother Goose out of ink!</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
Pretty sure printing could be done better ways in Go, but I stayed as close to the task description as I could. |
Pretty sure printing could be done better ways in Go, but I stayed as close to the task description as I could. |