Upgrade to Pro — share decks privately, control downloads, hide ads and more …

On Deny Capabilities for Safe, Fast Actors

On Deny Capabilities for Safe, Fast Actors

“Deny Capabilities for Safe, Fast Actors (2015)” by Sylvan Clebsch et al. lays out the core novel idea behind the Pony programming language: deny capabilities. Deny capabilities take object capabilities, turn them on their head and then apply them to variable aliases.

In this talk, Sean T. Allen (member of the Pony core team) explains Deny Capabilities and how Pony combines them with an actor-based model – to provide a programming environment that allows for data-race freedom and fearless concurrency.

Sean T Allen

January 08, 2020
Tweet

More Decks by Sean T Allen

Other Decks in Technology

Transcript

  1. Actor model basics Actors communicate with other actors via messaging

    Actors process messages Actors "protect resources" 8/39
  2. Data race Two memory accesses attempts where both: Target the

    same location Are performed concurrently by two threads 11/39
  3. Data race Two memory accesses attempts where both: Target the

    same location Are performed concurrently by two threads Are not reads 11/39
  4. Data race Two memory accesses attempts where both: Target the

    same location Are performed concurrently by two threads Are not reads Are not synchronization operations 11/39
  5. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables 12/39
  6. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables Actors are processed sequentially 1 message a time by a single thread 12/39
  7. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables Actors are processed sequentially 1 message a time by a single thread Actors are "synchronization operations" 12/39
  8. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables Actors are processed sequentially 1 message a time by a single thread But sending data from one actor to another can cause problems... 12/39
  9. How actors can hurt fast naive implementations can be very

    slow message queues are points of contention 16/39
  10. How actors can hurt fast naive implementations can be very

    slow message queues are points of contention locks are usually faster than a large memory copy 16/39
  11. What is an alias? Aliases are "names" for things in

    memory Aliases allow you to access a thing at a location 21/39
  12. Aliases in Pony When you assign a value to a

    variable or a eld. When you pass a value as an argument to a method. 22/39
  13. Aliases in Pony When you assign a value to a

    variable or a eld. When you pass a value as an argument to a method. When you call a method, an alias of the receiver of the call is created. It is accessible as this within the method body. 22/39
  14. Count the aliases primitive Say fun say(msg: String, out: OutStream)

    => let x = "We say '" + msg + "'" out.print(x) 23/39
  15. Count the aliases fun say(msg: String, out: OutStream) => primitive

    Say let x = "We say '" + msg + "'" out.print(x) msg and out are aliases 23/39
  16. Count the aliases let x = "We say '" +

    msg + "'" primitive Say fun say(msg: String, out: OutStream) => out.print(x) x is an alias 23/39
  17. Count the aliases out.print(x) primitive Say fun say(msg: String, out:

    OutStream) => let x = "We say '" + msg + "'" x is aliased when passed to print 23/39
  18. Count the aliases primitive Say fun say(msg: String, out: OutStream)

    => let x = "We say '" + msg + "'" out.print(x) 23/39
  19. actor Main new create(env: Env) => let msg: String val

    = "Hello World!" env.out.print(msg) 25/39
  20. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val is a capability 25/39
  21. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val is part of the type at compile-time 25/39
  22. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val says "the alias msg to the String Hello World is immutable" 25/39
  23. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso Shareable 32/39
  24. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso Shareable val 32/39
  25. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso Shareable val tag 32/39
  26. actor Main new create(env: Env) => let msg: String ref

    = "Hello World!".clone() env.out.print(msg) 35/39
  27. let msg: String ref = "Hello World!".clone() actor Main new

    create(env: Env) => env.out.print(msg) Hello World String is mutable 35/39
  28. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    ref = "Hello World!".clone() send msg to actor out 35/39
  29. let msg: String ref = "Hello World!".clone() actor Main new

    create(env: Env) => env.out.print(msg) ref isn't sendable 35/39
  30. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    ref = "Hello World!".clone() which will result in an error here 35/39
  31. Error: main.pony:4:19: argument not a subtype of parameter env.out.print(msg) ^

    Info: main.pony:4:19: argument type is String ref env.out.print(msg) ^ (...):13:12: parameter type is (String val | Array[U8 val] val) be print(data: ByteSeq) ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ main.pony:3:14: String ref is not a subtype of Array[U8 val] val 36/39
  32. main.pony:4:19: argument not a subtype of paramete env.out.print(msg) Error: ^

    Info: main.pony:4:19: argument type is String ref env.out.print(msg) ^ (...):13:12: parameter type is (String val | Array[U8 val] val) be print(data: ByteSeq) ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ msg isn't the correct type 36/39
  33. main.pony:4:19: argument type is String ref env.out.print(msg) Error: main.pony:4:19: argument

    not a subtype of parameter env.out.print(msg) ^ Info: ^ (...):13:12: parameter type is (String val | Array[U8 val] val) be print(data: ByteSeq) ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ msg is String ref 36/39
  34. (...):13:12: parameter type is (String val | Array[U8 val] val)

    be print(data: ByteSeq) main.pony:4:19: argument not a subtype of parameter env.out.print(msg) ^ Info: main.pony:4:19: argument type is String ref env.out.print(msg) ^ ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ main.pony:3:14: String ref is not a subtype of Array[U8 val] val l S i f "H ll W ld!" l () print requires String val or Array[U8] val 36/39
  35. actor Main new create(env: Env) => let msg: String val

    = "Hello World!" env.out.print(msg) 38/39
  36. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) Hello World String is immutable 38/39
  37. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    val = "Hello World!" send msg to actor out 38/39
  38. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val is sendable 38/39