Files
@ bf5b20db8be4
Branch filter:
Location: CSY/reowolf/testdata/examples/02_error_handling.pdl - annotation
bf5b20db8be4
3.1 KiB
text/plain
Finish tcp client/server example
8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 8fa5df1e1626 | // Although in an unstable state, there is an initial implementation for error
// handling. Roughly speaking: if a component has failed then it cannot complete
// any current or future synchronous rounds anymore. Hence, apart from some edge
// cases, any received message by a peer should cause a failure at that peer as
// well. We may have a look at the various places where a component with respect
// to a peer that is receiving its messages
enum ErrorLocation {
BeforeSync,
DuringSyncBeforeFirstInteraction,
DuringSyncBeforeSecondInteraction,
DuringSyncAfterInteractions,
AfterSync,
}
func error_location_to_string(ErrorLocation loc) -> string {
if (let ErrorLocation::BeforeSync = loc) {
return "before sync";
} else if (let ErrorLocation::DuringSyncBeforeFirstInteraction = loc) {
return "during sync before first interaction";
} else if (let ErrorLocation::DuringSyncBeforeSecondInteraction = loc) {
return "during sync before second interaction";
} else if (let ErrorLocation::DuringSyncAfterInteractions = loc) {
return "during sync after interactions";
} else { return "after sync"; }
}
func crash() -> u8 {
return {}[0]; // access index 1 of an empty array
}
comp sender_and_crasher(out<u32> value, ErrorLocation loc) {
print("sender: will crash " @ error_location_to_string(loc));
if (loc == ErrorLocation::BeforeSync) { crash(); }
sync {
if (loc == ErrorLocation::DuringSyncBeforeFirstInteraction) { crash(); }
print("sender: sending first value");
put(value, 0);
if (loc == ErrorLocation::DuringSyncBeforeSecondInteraction) { crash(); }
print("sender: sending second value");
put(value, 1);
if (loc == ErrorLocation::DuringSyncAfterInteractions) { crash(); }
}
if (loc == ErrorLocation::AfterSync) { crash(); }
}
comp receiver(in<u32> value) {
sync {
auto a = get(value);
auto b = get(value);
}
}
// Note that when we run the example with the error location before sync, or
// during sync, that the receiver always crashes. However the location where it
// will crash is somewhat random! Due to the asynchronous nature of the runtime
// a sender of messages will always just `put` the value onto the port and
// continue execution. So even though the sender component might already be done
// with its sync round, the receiver officially still has to receive its first
// message. In any case, a neat error message should be displayed in the
// console.
//
// Note especially, given the asynchronous nature of the runtime, that the
// receiver should figure out when the peer component has crashed, but it can
// still finish the current synchronous round. This might happen if the peer
// component crashes *just* after the synchronous round. There may be a case
// where the peer receives the information that the peer crashed *before* it
// receives the information that the synchronous round has succeeded.
comp main() {
channel tx -> rx;
new sender_and_crasher(tx, ErrorLocation::AfterSync);
new receiver(rx);
}
|