$30 off During Our Annual Pro Sale. View Details »

CSP

othree
February 14, 2015

 CSP

Communicating Sequential Processes

othree

February 14, 2015
Tweet

More Decks by othree

Other Decks in Technology

Transcript

  1. CSP
    othree

    View Slide

  2. Communicating Sequential
    Processes

    View Slide

  3. https://medium.com/@addyosmani/javascript-application-architecture-on-the-road-to-2015-d8125811101b

    View Slide

  4. 1978

    View Slide

  5. 1985

    View Slide

  6. What is CSP
    • Communication between processes
    • Born to be async
    • Using channel

    View Slide

  7. Process B
    Process A

    View Slide

  8. Process B
    Process A
    Channel
    msg

    View Slide

  9. Process B
    Process A
    msg
    PUT

    View Slide

  10. Process B
    Process A
    msg

    View Slide

  11. Process B
    Process A
    msg
    TAKE

    View Slide

  12. Process B
    Process A
    Channel
    msg

    View Slide

  13. Implements
    Go Clojure
    goroutine core.async

    View Slide

  14. https://speakerdeck.com/kachayev/channels-and-concurrency-go-clojure-erlang-haskell

    View Slide

  15. Go Example

    View Slide

  16. package main
    import "fmt"
    func main() {
    messages := make(chan string, 1)
    messages <- "ping"
    msg := <-messages
    fmt.Println(msg)
    }

    View Slide

  17. package main
    import "fmt"
    func main() {
    messages := make(chan string, 1)
    messages <- "ping"
    msg := <-messages
    fmt.Println(msg)
    }

    View Slide

  18. Short Variable Declarations
    • Declare variable
    • and assign value at the same time
    :=

    View Slide

  19. package main
    import "fmt"
    func main() {
    messages := make(chan string, 1)
    messages <- "ping"
    msg := <-messages
    fmt.Println(msg)
    }

    View Slide

  20. Receive Operator
    • Receive message
    • From channel
    • or channel receive message
    • Also imply direction of message
    <-

    View Slide

  21. package main
    import "fmt"
    func main() {
    messages := make(chan string, 1)
    messages <- "ping"
    msg := <-messages
    fmt.Println(msg)
    }

    View Slide

  22. View Slide

  23. Go Example II

    View Slide

  24. package main
    import "fmt"
    import "time"
    func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")
    done <- true
    }
    func main() {
    done := make(chan bool, 1)
    go worker(done)
    <-done
    }

    View Slide

  25. package main
    import "fmt"
    import "time"
    func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")
    done <- true
    }
    func main() {
    done := make(chan bool, 1)
    go worker(done)
    <-done
    }

    View Slide

  26. package main
    import "fmt"
    import "time"
    func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")
    done <- true
    }
    func main() {
    done := make(chan bool, 1)
    go worker(done)
    <-done
    }

    View Slide

  27. Go Statement
    • Execute function as independent
    process(goroutine)
    go

    View Slide

  28. View Slide

  29. Go Pingpong Example

    View Slide

  30. package main
    import "fmt"
    import "time"
    type Ball struct{ hits int }
    func player(name string, table chan *Ball) {
    for {
    ball := <-table
    ball.hits++
    fmt.Println(name, ball.hits)
    time.Sleep(100 * time.Millisecond)
    table <- ball
    }
    }

    View Slide

  31. package main
    import "fmt"
    import "time"
    type Ball struct{ hits int }
    func player(name string, table chan *Ball) {
    for {
    ball := <-table
    ball.hits++
    fmt.Println(name, ball.hits)
    time.Sleep(100 * time.Millisecond)
    table <- ball
    }
    }

    View Slide

  32. player
    • Receive ball from channel
    • Hit ball(+1)
    • Sleep
    • Send ball back

    View Slide

  33. func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)
    table <- new(Ball) // game on; toss the ball
    time.Sleep(1 * time.Second)
    <-table // game over; grab the ball
    }

    View Slide

  34. func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)
    table <- new(Ball) // game on; toss the ball
    time.Sleep(1 * time.Second)
    <-table // game over; grab the ball
    }

    View Slide

  35. func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)
    table <- new(Ball) // game on; toss the ball
    time.Sleep(1 * time.Second)
    <-table // game over; grab the ball
    }

    View Slide

  36. func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)
    table <- new(Ball) // game on; toss the ball
    time.Sleep(1 * time.Second)
    <-table // game over; grab the ball
    }

    View Slide

  37. Process Channel Message
    players table Ball

    View Slide

  38. player pong
    player ping
    table
    Ball

    View Slide

  39. View Slide

  40. Key Requirement
    • Channel
    • Ability to wait(idle) message

    View Slide

  41. Channel
    • First class object
    • First in first out
    • Accessible across processes

    View Slide

  42. Idle
    • Not able to idle in JavaScript
    • Use recursive function call can emulate, bad
    performance
    • ES6 have async function

    View Slide

  43. async function

    View Slide

  44. function* foo(){
    var index = 0;
    while (index <= 2) // when index reaches 3,
    // yield's done will be true
    // and its value will be undefined;
    yield index++;
    }

    View Slide

  45. var iterator = foo();
    console.log(iterator.next()); // { value:0, done:false }
    console.log(iterator.next()); // { value:1, done:false }
    console.log(iterator.next()); // { value:2, done:false }
    console.log(iterator.next()); // { value:undefined, done:true }

    View Slide

  46. yield
    • Function will stop and return on yield
    • Next call will exec from last yield
    • Sort of idle

    View Slide

  47. js-csp

    View Slide

  48. js-csp
    • by Nguyễn Tuấn Anh
    • Major implementation
    • Use async function
    • Also implement `go`, dispatcher…etc

    View Slide

  49. View Slide

  50. Pingpong Example

    View Slide

  51. function* player(name, table) {
    while (true) {
    var ball = yield csp.take(table);
    if (ball === csp.CLOSED) {
    console.log(name + ": table's gone");
    return;
    }
    ball.hits += 1;
    console.log(name + " " + ball.hits);
    yield csp.timeout(100);
    yield csp.put(table, ball);
    }
    }

    View Slide

  52. function* player(name, table) {
    while (true) {
    var ball = yield csp.take(table);
    if (ball === csp.CLOSED) {
    console.log(name + ": table's gone");
    return;
    }
    ball.hits += 1;
    console.log(name + " " + ball.hits);
    yield csp.timeout(100);
    yield csp.put(table, ball);
    }
    }
    func player(name string, table chan *Ball) {
    for {
    ball := <-table
    ball.hits++
    fmt.Println(name, ball.hits)
    time.Sleep(100 * time.Millisecond)
    table <- ball
    }
    }
    Go

    View Slide

  53. csp.go(function* () {
    var table = csp.chan();
    csp.go(player, ["ping", table]);
    csp.go(player, ["pong", table]);
    yield csp.put(table, {hits: 0});
    yield csp.timeout(1000);
    table.close();
    });

    View Slide

  54. csp.go(function* () {
    var table = csp.chan();
    csp.go(player, ["ping", table]);
    csp.go(player, ["pong", table]);
    yield csp.put(table, {hits: 0});
    yield csp.timeout(1000);
    table.close();
    });
    func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)
    table <- new(Ball)
    time.Sleep(1 * time.Second)
    <-table
    }
    Go

    View Slide

  55. csp.go(player, ["ping", table]); go player("ping", table)
    yield csp.put(table, {hits: 0}); table <- new(Ball)
    yield csp.take(table); <-table

    View Slide

  56. csp.go(function* () { func main() {
    var table = csp.chan(); table := make(chan *Ball)
    yield csp.timeout(1000); time.Sleep(1 * time.Second)

    View Slide

  57. js-csp
    • Easy to port Go program
    • yield is annoying

    View Slide

  58. What Can Use CSP
    • Sequential async data
    • Event

    View Slide

  59. Real World Event
    • Might have multiple event handler on single event

    View Slide

  60. Channel Message
    • Only can take once

    View Slide

  61. operations
    alt mult mix
    merge onto pipe
    split close timeout
    https://clojure.github.io/core.async/

    View Slide

  62. mult
    • one to many

    View Slide

  63. var csp = require("./src/csp");
    var mult = csp.operations.mult;
    var buffers = csp.buffers;
    var channel = csp.chan();
    var m = mult(channel);
    https://github.com/ubolonton/js-csp/issues/31#issuecomment-68089526

    View Slide

  64. var csp = require("./src/csp");
    var mult = csp.operations.mult;
    var buffers = csp.buffers;
    var channel = csp.chan();
    var m = mult(channel);

    View Slide

  65. csp.go(function*() {
    var out = mult.tap(m, csp.chan(buffers.sliding(1)));
    var val = yield csp.take(out);
    console.log('process 1', val);
    });
    csp.go(function*() {
    var out = mult.tap(m, csp.chan(buffers.sliding(1)));
    var val = yield csp.take(out);
    console.log('process 2', val);
    });

    View Slide

  66. csp.go(function*() {
    var out = mult.tap(m, csp.chan(buffers.sliding(1)));
    var val = yield csp.take(out);
    console.log('process 1', val);
    });
    csp.go(function*() {
    var out = mult.tap(m, csp.chan(buffers.sliding(1)));
    var val = yield csp.take(out);
    console.log('process 2', val);
    });

    View Slide

  67. csp.go(function*() {
    var out = mult.tap(m, csp.chan(buffers.sliding(1)));
    var val = yield csp.take(out);
    console.log('process 1', val);
    });
    csp.go(function*() {
    var out = mult.tap(m, csp.chan(buffers.sliding(1)));
    var val = yield csp.take(out);
    console.log('process 2', val);
    });

    View Slide

  68. csp.putAsync(channel, 42);

    View Slide

  69. not stable on js-csp

    View Slide

  70. Cons
    • Annoying yield
    • Not stable operations*
    • Lib size
    • Not support Web Worker

    View Slide

  71. js-csp
    • Syntax from Go
    • Operations from Clojure
    • Have disadvantages
    • Can use transducer from Clojure

    View Slide

  72. https://www.youtube.com/watch?v=7rDsRXj9-cU

    View Slide