4. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
5. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
BSD license
Copyright (c) 2014-2015, Causality Ltd.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
6. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
Classes, Interfaces, Traits
(but they may work a little differently than you expect)
7. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
Actors communicate by
passing messages to other
actors
8. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
The compiler enforces what
you can and cannot do with
an object
9. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
Uses LLVM to compile to
native code
10. What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
Also:
● powerful type system (unions, intersections,
parameterized types and functions)
● fast actor-based garbage collection system
15. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
16. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
17. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
traits: nominal
subtyping
18. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
19. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
interfaces:
structural
subtyping
20. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
21. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
22. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
primitive: object
with no data and
only one
instance
23. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
24. more-interesting.pony
trait Shape
fun area(): F64
interface Named
fun name(): String
class Circle is Shape
let _radius: F64
new create(radius: F64) =>
_radius = radius
fun name(): String => "circle"
fun area(): F64 =>
3.14159 * _radius * _radius
class Square is Shape
let _side: F64
new create(side: F64) =>
_side = side
fun name(): String => "square"
fun area(): F64 =>
_side * _side
primitive AreaReporter
fun report(shape: (Shape & Named)): String =>
"The area of this " + shape.name() +
" is " + shape.area().string()
actor Main
new create(env: Env) =>
let s: F64 = 15.3
var area = AreaReporter.report(Circle(s))
env.out.print(area)
area = AreaReporter.report(Square(s))
env.out.print(area)
> ./ponyc src/more-interesting
> ./more-interesting
The area of this circle is 735.415
The area of this square is 234.09
>
26. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
27. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
28. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
29. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
30. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
31. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
32. Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is
data-race-free.
33. Pony: The Really Interesting Parts
data-race-free
(this is the part you should remember)
35. Off To The Data Races!
Some pseudo code (not Pony) …
global int a = 0
function inc() {
for x in range(0, 1000001) {
a = a + 1
}
}
function main() {
inc()
print(“a = “ + a)
}
1000000
36. Off To The Data Races!
Some more pseudo code (not Pony) …
global int a = 0
function inc() {
for x in range(0, 1000001) {
a = a + 1
}
}
function main() {
thread thread1 = Thread(inc)
thread thread2 = Thread(inc)
thread1.run()
thread2.run()
thread1.join()
thread2.join()
print(“a = “ + a)
}
● Run “inc()” simultaneously in two
places
● wait for both runs to finish
● print the value of “a”
37. Off To The Data Races!
Some more pseudo code (not Pony) …
global int a = 0
function inc() {
for x in range(0, 1000001) {
a = a + 1
}
}
function main() {
thread thread1 = Thread(inc)
thread thread2 = Thread(inc)
thread1.run()
thread2.run()
thread1.join()
thread2.join()
print(“a = “ + a)
}
Expected (two threads each
incrementing a variable
1000000 times):
2000000
38. Off To The Data Races!
Some more pseudo code (not Pony) …
global int a = 0
function inc() {
for x in range(0, 1000001) {
a = a + 1
}
}
function main() {
thread thread1 = Thread(inc)
thread thread2 = Thread(inc)
thread1.run()
thread2.run()
thread1.join()
thread2.join()
print(“a = “ + a)
}
Expected:
2000000
Actual Run 1:
1987735
Actual Run 2:
1935010
Actual Run 3:
1941217
39. Off To The Data Races!
Some more pseudo code (not Pony) …
global int a = 0
function inc() {
for x in range(0, 1000001) {
a = a + 1
}
}
function main() {
thread thread1 = Thread(inc)
thread thread2 = Thread(inc)
thread1.run()
thread2.run()
thread1.join()
thread2.join()
print(“a = “ + a)
}
Expected:
2000000
Actual Run 1:
1987735
Actual Run 2:
1935010
Actual Run 3:
1941217
WHY?
40. Off To The Data Races!
In thread1 …
// get the value of “a”
// add 1 to that value
// write the new value back to “a”
a = a + 1
Meanwhile, in thread2...
// get the value of “a”
// add 1 to that value
// write the new value back to “a”
a = a + 1
a = 26
41. Off To The Data Races!
In thread1 …
// get the value of “a” 26
// add 1 to that value
// write the new value back to “a”
a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26
// add 1 to that value
// write the new value back to “a”
a = a + 1
a = 26
42. Off To The Data Races!
In thread1 …
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a”
a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a”
a = a + 1
a = 26
43. Off To The Data Races!
In thread1 …
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
a = 27
44. Off To The Data Races!
In thread1 …
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
a = 27
We wanted a = 28
45. Off To The Data Races!
In thread1 …
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
a = 27
This may not happen every time, but each time it
happens it increases the error of the result.
We wanted a = 28
46. Off To The Data Races!
In thread1 …
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26
// add 1 to that value 26 + 1 = 27
// write the new value back to “a” a = 27
a = a + 1
a = 27
This may not happen every time, but each time it
happens it increases the error of the result.
We wanted a = 28
“Shared mutable state is the root of all evil.”
-- several different people, all at the same time
47. Off To The Data Races!
Techniques various and sundry for avoiding data races ...
● Locks! → a unit of execution acquires a lock, no other unit of execution can
acquire the lock until it is released
○ C and C++
● Synchronized blocks/functions/methods! → somebody writes the locks for you
○ Java
● Everything is read-only! → don’t need to worry about writes anymore
○ Erlang
● There’s only one binding to an object at any time! → move, borrow, copy
○ Rust
48. Off To The Data Races!
Techniques various and sundry for avoiding data races ...
● Locks! → a unit of execution acquires a lock, no other unit of execution can
acquire the lock until it is released
○ C and C++
● Synchronized blocks/functions/methods! → somebody writes the locks for you
○ Java
● Everything is read-only! → don’t need to worry about writes anymore
○ Erlang
● There’s only one binding to an object at any time! → move, borrow, copy
○ Rust
WELL
ACTUALLYNope, save it until the end.
50. Leaving The Data Races
Pony uses two rules to avoid data races:
● The Read Rule: If an actor can read an object then no other actor can modify
that object
● The Write Rule: If an actor can modify an object then no other actor can read
or modify it
54. THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
Actors
message3
message4
message1
message2 }Queue
55. THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
Actors
Get next
message
message3
message4
message1
message2 }Queue
56. THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
Actors
Get next
message
Process
message
message3
message4
message1
message2 }Queue
57. THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
Actors
Get next
message
Process
message
Collect
garbage
message3
message4
message1
message2 }Queue
58. THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
WHICH / ONE WHICH / ONE
Actors
Get next
message
Process
message
Collect
garbage
message3
message4
message1
message2 }Queue
59. Actors
actor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
60. Actors
actor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
“be” means
“behavior”, this is
what processes a
message
61. Actors
actor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
“fun” means
“function”, these
are run by the
actor as part of
processing the
message
62. Actors
actor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
An actor sends a
message to
another actor
using the
“<a>.<be>(...)”
syntax
63. Actors
actor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
When talking
about Pony,
“method” means
either a function
or a behavior.
64. Actors
a1.bar() a2.baz() a1.bar()
a3.dee() a4.doo() a3.doh()
a5.moo()
a8.fee() a7.foo()
a6.mee()
a7.fuz()
time
CPU1: thread1
CPU2: thread2
CPU3: thread3
CPU4: thread4
Actors run on
threads (1 thread
per CPU by
default)
66. Actors
a1.bar() a2.baz() a1.bar()
a1.buz() a4.doo() a3.doh()
a5.moo()
a8.fee() a7.foo()
a6.mee()
a7.fuz()
time
CPU1: thread1
CPU2: thread2
CPU3: thread3
CPU4: thread4
Actors process
one message at a
time
68. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
69. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main
create(env)
70. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main
create(env)
71. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
create(“howdy”)
create(env)
72. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
create(env)
o
create(“howdy)
create(env)
73. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main
create(env)create(“howdy)
foo(o)
e
_text=”howdy”
o
_env=env
create(env)
74. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”howdy”
o
_env=env
foo(o)1
foo(o)2
create(env)
75. foo(o)1
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”ydwoh”
o
_env=env
foo(o)2
76. foo(o)1
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”ydwoh”
o
_env=env
foo(o)2 say(“ydwoh”)
77. say(“ydwoh”)foo(o)2
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”howdy”
o
_env=env
YDWOH
78. foo(o)2
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”howdy”
o
_env=env
say(“howdy”)
YDWOH
79. say(“howdy”)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”howdy”
o
_env=env
YDWOH
HOWDY
80. Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
_text=”howdy”
o
_env=env
YDWOH
HOWDY
85. Reference Capabilities
Remember the Read Rule and the Write Rule:
● The Read Rule: If an actor can read an object then no other actor can modify
that object
● The Write Rule: If an actor can modify an object then no other actor can read
or modify it
86. Reference Capabilities
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
87. Reference Capabilities
SPOT THE REFERENCE
CAPABILITIES!
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
88. Reference Capabilities
SPOT THE EXPLICIT REFERENCE
CAPABILITIES!
SPOT THE IMPLIED REFERENCE
CAPABILITIES!
class ref Foo
class val Bar
let v: U32 val
new val create(vv: U32 val) =>
v = vv
actor tag Main
new create(env: Env val) =>
let a: Foo iso = recover iso
Foo
end
var b: Bar val = Bar(1)
b = Bar(2)
baz(b)
fun box baz(c: Bar val): U32 val =>
c.v + 16
89. Reference Capabilities
Actors have a default reference
capability of tag, objects created
from classes have a default reference
capability of ref
You can change the implicit reference
capability of a class (normally it is
ref)
You can change the reference
capability of the object generated by
the constructor (normally it is ref)
class ref Foo
class val Bar
let v: U32 val
new val create(vv: U32 val) =>
v = vv
actor tag Main
new create(env: Env val) =>
let a: Foo iso = recover iso
Foo
end
var b: Bar val = Bar(1)
b = Bar(2)
baz(b)
fun box baz(c: Bar val): U32 val =>
c.v + 16
90. Reference Capabilities
You can specify the type of reference
capability that the receiver must have
to call a function
class ref Foo
class val Bar
let v: U32 val
new val create(vv: U32 val) =>
v = vv
actor tag Main
new create(env: Env val) =>
let a: Foo iso = recover iso
Foo
end
var b: Bar val = Bar(1)
b = Bar(2)
baz(b)
fun box baz(c: Bar val): U32 val =>
c.v + 16
91. Reference Capabilities
You can specify the type of reference
capability that the receiver must have
to call a function
This can get really tricky!
class ref Foo
class val Bar
let v: U32 val
new val create(vv: U32 val) =>
v = vv
actor tag Main
new create(env: Env val) =>
let a: Foo iso = recover iso
Foo
end
var b: Bar val = Bar(1)
b = Bar(2)
baz(b)
fun box baz(c: Bar val): U32 val =>
c.v + 16
92. Reference Capabilities
You can specify the type of reference
capability that the receiver must have
to call a function
This can get really tricky!
class ref Foo
class val Bar
let v: U32 val
new val create(vv: U32 val) =>
v = vv
actor tag Main
new create(env: Env val) =>
let a: Foo iso = recover iso
Foo
end
var b: Bar val = Bar(1)
b = Bar(2)
baz(b)
fun box baz(c: Bar val): U32 val =>
c.v + 16
93. Reference Capabilities
An alias is a name given to a particular object in
memory
Aliases are created when
● an object is assigned to a variable
● an object is passed as an argument to a
method
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
94. Reference Capabilities
An alias is a name given to a particular object in
memory
Aliases are created when
● an object is assigned to a variable
● an object is passed as an argument to a
method
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
95. Reference Capabilities
An alias is a name given to a particular object in
memory
Aliases are created when
● an object is assigned to a variable
● an object is passed as an argument to a
method
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
96. Reference Capabilities
An alias is a name given to a particular object in
memory
Aliases are created when
● an object is assigned to a variable
● an object is passed as an argument to a
method
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
97. Reference Capabilities
An alias is a name given to a particular object in
memory
Aliases are created when
● an object is assigned to a variable
● an object is passed as an argument to a
method
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
98. Reference Capabilities
An object may have more than one alias,
possibly in more than one actor, but the
combination of aliases must not violate the read
rule and write rule.
● The Read Rule: If an actor can
read an object then no other
actor can modify that object
● The Write Rule: If an actor can
modify an object then no other
actor can read or modify it
class Foo
class val Bar
let v: U32
new val create(vv: U32) =>
v = vv
actor Main
new create(env: Env) =>
let a: Foo iso = recover Foo end
var b = Bar(1)
b = Bar(2)
baz(b)
fun baz(c: Bar): U32 =>
c.v + 16
105. Reference Capabilities: A Visual Guide
object
alias can
send
object a
message
ref cap
A visual language
106. Reference Capabilities: A Visual Guide
object
note: any
alias can
send an
actor a
message,
regardless of
reference
capability
ref cap
A visual language
114. Reference Capabilities: A Visual Guide
object
ref cap
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
115. Reference Capabilities: iso (isolated)
iso
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
object
iso reference
can read and
modify an object.
No other
reference can
read or modify
the object.
116. Reference Capabilities: trn (transitional)
trn
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
object
trn reference
can read and
modify an object.
No other
reference can
modify the
object, but the
actor may have
other references
that can read the
object.
117. Reference Capabilities: ref (reference)
ref
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
object
ref reference
can read and
modify an object.
Other references
in the object may
be able to read
or modify the
object, but no
other actor may
have a reference
that can read or
modify it.
118. Reference Capabilities: val (value)
val
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
object
val reference
can read an
object. The actor
may have other
references that
can read the
object, and other
actors may have
references that
can read the
object, but no
actor may have
a reference that
can modify it.
119. Reference Capabilities: box (box)
box
OR
box
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
objectobject
120. Reference Capabilities: box (box)
box
OR
box
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
objectobject
This looks like a ref This looks like a val
121. Reference Capabilities: box (box)
box
OR
box
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
objectobject
A box capability is used when you want to create a new read-only
reference to an object that is either val or ref.
This looks like a ref This looks like a val
122. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ???): I32 =>
x.v() + 1
What should the
reference capability
be?
123. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
124. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
ref doesn’t work
because a ref (x)
can’t alias a val (b)
125. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X val): I32 =>
x.v() + 1
ref doesn’t work
because a ref (x)
can’t alias a val (b)
126. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X val): I32 =>
x.v() + 1
ref doesn’t work
because a ref (x)
can’t alias a val (b)
val Doesn’t work
because a val (x)
can’t alias a ref (a)
127. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X val): I32 =>
x.v() + 1
ref doesn’t work
because a ref (x)
can’t alias a val (b)
val Doesn’t work
because a val (x)
can’t alias a ref (a)
128. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X val): I32 =>
x.v() + 1
ref doesn’t work
because a ref (x)
can’t alias a val (b)
val Doesn’t work
because a val (x)
can’t alias a ref (a)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X box): I32 =>
x.v() + 1
129. Reference Capabilities: box (box)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X ref): I32 =>
x.v() + 1
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X val): I32 =>
x.v() + 1
ref doesn’t work
because a ref (x)
can’t alias a val (b)
val Doesn’t work
because a val (x)
can’t alias a ref (a)
class X
let v: I32
new create(v': I32) =>
v = v'
actor Main
new create(env: Env) =>
let a: X ref = X(7)
let b: X val = recover
X(8)
end
bar(a)
bar(b)
fun bar(x: X box): I32 =>
x.v() + 1
box works because
a box (x) can alias
a ref (a) or a val (b)
130. Reference Capabilities: tag (tag)
tag
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
object
tag reference
cannot read or
modify an object,
but it can be
used to send the
object messages
if the object is an
actor. Other
references may
read or modify
the object as
long as they do
not violate the
Read Rule and
the Write Rule.
133. Reference Capabilities
Sendable → iso, val, tag
Objects with sendable reference
capabilities can be sent to other
actors in messages
iso trn
ref val
box box
OR
tag
134. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
135. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
main
136. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
Main Foo
foo
137. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
Main Foo
f
Bar
b
138. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
Main Foo
f
Bar
b
baz( )
139. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
Main Foo
f
Bar
b
baz( )
x
140. Reference Capabilities: Sending A val
class Bar
actor Foo
be baz(x: Bar val) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover val Bar end
f.baz(b)
Main Foo
f
Bar
b x
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
141. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
142. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
An actor’s default
reference
capability is tag
143. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
main
144. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
Main Foo
foo
145. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
Main Foo
f
Bar
b
146. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
Main Foo
f
Bar
b
baz( )
147. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
Main Foo
f
Bar
b
baz( )
x
148. Reference Capabilities: Sending A tag
actor Bar
actor Foo
be baz(x: Bar tag) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = Bar
f.baz(b)
Main Foo
f
Bar
b x
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
149. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
150. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
main
151. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
foo
152. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
f
Bar
b
153. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
f
Bar
b
consume
causes b to
give up it’s
reference
154. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
f
Bar
b
once we
consume b,
we can no
longer use it
155. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
f
Bar
b
baz( )
156. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
f
Bar
b
baz( )
x
157. Reference Capabilities: Sending An iso
class Bar
actor Foo
be baz(x: Bar iso) =>
// do something with x
actor Main
new create(env: Env) =>
let f = Foo
let b = recover iso Bar end
f.baz(consume b)
Main Foo
f
Bar
b x
● The Read Rule: If an
actor can read an
object then no other
actor can modify that
object
● The Write Rule: If an
actor can modify an
object then no other
actor can read or
modify it
159. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
160. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
161. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
162. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
163. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
164. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
165. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
166. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
167. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
2000000
168. No More Data Races
use “collections”
actor Counter
var _count: U64 = 0
be increment() =>
_count = _count + 1
be print(env: Env) =>
env.out.print(_count.string())
actor Incrementer
new create(counter: Counter, main: Main) =>
for x in Range(0, 1_000_001) do
counter.increment()
end
main.finished(this)
actor Main
let _finished_count = 0
let _counter: Counter = Counter
let _env: Env
new create(env: Env) =>
_env = env
let inc1 = Incrementer(_counter, this)
let inc2 = Incrementer(_counter, this)
be finished() =>
_finished_count = _finished_count + 1
if _finished_count = 2 then
_counter.print(env)
end
The Counter
actor “protects”
the _count data
structure
171. Sendence’s Experience With Pony
It’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
172. Sendence’s Experience With Pony
It’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation
173. Sendence’s Experience With Pony
It’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation
● things change
174. Sendence’s Experience With Pony
It’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation
● things change
● there are some sharp edges (compiler bugs, runtime bugs)
175. Sendence’s Experience With Pony
It’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation
● things change
● there are some sharp edges (compiler bugs, runtime bugs)
“America is all about speed. Hot, nasty, badass speed.” -- Eleanor Roosevelt
PONY