c265902bea
Review URL: https://chromiumcodereview.appspot.com//10836241 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@10685 260f80e4-7a28-3924-810f-c04153c831b5
262 lines
6.6 KiB
Dart
262 lines
6.6 KiB
Dart
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// Things that should be "auto-generated" are between AUTO START and
|
|
// AUTO END (or just AUTO if it's a single line).
|
|
|
|
#library("MintMakerTest");
|
|
#import("dart:isolate");
|
|
#import('../../pkg/unittest/unittest.dart');
|
|
|
|
class Mint {
|
|
Mint() : registry_ = new Map<SendPort, Purse>() {
|
|
// AUTO START
|
|
ReceivePort mintPort = new ReceivePort();
|
|
port = mintPort.toSendPort();
|
|
serveMint(mintPort);
|
|
// AUTO END
|
|
}
|
|
|
|
// AUTO START
|
|
void serveMint(ReceivePort port) {
|
|
port.receive((var message, SendPort replyTo) {
|
|
int balance = message;
|
|
Purse purse = createPurse(balance);
|
|
replyTo.send([ purse.port ], null);
|
|
});
|
|
}
|
|
// AUTO END
|
|
|
|
Purse createPurse(int balance) {
|
|
Purse purse = new Purse(this, balance);
|
|
registry_[purse.port] = purse;
|
|
return purse;
|
|
}
|
|
|
|
Purse lookupPurse(SendPort port) {
|
|
return registry_[port];
|
|
}
|
|
|
|
Map<SendPort, Purse> registry_;
|
|
// AUTO
|
|
SendPort port;
|
|
}
|
|
|
|
|
|
// AUTO START
|
|
class MintWrapper {
|
|
MintWrapper(SendPort this.mint_) {}
|
|
|
|
void createPurse(int balance, handlePurse(PurseWrapper purse)) {
|
|
mint_.call(balance).then((var message) {
|
|
SendPort purse = message[0];
|
|
handlePurse(new PurseWrapper(purse));
|
|
});
|
|
}
|
|
|
|
SendPort mint_;
|
|
}
|
|
// AUTO END
|
|
|
|
|
|
/*
|
|
One way this could look without the autogenerated code:
|
|
|
|
class Mint {
|
|
Mint() : registry_ = new Map<SendPort, Purse>() {
|
|
}
|
|
|
|
wrap Purse createPurse(int balance) {
|
|
Purse purse = new Purse(this, balance);
|
|
registry_[purse.port] = purse;
|
|
return purse;
|
|
}
|
|
|
|
Purse lookupPurse(SendPort port) {
|
|
return registry_[port];
|
|
}
|
|
|
|
Map<SendPort, Purse> registry_;
|
|
}
|
|
|
|
The other end of the port would use Wrapper<Mint> as the wrapper, or
|
|
Future<Mint> as a future for the wrapper.
|
|
*/
|
|
|
|
|
|
class Purse {
|
|
Purse(Mint this.mint, int this.balance) {
|
|
// AUTO START
|
|
ReceivePort recipient = new ReceivePort();
|
|
port = recipient.toSendPort();
|
|
servePurse(recipient);
|
|
// AUTO END
|
|
}
|
|
|
|
// AUTO START
|
|
void servePurse(ReceivePort recipient) {
|
|
recipient.receive((var message, SendPort replyTo) {
|
|
String command = message[0];
|
|
if (command == "balance") {
|
|
replyTo.send(queryBalance(), null);
|
|
} else if (command == "deposit") {
|
|
Purse source = mint.lookupPurse(message[2]);
|
|
deposit(message[1], source);
|
|
} else if (command == "sprout") {
|
|
Purse result = sproutPurse();
|
|
replyTo.send([ result.port ], null);
|
|
} else {
|
|
// TODO: Send an exception back.
|
|
replyTo.send("Exception: Command not understood", null);
|
|
}
|
|
});
|
|
}
|
|
// AUTO END
|
|
|
|
int queryBalance() { return balance; }
|
|
|
|
Purse sproutPurse() { return mint.createPurse(0); }
|
|
|
|
void deposit(int amount, Purse source) {
|
|
// TODO: Throw an exception if the source purse doesn't hold
|
|
// enough dough.
|
|
balance += amount;
|
|
source.balance -= amount;
|
|
}
|
|
|
|
Mint mint;
|
|
int balance;
|
|
// AUTO
|
|
SendPort port;
|
|
}
|
|
|
|
|
|
// AUTO START
|
|
class PurseWrapper {
|
|
PurseWrapper(SendPort this.purse_) {}
|
|
|
|
void queryBalance(handleBalance(int balance)) {
|
|
purse_.call([ "balance" ]).then((var message) {
|
|
int balance = message;
|
|
handleBalance(balance);
|
|
});
|
|
}
|
|
|
|
void sproutPurse(handleSprouted(PurseWrapper sprouted)) {
|
|
purse_.call([ "sprout" ]).then((var message) {
|
|
SendPort sprouted = message[0];
|
|
handleSprouted(new PurseWrapper(sprouted));
|
|
});
|
|
}
|
|
|
|
void deposit(PurseWrapper source, int amount) {
|
|
purse_.send([ "deposit", amount, source.purse_ ], null);
|
|
}
|
|
|
|
|
|
SendPort purse_;
|
|
}
|
|
// AUTO END
|
|
|
|
|
|
// AUTO STATUS UNCLEAR!
|
|
|
|
mintMakerWrapper() {
|
|
port.receive((var message, SendPort replyTo) {
|
|
Mint mint = new Mint();
|
|
replyTo.send([ mint.port ], null);
|
|
});
|
|
}
|
|
|
|
class MintMakerWrapper {
|
|
MintMakerWrapper() {
|
|
port_ = spawnFunction(mintMakerWrapper);
|
|
}
|
|
|
|
void makeMint(handleMint(MintWrapper mint)) {
|
|
port_.call(null).then((var message) {
|
|
SendPort mint = message[0];
|
|
handleMint(new MintWrapper(mint));
|
|
});
|
|
}
|
|
|
|
SendPort port_;
|
|
}
|
|
|
|
_checkBalance(PurseWrapper wrapper, expected) {
|
|
wrapper.queryBalance(expectAsync1((int balance) {
|
|
expect(balance, equals(expected));
|
|
}));
|
|
}
|
|
|
|
main() {
|
|
test("creating purse, deposit, and query balance", () {
|
|
MintMakerWrapper mintMaker = new MintMakerWrapper();
|
|
mintMaker.makeMint(expectAsync1((MintWrapper mint) {
|
|
mint.createPurse(100, expectAsync1((PurseWrapper purse) {
|
|
_checkBalance(purse, 100);
|
|
purse.sproutPurse(expectAsync1((PurseWrapper sprouted) {
|
|
_checkBalance(sprouted, 0);
|
|
_checkBalance(purse, 100);
|
|
|
|
sprouted.deposit(purse, 5);
|
|
_checkBalance(sprouted, 0 + 5);
|
|
_checkBalance(purse, 100 - 5);
|
|
|
|
sprouted.deposit(purse, 42);
|
|
_checkBalance(sprouted, 0 + 5 + 42);
|
|
_checkBalance(purse, 100 - 5 - 42);
|
|
}));
|
|
}));
|
|
}));
|
|
});
|
|
|
|
/* This is an attempt to show how the above code could look like if we had
|
|
* better language support for asynchronous messages (deferred/asynccall).
|
|
* The static helper methods like createPurse and queryBalance would also
|
|
* have to be marked async.
|
|
|
|
void run(port) {
|
|
MintMakerWrapper mintMaker = spawnMintMaker();
|
|
deferred {
|
|
MintWrapper mint = asynccall mintMaker.createMint();
|
|
PurseWrapper purse = asynccall mint.createPurse(100);
|
|
Expect.equals(100, asynccall purse.queryBalance());
|
|
|
|
PurseWrapper sprouted = asynccall purse.sproutPurse();
|
|
Expect.equals(0, asynccall sprouted.queryBalance());
|
|
|
|
asynccall sprouted.deposit(purse, 5);
|
|
Expect.equals(0 + 5, asynccall sprouted.queryBalance());
|
|
Expect.equals(100 - 5, asynccall purse.queryBalance());
|
|
|
|
asynccall sprouted.deposit(purse, 42);
|
|
Expect.equals(0 + 5 + 42, asynccall sprouted.queryBalance());
|
|
Expect.equals(100 - 5 - 42, asynccall purse.queryBalance());
|
|
}
|
|
}
|
|
*/
|
|
|
|
/* And a version using futures and wrappers.
|
|
|
|
void run(port) {
|
|
Wrapper<MintMaker> mintMaker = spawnMintMaker();
|
|
Future<Mint> mint = mintMaker...createMint();
|
|
Future<Purse> purse = mint...createPurse(100);
|
|
Expect.equals(100, purse.queryBalance());
|
|
|
|
Future<Purse> sprouted = purse...sproutPurse();
|
|
Expect.equals(0, sprouted.queryBalance());
|
|
|
|
sprouted...deposit(purse, 5);
|
|
Expect.equals(0 + 5, sprouted.queryBalance());
|
|
Expect.equals(100 - 5, purse.queryBalance());
|
|
|
|
sprouted...deposit(purse, 42);
|
|
Expect.equals(0 + 5 + 42, sprouted.queryBalance());
|
|
Expect.equals(100 - 5 - 42, purse.queryBalance());
|
|
}
|
|
*/
|
|
}
|