Skip to content

Instantly share code, notes, and snippets.

@Szer
Last active August 15, 2021 11:03
Show Gist options
  • Select an option

  • Save Szer/504bcbfa0be21a230a918fe641db87fe to your computer and use it in GitHub Desktop.

Select an option

Save Szer/504bcbfa0be21a230a918fe641db87fe to your computer and use it in GitHub Desktop.
#r "nuget: Hopac"
open System
open System.Threading
open Hopac
// ------- IMPLEMENTATION -------
type IQueue<'a> =
abstract member Dequeue: Alt<'a>
let uberQueue (queues: IQueue<_> seq) =
let dequeueAlt = // we need only one Alt object, don't need to recreate it
queues
|> Seq.map (fun x -> x.Dequeue)
|> Alt.choose
{ new IQueue<_> with
member _.Dequeue = dequeueAlt }
// ------- EXAMPLE -------
let inline threadName() =
if String.IsNullOrEmpty Thread.CurrentThread.Name then
$"non-Hopac thread %3d{Thread.CurrentThread.ManagedThreadId}"
else
$"%20s{Thread.CurrentThread.Name}"
let createQueue name =
let ch = Ch<int>() // internal implementation of queue
// fill the channel indefinitely with numbers
fun x -> job {
Console.WriteLine $"%4s{name} - {threadName()} - waiting to give {x} ..."
do! Ch.give ch x
Console.WriteLine $"%4s{name} - {threadName()} - {x} was given"
return x + 1
}
|> Job.iterateServer 0 // starting from 0
|> queue
// return IQueue object
{ new IQueue<int> with
member _.Dequeue = upcast ch }
let q1 = createQueue "q1"
let q2 = createQueue "q2"
let q = uberQueue [q1; q2]
let dequeueJob = job {
Console.WriteLine $"uber - {threadName()} - trying to dequeue..."
let! x = q.Dequeue
Console.WriteLine $"uber - {threadName()} - got {x}"
}
Job.forN 10 dequeueJob
|> run
q1 - Hopac.Worker.1/8 - waiting to give 0 ...
uber - non-Hopac thread 1 - trying to dequeue...
q2 - Hopac.Worker.0/8 - waiting to give 0 ...
uber - non-Hopac thread 1 - got 0
uber - non-Hopac thread 1 - trying to dequeue...
uber - non-Hopac thread 1 - got 0
uber - non-Hopac thread 1 - trying to dequeue...
q1 - Hopac.Worker.0/8 - 0 was given
q2 - Hopac.Worker.1/8 - 0 was given
q1 - Hopac.Worker.0/8 - waiting to give 1 ...
q2 - Hopac.Worker.1/8 - waiting to give 1 ...
q1 - Hopac.Worker.0/8 - 1 was given
q1 - Hopac.Worker.0/8 - waiting to give 2 ...
uber - Hopac.Worker.0/8 - got 1
uber - Hopac.Worker.0/8 - trying to dequeue...
uber - Hopac.Worker.0/8 - got 2
uber - Hopac.Worker.0/8 - trying to dequeue...
uber - Hopac.Worker.0/8 - got 1
uber - Hopac.Worker.0/8 - trying to dequeue...
q1 - Hopac.Worker.1/8 - 2 was given
q2 - Hopac.Worker.0/8 - 1 was given
q2 - Hopac.Worker.0/8 - waiting to give 2 ...
q1 - Hopac.Worker.1/8 - waiting to give 3 ...
q2 - Hopac.Worker.0/8 - 2 was given
q2 - Hopac.Worker.0/8 - waiting to give 3 ...
uber - Hopac.Worker.0/8 - got 2
uber - Hopac.Worker.0/8 - trying to dequeue...
uber - Hopac.Worker.0/8 - got 3
uber - Hopac.Worker.0/8 - trying to dequeue...
uber - Hopac.Worker.0/8 - got 3
uber - Hopac.Worker.0/8 - trying to dequeue...
q1 - Hopac.Worker.1/8 - 3 was given
q2 - Hopac.Worker.0/8 - 3 was given
q1 - Hopac.Worker.1/8 - waiting to give 4 ...
q2 - Hopac.Worker.0/8 - waiting to give 4 ...
q1 - Hopac.Worker.1/8 - 4 was given
q1 - Hopac.Worker.1/8 - waiting to give 5 ...
uber - Hopac.Worker.1/8 - got 4
uber - Hopac.Worker.1/8 - trying to dequeue...
uber - Hopac.Worker.1/8 - got 5
q1 - Hopac.Worker.1/8 - 5 was given
q1 - Hopac.Worker.1/8 - waiting to give 6 ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment