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
|
/*
* https://github.com/ponylang/ponyc/raw/908402b60f083d66d3b59a1879efb6adee5ca3cc/examples/ring/main.pony
*/
"""
A ring is a group of processes connected to each other using
unidirectional links through which messages can pass from process to
process in a cyclic manner.
The logic of this program is as follows:
* Each process in a ring is represented by the actor `Ring`
* `Main` creates Ring by instantiating `Ring` actors based on the
arguments passed and links them with each other by setting the next
actor as the previous ones number and at the end linking the last actor
to the first one thereby closing the links and completing the ring
* Once the ring is complete messages can be passed by calling the `pass`
behaviour on the current `Ring` to its neighbour.
* The program prints the id of the last `Ring` to receive a message
For example if you run this program with the following options `--size 3`
and `--pass 2`. It will create a ring that looks like this:
* * * *
* * * *
* 1 *_ _ _ * 2 *
* * * *
* * * *
* * * *
\ /
\ /
\ /
\ * * /
* *
* 3 *
* *
* *
* *
and print 3 as the id of the last Ring actor that received the
message.
"""
use "collections"
actor Ring
let _id: U32
let _env: Env
var _next: (Ring | None)
new create(id: U32, env: Env, neighbor: (Ring | None) = None) =>
_id = id
_env = env
_next = neighbor
be set(neighbor: Ring) =>
_next = neighbor
be pass(i: USize) =>
if i > 0 then
match _next
| let n: Ring =>
n.pass(i - 1)
end
else
_env.out.print(_id.string())
end
actor Main
var _ring_size: U32 = 3
var _ring_count: U32 = 1
var _pass: USize = 10
var _env: Env
new create(env: Env) =>
_env = env
try
parse_args()?
setup_ring()
else
usage()
end
fun ref parse_args() ? =>
var i: USize = 1
while i < _env.args.size() do
// Every option has an argument.
var option = _env.args(i)?
var value = _env.args(i + 1)?
i = i + 2
match option
| "--size" =>
_ring_size = value.u32()?
| "--count" =>
_ring_count = value.u32()?
| "--pass" =>
_pass = value.usize()?
else
error
end
end
fun setup_ring() =>
for j in Range[U32](0, _ring_count) do
let first = Ring(1, _env)
var next = first
for k in Range[U32](0, _ring_size - 1) do
let current = Ring(_ring_size - k, _env, next)
next = current
end
first.set(next)
if _pass > 0 then
first.pass(_pass)
end
end
fun usage() =>
_env.out.print(
"""
rings OPTIONS
--size N number of actors in each ring
--count N number of rings
--pass N number of messages to pass around each ring
"""
)
|