SlideShare a Scribd company logo
Prime Cuts
The Best Pieces of Pony
Andrew Turley
February 2, 2017
About Me
Name
Andrew Turley
Contact
@casio_juarez / aturley@acm.org
Career
Currently at Sendence
What Is Pony?
What Is Pony?
“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high
performance programming language.” -- ponylang.org
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.
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)
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
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
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
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
hello.pony
hello.pony
actor Main
new create(env: Env) =>
env.out.print(“hello world”)
more-interesting.pony
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)
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)
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
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)
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
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)
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)
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
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)
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
>
Pony: The Really Interesting Parts
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting Parts
Pony uses actors and reference capabilities to allow the compiler to guarantee
that a program is
data-race-free.
Pony: The Really Interesting Parts
data-race-free
(this is the part you should remember)
Off To The Data Races!
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
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”
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
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
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?
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
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
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
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
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
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
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
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
Leaving The Data Races
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
Actors
Actors
Actors store state and act on that state in response to messages
Actor
● state
● behaviors
● functions
Actors
message3
message4
message1
message2 }Queue
Actors
message3
message4
message1
message2 }Queue
Actors
Get next
message
message3
message4
message1
message2 }Queue
Actors
Get next
message
Process
message
message3
message4
message1
message2 }Queue
Actors
Get next
message
Process
message
Collect
garbage
message3
message4
message1
message2 }Queue
Actors
Get next
message
Process
message
Collect
garbage
message3
message4
message1
message2 }Queue
Actors
Get next
message
Process
message
Collect
garbage
message3
message4
message1
message2 }Queue
In reality
messages
are
processed
in batches,
GC is done
between
batches
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)
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 are
assigned to a
specific thread
a1, a2
a3, a4
a5, a6
a7, a8
Actors
a1.bar() a2.baz()1 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
a2.baz()2
Behaviors cannot
be preempted
Actors
a1.bar() a2.baz() a1.bar()
IDLE a1.baz() a3.doh()
a5.moo()
a8.fee() a7.foo()
a6.mee()
a7.fuz()
time
CPU1: thread1
CPU2: thread2
CPU3: thread3
CPU4: thread4
A idle thread
“steal” work from
another thread
Work for actor
a1 “stolen” by
thread2
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 (actors are
effectively
single-threaded)
Actors
a1 a3
a2
o1
Actors have references to objects
and other actors
Actors
a1 a3
a2
o1
Actors have references to objects and
other actors
References can be used to:
* read from an object
* write to an object
* send messages to another actor
Actors
a1 a3
a2
o1
Actors have references to objects and
other actors
References can be used to:
* read from an object
* write to an object
* send messages to another actor
Reference Capabilities control
whether reads and writes are
allowed via a given reference. Any
reference can be used to send a
message.
Actors
a1 a3
a2
o1
Actors have references to objects and
other actors
References can be used to:
* read from an object
* write to an object
* send messages to another actor
Reference Capabilities control whether
reads and writes are allowed via a
given reference. Any reference can be
used to send a message.
Note: send message ≠ read/write
Actors: An Example
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”
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)
run!
When the program starts, the
Main actor is instantiated and a
create message is sent to it.
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)
The Main actor begins to process
the create message.
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)
An instance of the Example actor
is instantiated and a create
message is sent to it with
“howdy” as the argument.
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)
An instance of the the Other
actor is instantiated and a
create message is sent to it with
env as the argument.
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)
The Main actor sends a foo
message to the Example actor.
The Example actor sets the value
of its _text field.
The Other actor sets the value of
its _env field
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)
The Main actor sends a foo
message to the Example actor.
The Example actor sets the value
of its _text field.
The Other actor sets the value of
its _env field
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
The Example actor processes
the first foo message by first
calling its rev method, which
reverses the _text string.
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”)
The Example actor sends the
string to the Other actor in a say
message.
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
The Example actor processes
the second foo message, which
again reverses the _text string.
The Other actor processes the
say message by printing the
string that it received.
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
The Example actor sends
another say message to the
Other actor.
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
The Other actor processes the
say message by printing the
string that it received.
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
All messages have been handled
so the program can exit.
Reference Capabilities
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
Reference Capabilities
Reference capabilities control whether a given alias can be used to read or modify
an object.
The collection of reference capabilities for aliases that refer to an object must be
consistent with the Read Rule and the Write Rule.
Any alias to an actor, regardless of reference capability, can be used to send
messages to that actor.
Reference Capabilities
There are six reference capabilities:
● iso - only one alias can be used to read or modify this object
● trn - only one alias can modify this object, but more than one alias can be
used to read it
● val - no alias can modify this object, but more than one alias can read from it
● ref - more than one alias can read from this object, and more than alias can
modify this object
● box - this alias can be used to read an object, there may more may not be
more than one other alias that can modify it
● tag - this alias cannot be used to read or modify this object (but it can be
used to send a message or do an identity comparison)
Reference Capabilities
Reference capabilities can appear in
● variable, parameter, and field declarations
○ let foo: Foo ref = Foo // foo’s reference capability is ref
Reference Capabilities
Reference capabilities can appear in
● variable, parameter, and field declarations
○ let foo: Foo ref = Foo // foo’s reference capability is ref
● actor and class declarations
○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified
Reference Capabilities
Reference capabilities can appear in
● variable, parameter, and field declarations
○ let foo: Foo ref = Foo // foo’s reference capability is ref
● actor and class declarations
○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified
● constructor declarations
○ new val create() => // objects of this class will have a reference capability of val
Reference Capabilities
Reference capabilities can appear in
● variable, parameter, and field declarations
○ let foo: Foo ref = Foo // foo’s reference capability is ref
● actor and class declarations
○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified
● constructor declarations
○ new val create() => // objects of this class will have a reference capability of val
● function declarations
○ fun ref bar() // bar()’s receiver must have a reference capability of ref
Reference Capabilities
Reference capabilities can appear in
● variable, parameter, and field declarations
○ let foo: Foo ref = Foo // foo’s reference capability is ref
● actor and class declarations
○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified
● constructor declarations
○ new val create() => // objects of this class will have a reference capability of val
● function declarations
○ fun ref bar() // bar()’s receiver must have a reference capability of ref
● function return values
○ fun f(): String ref // the String will have a reference capability of ref
Reference Capabilities
Reference capabilities can appear in
● variable, parameter, and field declarations
○ let foo: Foo ref = Foo // foo’s reference capability is ref
● actor and class declarations
○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified
● constructor declarations
○ new val create() => // objects of this class will have a reference capability of val
● function declarations
○ fun ref bar() // bar()’s receiver must have a reference capability of ref
● function return values
○ fun f(): String ref // the String will have a reference capability of ref
● recover blocks
○ recover iso … end // the reference capability of the returned object will be iso
Reference Capabilities
If no reference capability is specified, the default reference capability for the given
thing is used.
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
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
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
Reference Capabilities
Actors have a default reference
capability of tag, objects created
from classes have a default reference
capability of 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
Reference Capabilities
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
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
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
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
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
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
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
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
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
Reference Capabilities: A Visual Guide
Reference Capabilities: iso (isolated)
● 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
iso reference
can read and
modify an object.
No other
reference can
read or modify
the object.
object
alias1
alias2
alias3
Actor A Actor B
iso
Reference Capabilities: trn (transitional)
● 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
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.
object
alias1
alias2
alias3
Actor A Actor B
trn
Reference Capabilities: ref (reference)
● 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
ref reference
can read and
modify an object.
Other references
in the actor may
be able to read
or modify the
object, but no
other actor may
have a reference
that can read or
modify it.
object
alias1
alias2
alias3
Actor A Actor B
ref
Reference Capabilities: val (value)
● 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
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.
object
alias1
alias2
alias3
Actor A Actor B
val
Reference Capabilities: box (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
object
alias1
alias2
alias3
Actor A Actor B
box
OR
object
alias1
alias2
alias3
Actor A Actor B
box
Reference Capabilities: box (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
object
alias1
alias2
alias3
Actor A Actor B
box
OR
object
alias1
alias2
alias3
Actor A Actor B
box
This
looks like
a val
This
looks like
a ref
A box capability is
used when you want to
create a new read-only
reference to an object
that is either val or ref.
Reference Capabilities: box (box)
Why do we have box?
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?
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
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)
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)
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)
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)
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
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)
Reference Capabilities: 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
tag reference
cannot read or
modify an object,
but it can be
used to send the
object messages
if the object is an
actor, or to
compare
identity. Other
references may
read or modify
the object as
long as they do
not violate the
Read Rule and
the Write Rule.
object
alias1
alias2
alias3
Actor A Actor B
tag
Reference Capabilities: 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
alias1
alias2
alias3
Actor A Actor B
tag
Example:
alias2 can
be a ref
because this
does not
violate the
Read Rule or
Write Rule
tag reference
cannot read or
modify an object,
but it can be
used to send the
object messages
if the object is an
actor, or to
compare
identity. Other
references may
read or modify
the object as
long as they do
not violate the
Read Rule and
the Write Rule.
Reference Capabilities
Readable → iso, trn, ref, val, box
Reference Capabilities
Readable → iso, trn, ref, val, box
Writeable → iso, trn, ref
Reference Capabilities
Readable → iso, trn, ref, val, box
Writeable → iso, trn, ref
Sendable → iso, val, tag
Objects with sendable reference
capabilities can be sent to other
actors in messages
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)
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
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
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
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( )
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
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
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)
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
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
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
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
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( )
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
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
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)
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
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
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
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
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
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( )
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
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
No More Data Races
No More Data Races
Remember this?
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
No More Data Races
Remember this?
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)
}
This program violates the Read
Rule and Write Rule, because the
variable a can be read and
modified from multiple threads.
No More Data Races
A first pass at a Pony equivalent
use “collections”
class Counter
var v: U64 = 0
fun ref inc() => v = v + 1
actor Inc
be doit(c: Counter) =>
for x in range(0, 100001) do
c.inc()
end
actor Main
new create(env: Env) =>
let c = Counter
Inc.doit(c)
Inc.doit(c)
env.out.print(c.v.string())
No More Data Races
A first pass at a Pony equivalent
use “collections”
class Counter
var v: U64 = 0
fun ref inc() => v = v + 1
actor Inc
be doit(c: Counter) =>
for x in range(0, 100001) do
c.inc()
end
actor Main
new create(env: Env) =>
let c = Counter
Inc.doit(c)
Inc.doit(c)
env.out.print(c.v.string())
This doesn’t work because the
two Inc actors try to read and
write to the Counter
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
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
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
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
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
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
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
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
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
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
Sendence’s Experience With Pony
Sendence’s Experience With Pony
It’s nice to catch errors a compile time rather than runtime
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)
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
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
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)
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
Learn More
(because I left a lot out)
Learn More
User Mailing List
● https://pony.groups.io/g/user
Website
● https://www.ponylang.org
IRC
● freenode #ponylang
Contribute
Contribute
Developer Mailing List
● https://pony.groups.io/g/dev
Github
● Pony compiler → https://github.com/ponylang/ponyc
● RFCs → https://github.com/ponylang/rfcs
Thank You
Questions

