9 people like it.
Like the snippet!
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
More information