1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
package examples;
import java.util.Date;
import scala.concurrent._;
/** A simple demonstrator program implementing an online auction service
* The example uses the actor abstraction defined in the API of
* package scala.concurrent.
*/
trait AuctionMessage;
case class
Offer(bid: int, client: Actor), // make a bid
Inquire(client: Actor) extends AuctionMessage; // inquire status
trait AuctionReply;
case class
Status(asked: int, expiration: Date), // asked sum, expiration date
BestOffer(), // yours is the best offer
BeatenOffer(maxBid: int), // offer beaten by maxBid
AuctionConcluded(seller: Actor, client: Actor), // auction concluded
AuctionFailed(), // failed with no bids
AuctionOver() extends AuctionReply; // bidding is closed
class Auction(seller: Actor, minBid: int, closing: Date) extends Actor {
val timeToShutdown = 3600000; // msec
val bidIncrement = 10;
override def run() = {
var maxBid = minBid - bidIncrement;
var maxBidder: Actor = null;
var running = true;
while (running) {
receiveWithin (closing.getTime() - new Date().getTime()) {
case Offer(bid, client) =>
if (bid >= maxBid + bidIncrement) {
if (maxBid >= minBid)
maxBidder send BeatenOffer(bid);
maxBid = bid;
maxBidder = client;
client send BestOffer()
} else {
client send BeatenOffer(maxBid)
}
case Inquire(client) =>
client send Status(maxBid, closing)
case TIMEOUT() =>
if (maxBid >= minBid) {
val reply = AuctionConcluded(seller, maxBidder);
maxBidder send reply;
seller send reply
} else {
seller send AuctionFailed()
}
receiveWithin(timeToShutdown) {
case Offer(_, client) => client send AuctionOver()
case TIMEOUT() => running = false
}
}
}
}
}
// ---- Test -------------------------------------------------------------
object auction {
val random = new java.util.Random();
val minBid = 100;
val closing = new Date(new Date().getTime() + 60000);
val seller = new Actor {
override def run() = {}
}
val auction = new Auction(seller, minBid, closing);
def client(i: int, increment: int, top: int) = new Actor {
val name = "Client " + i;
def log(msg: String) = Console.println(name + ": " + msg);
var running = true;
var max: int = _;
var current: int = 0;
override def run() = {
log("started");
auction send Inquire(this);
receive {
case Status(maxBid, _) => {
log("status(" + maxBid + ")");
max = maxBid
}
}
while (running) {
if (max >= top)
log("too high for me")
else if (current < max) {
current = max + increment;
Thread.sleep(1 + random.nextInt(1000));
auction send Offer(current, this);
}
receive {
case BestOffer() => {
log("bestOffer(" + current + ")");
}
case BeatenOffer(maxBid) => {
log("beatenOffer(" + maxBid + ")");
max = maxBid;
}
case AuctionConcluded(seller, maxBidder) => {
log("auctionConcluded");
}
case AuctionOver() => {
running = false;
log("auctionOver");
}
}
}
}
}
def main(args: Array[String]) = {
seller.start();
auction.start();
client(1, 20, 200).start();
client(2, 10, 300).start();
}
}
|