More Related Content

Recently uploaded

Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
Alberto Brandolini
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
Liberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptxLiberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptx
Massimo Artizzu
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
Patrick Weigel
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
Sven Peters
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
sjcobrien
 
What next after learning python programming basics
What next after learning python programming basicsWhat next after learning python programming basics
What next after learning python programming basics
Rakesh Kumar R
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
TaghreedAltamimi
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
brainerhub1
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 

Recently uploaded (20)

Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
Liberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptxLiberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptx
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
 
What next after learning python programming basics
What next after learning python programming basicsWhat next after learning python programming basics
What next after learning python programming basics
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 

Featured

Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
Christy Abraham Joy
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
Vit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
MindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
RachelPearson36
 
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Applitools
 
12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work
GetSmarter
 

Featured (20)

Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
Unlocking the Power of ChatGPT and AI in Testing - A Real-World Look, present...
 
12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work12 Ways to Increase Your Influence at Work
12 Ways to Increase Your Influence at Work
 

Pony vug prime cuts the best pieces of pony

  • 1. Prime Cuts The Best Pieces of Pony Andrew Turley February 2, 2017
  • 2. About Me Name Andrew Turley Contact @casio_juarez / aturley@acm.org Career Currently at Sendence
  • 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
  • 12. hello.pony actor Main new create(env: Env) => env.out.print(“hello world”)
  • 14. 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)
  • 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) traits: nominal subtyping
  • 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)
  • 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) interfaces: structural subtyping
  • 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)
  • 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) primitive: object with no data and only one instance
  • 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)
  • 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) > ./ponyc src/more-interesting > ./more-interesting The area of this circle is 735.415 The area of this square is 234.09 >
  • 24. Pony: The Really Interesting Parts
  • 25. Pony: The Really Interesting Parts Pony uses actors and reference capabilities to allow the compiler to guarantee that a program is data-race-free.
  • 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 data-race-free (this is the part you should remember)
  • 33. Off To The Data Races!
  • 34. 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
  • 35. 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”
  • 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) } Expected (two threads each incrementing a variable 1000000 times): 2000000
  • 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: 2000000 Actual Run 1: 1987735 Actual Run 2: 1935010 Actual Run 3: 1941217
  • 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 WHY?
  • 39. 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
  • 40. 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
  • 41. 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
  • 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 = 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
  • 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 We wanted a = 28
  • 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 This may not happen every time, but each time it happens it increases the error of the result. 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 “Shared mutable state is the root of all evil.” -- several different people, all at the same time
  • 46. 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. 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
  • 50. Actors Actors store state and act on that state in response to messages
  • 51. Actor ● state ● behaviors ● functions Actors message3 message4 message1 message2 }Queue
  • 57. Actors Get next message Process message Collect garbage message3 message4 message1 message2 }Queue In reality messages are processed in batches, GC is done between batches
  • 58. 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)
  • 59. 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 are assigned to a specific thread a1, a2 a3, a4 a5, a6 a7, a8
  • 60. Actors a1.bar() a2.baz()1 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 a2.baz()2 Behaviors cannot be preempted
  • 61. Actors a1.bar() a2.baz() a1.bar() IDLE a1.baz() a3.doh() a5.moo() a8.fee() a7.foo() a6.mee() a7.fuz() time CPU1: thread1 CPU2: thread2 CPU3: thread3 CPU4: thread4 A idle thread “steal” work from another thread Work for actor a1 “stolen” by thread2
  • 62. 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 (actors are effectively single-threaded)
  • 63. Actors a1 a3 a2 o1 Actors have references to objects and other actors
  • 64. Actors a1 a3 a2 o1 Actors have references to objects and other actors References can be used to: * read from an object * write to an object * send messages to another actor
  • 65. Actors a1 a3 a2 o1 Actors have references to objects and other actors References can be used to: * read from an object * write to an object * send messages to another actor Reference Capabilities control whether reads and writes are allowed via a given reference. Any reference can be used to send a message.
  • 66. Actors a1 a3 a2 o1 Actors have references to objects and other actors References can be used to: * read from an object * write to an object * send messages to another actor Reference Capabilities control whether reads and writes are allowed via a given reference. Any reference can be used to send a message. Note: send message ≠ read/write
  • 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) run! When the program starts, the Main actor is instantiated and a create message is sent to it.
  • 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) The Main actor begins to process the create message.
  • 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) An instance of the Example actor is instantiated and a create message is sent to it with “howdy” as the argument.
  • 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) An instance of the the Other actor is instantiated and a create message is sent to it with env as the argument.
  • 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) The Main actor sends a foo message to the Example actor. The Example actor sets the value of its _text field. The Other actor sets the value of its _env field
  • 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) The Main actor sends a foo message to the Example actor. The Example actor sets the value of its _text field. The Other actor sets the value of its _env field
  • 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 The Example actor processes the first foo message by first calling its rev method, which reverses the _text string.
  • 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”) The Example actor sends the string to the Other actor in a say message.
  • 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 The Example actor processes the second foo message, which again reverses the _text string. The Other actor processes the say message by printing the string that it received.
  • 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 The Example actor sends another say message to the Other actor.
  • 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 The Other actor processes the say message by printing the string that it received.
  • 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 All messages have been handled so the program can exit.
  • 82. 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
  • 83. Reference Capabilities Reference capabilities control whether a given alias can be used to read or modify an object. The collection of reference capabilities for aliases that refer to an object must be consistent with the Read Rule and the Write Rule. Any alias to an actor, regardless of reference capability, can be used to send messages to that actor.
  • 84. Reference Capabilities There are six reference capabilities: ● iso - only one alias can be used to read or modify this object ● trn - only one alias can modify this object, but more than one alias can be used to read it ● val - no alias can modify this object, but more than one alias can read from it ● ref - more than one alias can read from this object, and more than alias can modify this object ● box - this alias can be used to read an object, there may more may not be more than one other alias that can modify it ● tag - this alias cannot be used to read or modify this object (but it can be used to send a message or do an identity comparison)
  • 85. Reference Capabilities Reference capabilities can appear in ● variable, parameter, and field declarations ○ let foo: Foo ref = Foo // foo’s reference capability is ref
  • 86. Reference Capabilities Reference capabilities can appear in ● variable, parameter, and field declarations ○ let foo: Foo ref = Foo // foo’s reference capability is ref ● actor and class declarations ○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified
  • 87. Reference Capabilities Reference capabilities can appear in ● variable, parameter, and field declarations ○ let foo: Foo ref = Foo // foo’s reference capability is ref ● actor and class declarations ○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified ● constructor declarations ○ new val create() => // objects of this class will have a reference capability of val
  • 88. Reference Capabilities Reference capabilities can appear in ● variable, parameter, and field declarations ○ let foo: Foo ref = Foo // foo’s reference capability is ref ● actor and class declarations ○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified ● constructor declarations ○ new val create() => // objects of this class will have a reference capability of val ● function declarations ○ fun ref bar() // bar()’s receiver must have a reference capability of ref
  • 89. Reference Capabilities Reference capabilities can appear in ● variable, parameter, and field declarations ○ let foo: Foo ref = Foo // foo’s reference capability is ref ● actor and class declarations ○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified ● constructor declarations ○ new val create() => // objects of this class will have a reference capability of val ● function declarations ○ fun ref bar() // bar()’s receiver must have a reference capability of ref ● function return values ○ fun f(): String ref // the String will have a reference capability of ref
  • 90. Reference Capabilities Reference capabilities can appear in ● variable, parameter, and field declarations ○ let foo: Foo ref = Foo // foo’s reference capability is ref ● actor and class declarations ○ class val Foo // a “Foo” type means “Foo val” unless otherwise specified ● constructor declarations ○ new val create() => // objects of this class will have a reference capability of val ● function declarations ○ fun ref bar() // bar()’s receiver must have a reference capability of ref ● function return values ○ fun f(): String ref // the String will have a reference capability of ref ● recover blocks ○ recover iso … end // the reference capability of the returned object will be iso
  • 91. Reference Capabilities If no reference capability is specified, the default reference capability for the given thing is used.
  • 92. 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
  • 93. 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
  • 94. 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
  • 95. Reference Capabilities Actors have a default reference capability of tag, objects created from classes have a default reference capability of 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
  • 96. Reference Capabilities 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
  • 97. 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
  • 98. 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
  • 99. 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
  • 100. 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
  • 101. 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
  • 102. 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
  • 103. 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
  • 104. 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
  • 106. Reference Capabilities: iso (isolated) ● 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 iso reference can read and modify an object. No other reference can read or modify the object. object alias1 alias2 alias3 Actor A Actor B iso
  • 107. Reference Capabilities: trn (transitional) ● 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 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. object alias1 alias2 alias3 Actor A Actor B trn
  • 108. Reference Capabilities: ref (reference) ● 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 ref reference can read and modify an object. Other references in the actor may be able to read or modify the object, but no other actor may have a reference that can read or modify it. object alias1 alias2 alias3 Actor A Actor B ref
  • 109. Reference Capabilities: val (value) ● 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 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. object alias1 alias2 alias3 Actor A Actor B val
  • 110. Reference Capabilities: box (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 object alias1 alias2 alias3 Actor A Actor B box OR object alias1 alias2 alias3 Actor A Actor B box
  • 111. Reference Capabilities: box (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 object alias1 alias2 alias3 Actor A Actor B box OR object alias1 alias2 alias3 Actor A Actor B box This looks like a val This looks like a ref A box capability is used when you want to create a new read-only reference to an object that is either val or ref.
  • 112. Reference Capabilities: box (box) Why do we have box?
  • 113. 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?
  • 114. 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
  • 115. 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)
  • 116. 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)
  • 117. 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)
  • 118. 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)
  • 119. 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
  • 120. 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)
  • 121. Reference Capabilities: 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 tag reference cannot read or modify an object, but it can be used to send the object messages if the object is an actor, or to compare identity. Other references may read or modify the object as long as they do not violate the Read Rule and the Write Rule. object alias1 alias2 alias3 Actor A Actor B tag
  • 122. Reference Capabilities: 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 alias1 alias2 alias3 Actor A Actor B tag Example: alias2 can be a ref because this does not violate the Read Rule or Write Rule tag reference cannot read or modify an object, but it can be used to send the object messages if the object is an actor, or to compare identity. Other references may read or modify the object as long as they do not violate the Read Rule and the Write Rule.
  • 123. Reference Capabilities Readable → iso, trn, ref, val, box
  • 124. Reference Capabilities Readable → iso, trn, ref, val, box Writeable → iso, trn, ref
  • 125. Reference Capabilities Readable → iso, trn, ref, val, box Writeable → iso, trn, ref Sendable → iso, val, tag Objects with sendable reference capabilities can be sent to other actors in messages
  • 126. 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)
  • 127. 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
  • 128. 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
  • 129. 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
  • 130. 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( )
  • 131. 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
  • 132. 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
  • 133. 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)
  • 134. 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
  • 135. 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
  • 136. 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
  • 137. 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
  • 138. 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( )
  • 139. 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
  • 140. 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
  • 141. 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)
  • 142. 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
  • 143. 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
  • 144. 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
  • 145. 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
  • 146. 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
  • 147. 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( )
  • 148. 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
  • 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) 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
  • 150. No More Data Races
  • 151. No More Data Races Remember this? 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
  • 152. No More Data Races Remember this? 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) } This program violates the Read Rule and Write Rule, because the variable a can be read and modified from multiple threads.
  • 153. No More Data Races A first pass at a Pony equivalent use “collections” class Counter var v: U64 = 0 fun ref inc() => v = v + 1 actor Inc be doit(c: Counter) => for x in range(0, 100001) do c.inc() end actor Main new create(env: Env) => let c = Counter Inc.doit(c) Inc.doit(c) env.out.print(c.v.string())
  • 154. No More Data Races A first pass at a Pony equivalent use “collections” class Counter var v: U64 = 0 fun ref inc() => v = v + 1 actor Inc be doit(c: Counter) => for x in range(0, 100001) do c.inc() end actor Main new create(env: Env) => let c = Counter Inc.doit(c) Inc.doit(c) env.out.print(c.v.string()) This doesn’t work because the two Inc actors try to read and write to the Counter
  • 155. 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
  • 156. 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
  • 157. 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
  • 158. 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
  • 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 2000000
  • 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 The Counter actor “protects” the _count data structure
  • 166. Sendence’s Experience With Pony It’s nice to catch errors a compile time rather than runtime
  • 167. 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)
  • 168. 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
  • 169. 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
  • 170. 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)
  • 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) ● 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
  • 172. Learn More (because I left a lot out)
  • 173. Learn More User Mailing List ● https://pony.groups.io/g/user Website ● https://www.ponylang.org IRC ● freenode #ponylang
  • 175. Contribute Developer Mailing List ● https://pony.groups.io/g/dev Github ● Pony compiler → https://github.com/ponylang/ponyc ● RFCs → https://github.com/ponylang/rfcs