Our pizza and coffee shops were both interested in receiving many messages on the same reusable channel. We accomplished that with a persistent for for (msg <= chan){...}
or a contract contract chan(msg){...}
.
An air traffic control tower may be interested in doing just the opposite -- sending the same message over and over. The controllers in the tower want to record a message containing weather and active runway information once, and make it available for every pilot who needs it. Like the pizza shop, they are busy and can't be bothered to continually re-send the message every time a pilot consumes it.
The control tower just needs a minor adjustment in their code to make the send persistent. Rather than sending with a single !
, they will use a double !!
.
new airportInfo, stdout(`rho:io:stdout`) in {
// ATC sends the info
airportInfo!!("No wind; Runway 11")
|
// Pilot receives the info
for (info <- airportInfo) {
stdout!(*info)
}
}
Confirm for yourself that the original send is still in the tuplespace.
Modify the above code so that a second pilot also receives the information. Still, the send persists.
By the way, did you notice that we don't need new stdout(...) in {}
when we don't actually print anything to the screen stdout
?
How many comm events happen in for (x <- y) {Nil} | y!!(Nil)
1
many
0
Persistent sends and receives are very useful as we just showed. But often normal sends and receives are perfectly good too. Imagine that the air traffic controllers want to update the airport information when the weather changes. If they use a persistent send, they cannot make updates.
A better solution is to use a normal send and require each pilot who receives the message to put it back on the channel when they are done.
new airportInfo, stdout(`rho:io:stdout`) in {
// ATC sends the info
airportInfo!("No wind; Runway 11")
|
// Pilot receives the info
for (info <- airportInfo) {
stdout!(*info)
// TODO Pilot MUST put the info back
}
|
// ATC later records a new message
for (oldInfo <- airportInfo) {
airportInfo!("Wind 3 knots; Runway 11")
}
}
Using what you already know, you can you can complete the code for an honest pilot to return the info to the airportInfo
channel.
Give that a try on your own first. The solution is listed below.
How many comms happen in for (x <= y) {Nil} | y!!(Nil)
1
many
0
One problem with the code above is that a forgetful pilot may not actually put the information back on the airportInfo
channel causing problems for other pilots who need it. A better solution would be to not actually receive the message off of the channel in the first place.
To "peek" at what's on a channel without consuming it, use the <<-
operator.
new airportInfo, stdout(`rho:io:stdout`) in {
// ATC sends the info
airportInfo!("No wind; Runway 11")
|
// Pilot receives the info
for (info <<- airportInfo) {
stdout!(*info)
}
|
// ATC later records a new message
for (oldInfo <- airportInfo) {
airportInfo!("Wind 3 knots; Runway 11")
}
}
Which syntax is used to peek at a message?
for (x <<- y){...}
for (x <= y){...}
x!!(y)
How many comms happen in for (x <! y) {Nil} | y!!(Nil)
1
many
0
We've solved the problem of forgetful pilots removing the message and forgeting to put it back by teaching them to use peek instead. But this still doesn't solve the problem of malicios pilots intentionally taking the data. In reality we need to enforce that nobody can leave airportInfo
blank. We'll see how to do that in lesson 6.