4 people like it.

Fun with Ping and Pong

Yet another ping pong sample with agents.

Declarations

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
type Agent<'a> = MailboxProcessor<'a>

let pong1 = Agent<string * (string -> unit)>.Start(fun inbox ->
  let rec loop (state: System.Collections.Generic.List<string>) = async {
    let! msg = inbox.Receive()
    match msg with
    // Build up state and return it at the end.
    | "Stop", _ ->
        for m in state do System.Console.WriteLine m
    | m, f ->
        state.Add m
        if state.Count > 5 then
          f "Bail!"
          for m in state do System.Console.WriteLine m
        else
          f "Pong"
          return! loop state
  }
  loop (new System.Collections.Generic.List<string>()) )

let pong2 = Agent<string * (string -> unit)>.Start(fun inbox ->
  let rec loop (state: System.Collections.Generic.List<string>) = async {
    let! msg = inbox.Receive()
    match msg with
    // Build up state and return it at the end.
    | "Stop", _ ->
        for m in state do System.Console.WriteLine m
    | m, f ->
        state.Add m
        f "Pong"
        return! loop state
  }
  loop (new System.Collections.Generic.List<string>()) )

let rec ping (target1: Agent<_>) (target2: Agent<_>) = Agent<string>.Start(fun inbox ->
  async {
    let target = ref target1
    for x=1 to 10 do
      (!target).Post("Ping", inbox.Post)
      let! msg = inbox.Receive()
      if msg = "Bail!" then
        target := target2
      System.Console.WriteLine msg
    (!target).Post("Stop", inbox.Post)
  })

Usage

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
ping pong1 pong2
// Pong
// Pong
// Pong
// Pong
// Pong
// Ping
// Ping
// Ping
// Ping
// Ping
// Ping
// Bail!
// Pong
// Pong
// Pong
// Pong
// Ping
// Ping
// Ping
// Ping
Multiple items
type MailboxProcessor<'Msg> =
  interface IDisposable
  new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:CancellationToken -> MailboxProcessor<'Msg>
  member Post : message:'Msg -> unit
  member PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
  member PostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply
  member PostAndTryAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply option>
  member Receive : ?timeout:int -> Async<'Msg>
  member Scan : scanner:('Msg -> Async<'T> option) * ?timeout:int -> Async<'T>
  member Start : unit -> unit
  member TryPostAndReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> 'Reply option
  ...

Full name: Microsoft.FSharp.Control.MailboxProcessor<_>

--------------------
new : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:System.Threading.CancellationToken -> MailboxProcessor<'Msg>
val pong1 : MailboxProcessor<string * (string -> unit)>

Full name: Script.pong1
type Agent<'a> = MailboxProcessor<'a>

Full name: Script.Agent<_>
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val inbox : MailboxProcessor<string * (string -> unit)>
val loop : (System.Collections.Generic.List<string> -> Async<unit>)
val state : System.Collections.Generic.List<string>
namespace System
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type List<'T> =
  new : unit -> List<'T> + 2 overloads
  member Add : item:'T -> unit
  member AddRange : collection:IEnumerable<'T> -> unit
  member AsReadOnly : unit -> ReadOnlyCollection<'T>
  member BinarySearch : item:'T -> int + 2 overloads
  member Capacity : int with get, set
  member Clear : unit -> unit
  member Contains : item:'T -> bool
  member ConvertAll<'TOutput> : converter:Converter<'T, 'TOutput> -> List<'TOutput>
  member CopyTo : array:'T[] -> unit + 2 overloads
  ...
  nested type Enumerator

Full name: System.Collections.Generic.List<_>

--------------------
System.Collections.Generic.List() : unit
System.Collections.Generic.List(capacity: int) : unit
System.Collections.Generic.List(collection: System.Collections.Generic.IEnumerable<'T>) : unit
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val msg : string * (string -> unit)
member MailboxProcessor.Receive : ?timeout:int -> Async<'Msg>
val m : string
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...

Full name: System.Console
System.Console.WriteLine() : unit
   (+0 other overloads)
System.Console.WriteLine(value: string) : unit
   (+0 other overloads)
System.Console.WriteLine(value: obj) : unit
   (+0 other overloads)
System.Console.WriteLine(value: uint64) : unit
   (+0 other overloads)
System.Console.WriteLine(value: int64) : unit
   (+0 other overloads)
System.Console.WriteLine(value: uint32) : unit
   (+0 other overloads)
System.Console.WriteLine(value: int) : unit
   (+0 other overloads)
System.Console.WriteLine(value: float32) : unit
   (+0 other overloads)
System.Console.WriteLine(value: float) : unit
   (+0 other overloads)
System.Console.WriteLine(value: decimal) : unit
   (+0 other overloads)
val f : (string -> unit)
System.Collections.Generic.List.Add(item: string) : unit
property System.Collections.Generic.List.Count: int
val pong2 : MailboxProcessor<string * (string -> unit)>

Full name: Script.pong2
val ping : target1:Agent<string * (string -> unit)> -> target2:Agent<string * (string -> unit)> -> MailboxProcessor<string>

Full name: Script.ping
val target1 : Agent<string * (string -> unit)>
val target2 : Agent<string * (string -> unit)>
val inbox : MailboxProcessor<string>
val target : Agent<string * (string -> unit)> ref
Multiple items
val ref : value:'T -> 'T ref

Full name: Microsoft.FSharp.Core.Operators.ref

--------------------
type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>
val x : int
member MailboxProcessor.Post : message:'Msg -> unit
val msg : string

More information

Link:http://fssnip.net/bN
Posted:11 years ago
Author:Ryan Riley
Tags: mailboxprocessor , agent , ping pong