Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Commit

Permalink
Add PosterAgent and NumberProducer
Browse files Browse the repository at this point in the history
  • Loading branch information
ataias committed Jan 5, 2020
1 parent a616a36 commit 417c8b0
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,5 @@ $RECYCLE.BIN/
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

.ionide
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.PHONY: format

format:
fantomas --recurse --pageWidth 80 .

44 changes: 38 additions & 6 deletions average-agents/Agents.fs
Original file line number Diff line number Diff line change
@@ -1,35 +1,67 @@
module Agents

open System
open System.Threading

type Stats =
{ Count: int;
Sum: double; }
{ Count: int
Sum: double }

type Msg =
| Incr of double
| Fetch of AsyncReplyChannel<Stats>
| Die

type StatsAgent() =

let agent =
MailboxProcessor.Start(fun inbox ->
let rec loop stats =
async {
let! msg = inbox.Receive()
match msg with
| Incr(x) ->
return! loop { Count = stats.Count + 1; Sum = stats.Sum + x}
return! loop
{ Count = stats.Count + 1
Sum = stats.Sum + x }
| Fetch(replyChannel) ->
replyChannel.Reply(stats)
return! loop stats
| Die -> return ()
}
loop { Count = 0; Sum = 0.0 }
)
loop
{ Count = 0
Sum = 0.0 })

interface IDisposable with
member this.Dispose() = this.Die()

member _.Incr(x) = agent.Post(Incr x)
member _.Fetch() = agent.PostAndReply(Fetch)
member _.Die() = agent.Post(Die)
member _.Die() = agent.Post(Die)

type NumberProducer =
{ TotalNumbers: int
SleepIntervalMilliseconds: int }

type Poster =
{ Producers: NumberProducer [] }

type PosterAgent(statsAgent, poster) =
let (poster: Poster) = poster
let (statsAgent: StatsAgent) = statsAgent

let produce (id, numberProducer) =
async {
for i in 1 .. numberProducer.TotalNumbers do
statsAgent.Incr(double i)
Thread.Sleep(numberProducer.SleepIntervalMilliseconds)
printfn "Producer %d finished; Current stats: %A" id
(statsAgent.Fetch())
}

member _.Execute() =
let producers =
[ for id in 0 .. poster.Producers.Length - 1 ->
produce (id, poster.Producers.[id]) ]
Async.RunSynchronously(Async.Parallel producers) |> ignore
28 changes: 22 additions & 6 deletions average-agents/Program.fs
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
open System
open Agents

let measureTime f =
let stopWatch = Diagnostics.Stopwatch.StartNew()
f()
stopWatch.Stop()
stopWatch.Elapsed.TotalMilliseconds

let useAgents() =
use statsAgent = new StatsAgent()

let producers =
[| { TotalNumbers = 100
SleepIntervalMilliseconds = 50 }
{ TotalNumbers = 200
SleepIntervalMilliseconds = 30 } |]

let poster = { Producers = producers }

let posterAgent = PosterAgent(statsAgent, poster)
posterAgent.Execute()

[<EntryPoint>]
let main argv =
use statsAgent = new StatsAgent()
statsAgent.Incr(5.0)
statsAgent.Incr(7.0)
printfn "%A" (statsAgent.Fetch())
statsAgent.Incr(7.0)
printfn "%A" (statsAgent.Fetch())
let elapsedTime = measureTime useAgents
printfn "Program execution took %fms" elapsedTime
0 // return an integer exit code

0 comments on commit 417c8b0

Please sign in to comment.