9 people like it.

Agent based ObjectPool

This is a simple implementation of an object pool using an agent (MailboxProcessor). The pool is created with an initial number of object using the specified generator. The ObjectPool has three functions: Put: An item can be 'Put' into the pool. Get: An item can be taken from the pool ToListAndClear: A list of all the items in the pool is returned and the pool is cleared.

 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: 
module Poc

//Agent alias for MailboxProcessor
type Agent<'T> = MailboxProcessor<'T>

///One of three messages for our Object Pool agent
type PoolMessage<'a> =
    | Get of AsyncReplyChannel<'a>
    | Put of 'a
    | Clear of AsyncReplyChannel<List<'a>>

/// Object pool representing a reusable pool of objects
type ObjectPool<'a>(generate: unit -> 'a, initialPoolCount) = 
    let initial = List.init initialPoolCount (fun (x) -> generate())
    let agent = Agent.Start(fun inbox ->
        let rec loop(x) = async {
            let! msg = inbox.Receive()
            match msg with
            | Get(reply) -> 
                let res = match x with
                          | a :: b -> 
                              reply.Reply(a);b
                          | [] as empty-> 
                              reply.Reply(generate());empty
                return! loop(res)
            | Put(value)-> 
                return! loop(value :: x) 
            | Clear(reply) -> 
                reply.Reply(x)
                return! loop(List.empty<'a>) }
        loop(initial))

    /// Clears the object pool, returning all of the data that was in the pool.
    member this.ToListAndClear() = 
        agent.PostAndAsyncReply(Clear)
    /// Puts an item into the pool
    member this.Put(item ) = 
        agent.Post(item)
    /// Gets an item from the pool or if there are none present use the generator
    member this.Get(item) = 
        agent.PostAndAsyncReply(Get)
module Poc
type Agent<'T> = MailboxProcessor<'T>

Full name: Poc.Agent<_>
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>
type PoolMessage<'a> =
  | Get of AsyncReplyChannel<'a>
  | Put of 'a
  | Clear of AsyncReplyChannel<List<'a>>

Full name: Poc.PoolMessage<_>


One of three messages for our Object Pool agent
union case PoolMessage.Get: AsyncReplyChannel<'a> -> PoolMessage<'a>
type AsyncReplyChannel<'Reply>
member Reply : value:'Reply -> unit

Full name: Microsoft.FSharp.Control.AsyncReplyChannel<_>
union case PoolMessage.Put: 'a -> PoolMessage<'a>
union case PoolMessage.Clear: AsyncReplyChannel<List<'a>> -> PoolMessage<'a>
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
Multiple items
type ObjectPool<'a> =
  new : generate:(unit -> 'a) * initialPoolCount:int -> ObjectPool<'a>
  member Get : item:'a0 -> Async<'a>
  member Put : item:PoolMessage<'a> -> unit
  member ToListAndClear : unit -> Async<List<'a>>

Full name: Poc.ObjectPool<_>


 Object pool representing a reusable pool of objects


--------------------
new : generate:(unit -> 'a) * initialPoolCount:int -> ObjectPool<'a>
val generate : (unit -> 'a)
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val initialPoolCount : int
val initial : 'a list
val init : length:int -> initializer:(int -> 'T) -> 'T list

Full name: Microsoft.FSharp.Collections.List.init
val x : int
val agent : MailboxProcessor<PoolMessage<'a>>
static member MailboxProcessor.Start : body:(MailboxProcessor<'Msg> -> Async<unit>) * ?cancellationToken:System.Threading.CancellationToken -> MailboxProcessor<'Msg>
val inbox : MailboxProcessor<PoolMessage<'a>>
val loop : ('a list -> Async<'b>)
val x : 'a list
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
val msg : PoolMessage<'a>
member MailboxProcessor.Receive : ?timeout:int -> Async<'Msg>
val reply : AsyncReplyChannel<'a>
val res : 'a list
val a : 'a
val b : 'a list
member AsyncReplyChannel.Reply : value:'Reply -> unit
val empty : 'a list
val value : 'a
val reply : AsyncReplyChannel<List<'a>>
val empty<'T> : 'T list

Full name: Microsoft.FSharp.Collections.List.empty
val this : ObjectPool<'a>
member ObjectPool.ToListAndClear : unit -> Async<List<'a>>

Full name: Poc.ObjectPool`1.ToListAndClear


 Clears the object pool, returning all of the data that was in the pool.
member MailboxProcessor.PostAndAsyncReply : buildMessage:(AsyncReplyChannel<'Reply> -> 'Msg) * ?timeout:int -> Async<'Reply>
member ObjectPool.Put : item:PoolMessage<'a> -> unit

Full name: Poc.ObjectPool`1.Put


 Puts an item into the pool
val item : PoolMessage<'a>
member MailboxProcessor.Post : message:'Msg -> unit
member ObjectPool.Get : item:'a0 -> Async<'a>

Full name: Poc.ObjectPool`1.Get


 Gets an item from the pool or if there are none present use the generator
val item : 'a
Raw view Test code New version

More information

Link:http://fssnip.net/5H
Posted:13 years ago
Author:7sharp9
Tags: async , agent , objectpool