How to use TryScan in F# properly - concurrency
I was trying to find an example about how to use TryScan, but haven't found any, could you help me?
What I would like to do (quite simplified example): I have a MailboxProcessor that accepts
two types of mesages.
First one GetState returns current state.
GetState messages are sent quite frequently
The other UpdateState is very expensive (time consuming) - e.g. downloading something from internet and then updates the state accordingly.
UpdateState is called only rarely.
My problem is - messages GetState are blocked and wait until preceding UpdateState are served. That's why I tried to use TryScan to process all GetState messages, but with no luck.
My example code:
type Msg = GetState of AsyncReplyChannel<int> | UpdateState
let mbox = MailboxProcessor.Start(fun mbox ->
let rec loop state = async {
// this TryScan doesn't work as expected
// it should process GetState messages and then continue
mbox.TryScan(fun m ->
match m with
| GetState(chnl) ->
printfn "G processing TryScan"
chnl.Reply(state)
Some(async { return! loop state})
| _ -> None
) |> ignore
let! msg = mbox.Receive()
match msg with
| UpdateState ->
printfn "U processing"
// something very time consuming here...
async { do! Async.Sleep(1000) } |> Async.RunSynchronously
return! loop (state+1)
| GetState(chnl) ->
printfn "G processing"
chnl.Reply(state)
return! loop state
}
loop 0
)
[async { for i in 1..10 do
printfn " U"
mbox.Post(UpdateState)
async { do! Async.Sleep(200) } |> Async.RunSynchronously
};
async { // wait some time so that several `UpdateState` messages are fired
async { do! Async.Sleep(500) } |> Async.RunSynchronously
for i in 1..20 do
printfn "G"
printfn "%d" (mbox.PostAndReply(GetState))
}] |> Async.Parallel |> Async.RunSynchronously
If you try to run the code, you will see, that GetState message is not almost processed, because it waits for the result. On the other hand UpdateState is only fire-and-forget, thus blocking effectively getting state.
Edit
Current solution that works for me is this one:
type Msg = GetState of AsyncReplyChannel<int> | UpdateState
let mbox = MailboxProcessor.Start(fun mbox ->
let rec loop state = async {
// this TryScan doesn't work as expected
// it should process GetState messages and then continue
let! res = mbox.TryScan((function
| GetState(chnl) -> Some(async {
chnl.Reply(state)
return state
})
| _ -> None
), 5)
match res with
| None ->
let! msg = mbox.Receive()
match msg with
| UpdateState ->
async { do! Async.Sleep(1000) } |> Async.RunSynchronously
return! loop (state+1)
| _ -> return! loop state
| Some n -> return! loop n
}
loop 0
)
Reactions to comments: the idea with other MailboxProcessor or ThreadPool that executes UpdateState in parallel is great, but I don't need it currently.
All I wanted to do is to process all GetState messages and after that the others. I don't care that during processing UpdateState the agent is blocked.
I'll show you what was the problem on the output:
// GetState messages are delayed 500 ms - see do! Async.Sleep(500)
// each UpdateState is sent after 200ms
// each GetState is sent immediatelly! (not real example, but illustrates the problem)
U 200ms <-- issue UpdateState
U processing <-- process UpdateState, it takes 1sec, so other
U 200ms 5 requests are sent; sent means, that it is
U 200ms fire-and-forget message - it doesn't wait for any result
and therefore it can send every 200ms one UpdateState message
G <-- first GetState sent, but waiting for reply - so all
previous UpdateState messages have to be processed! = 3 seconds
and AFTER all the UpdateState messages are processed, result
is returned and new GetState can be sent.
U 200ms
U 200ms because each UpdateState takes 1 second
U 200ms
U processing
U
U
U
U
U processing
G processing <-- now first GetState is processed! so late? uh..
U processing <-- takes 1sec
3
G
U processing <-- takes 1sec
U processing <-- takes 1sec
U processing <-- takes 1sec
U processing <-- takes 1sec
U processing <-- takes 1sec
U processing <-- takes 1sec
G processing <-- after MANY seconds, second GetState is processed!
10
G
G processing
// from this line, only GetState are issued and processed, because
// there is no UpdateState message in the queue, neither it is sent
I don't think that the TryScan method will help you in this scenario. It allows you to specify timeout to be used while waiting for messages. Once some message is received, it will start processing the message (ignoring the timeout).
For example, if you wanted to wait for some specific message, but perform some other checking every second (while waiting) you could write:
let loop () = async {
let! res = mbox.TryScan(function
| ImportantMessage -> Some(async {
// process message
return 0
})
| _ -> None)
match res with
| None ->
// perform some check & continue waiting
return! loop ()
| Some n ->
// ImportantMessage was received and processed
}
What can you do to avoid blocking the mailbox processor when processing the UpdateState message? The mailbox processor is (logically) single-threaded - you probably don't want to cancel the processing of UpdateState message, so the best option is to start processing it in background and wait until the processing completes. The code that processes UpdateState can then send some message back to the mailbox (e.g. UpdateStateCompleted).
Here is a sketch how this might look:
let rec loop (state) = async {
let! msg = mbox.Receive()
match msg with
| GetState(repl) ->
repl.Reply(state)
return! scanning state
| UpdateState ->
async {
// complex calculation (runs in parallel)
mbox.Post(UpdateStateCompleted newState) }
|> Async.Start
| UpdateStateCompleted newState ->
// Received new state from background workflow
return! loop newState }
Now that the background task is running in parallel, you need to be careful about mutable state. Also, if you send UpdateState messages faster than you can process them, you'll be in trouble. This can be fixed, for example, by ignoring or queueing requests when you're already processing previous one.
DON'T USE TRYSCAN!!!
Unfortunately, the TryScan function in the current version of F# is broken in two ways. Firstly, the whole point is to specify a timeout but the implementation does not actually honor it. Specifically, irrelevant messages reset the timer. Secondly, as with the other Scan function, the message queue is examined under a lock that prevents any other threads from posting for the duration of the scan, which can be an arbitrarily long time. Consequently, the TryScan function itself tends to lock-up concurrent systems and can even introduce deadlocks because the caller's code is evaluated inside the lock (e.g. posting from the function argument to Scan or TryScan can deadlock the agent when the code under the lock blocks waiting to acquire the lock it is already under).
I used TryScan in an early prototype of my production code and it caused no end of problems. However, I managed to architect around it and the resulting architecture was actually better. In essence, I eagerly Receive all messages and filter using my own local queue.
As Tomas mentioned MailboxProcessor is single threaded. You will need another MailboxProcessor to run the updates on a separate thread from the state getter.
#nowarn "40"
type Msg =
| GetState of AsyncReplyChannel<int>
| UpdateState
let runner_UpdateState = MailboxProcessor.Start(fun mbox ->
let rec loop = async {
let! state = mbox.Receive()
printfn "U start processing %d" !state
// something very time consuming here...
do! Async.Sleep 100
printfn "U done processing %d" !state
state := !state + 1
do! loop
}
loop
)
let mbox = MailboxProcessor.Start(fun mbox ->
// we need a mutiple state if another thread can change it at any time
let state = ref 0
let rec loop = async {
let! msg = mbox.Receive()
match msg with
| UpdateState -> runner_UpdateState.Post state
| GetState chnl -> chnl.Reply !state
return! loop
}
loop)
[
async {
for i in 1..10 do
mbox.Post UpdateState
do! Async.Sleep 200
};
async {
// wait some time so that several `UpdateState` messages are fired
do! Async.Sleep 1000
for i in 1..20 do
printfn "G %d" (mbox.PostAndReply GetState)
do! Async.Sleep 50
}
]
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
System.Console.ReadLine() |> ignore
output:
U start processing 0
U done processing 0
U start processing 1
U done processing 1
U start processing 2
U done processing 2
U start processing 3
U done processing 3
U start processing 4
U done processing 4
G 5
U start processing 5
G 5
U done processing 5
G 5
G 6
U start processing 6
G 6
G 6
U done processing 6
G 7
U start processing 7
G 7
G 7
U done processing 7
G 8
G U start processing 8
8
G 8
U done processing 8
G 9
G 9
U start processing 9
G 9
U done processing 9
G 9
G 10
G 10
G 10
G 10
You could also use ThreadPool.
open System.Threading
type Msg =
| GetState of AsyncReplyChannel<int>
| SetState of int
| UpdateState
let mbox = MailboxProcessor.Start(fun mbox ->
let rec loop state = async {
let! msg = mbox.Receive()
match msg with
| UpdateState ->
ThreadPool.QueueUserWorkItem((fun obj ->
let state = obj :?> int
printfn "U start processing %d" state
Async.Sleep 100 |> Async.RunSynchronously
printfn "U done processing %d" state
mbox.Post(SetState(state + 1))
), state)
|> ignore
| GetState chnl ->
chnl.Reply state
| SetState newState ->
return! loop newState
return! loop state
}
loop 0)
[
async {
for i in 1..10 do
mbox.Post UpdateState
do! Async.Sleep 200
};
async {
// wait some time so that several `UpdateState` messages are fired
do! Async.Sleep 1000
for i in 1..20 do
printfn "G %d" (mbox.PostAndReply GetState)
do! Async.Sleep 50
}
]
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
System.Console.ReadLine() |> ignore
Related
Putting lwt.t code in infinite loop in Ocaml for mirage os
I have the following code block which I modified from the mirageOS github repo: open Lwt.Infix module Main (KV: Mirage_kv.RO) = struct let start kv = let read_from_file kv = KV.get kv (Mirage_kv.Key.v "secret") >|= function | Error e -> Logs.warn (fun f -> f "Could not compare the secret against a known constant: %a" KV.pp_error e) | Ok stored_secret -> Logs.info (fun f -> f "Data -> %a" Format.pp_print_string stored_secret); in read_from_file kv end This code reads data from a file called "secret" and outputs it once. I want to read the file and output from it constantly with sleep in between. The usage case is this: While this program is running I will update the secret file with other processes, so I want to see the change in the output. What I tried ? I tried to put the last statement in while loop with in while true do read_from_file kv done But It gives the error This expression has type unit Lwt.t but an expression was expected of type unit because it is in the body of a while loop. I just know that lwt is a threading library but I'm not a ocaml developer and don't try to be one, (I'm interested in MirageOS) , so I can't find the functional syntax to write it.
You need to write the loop as a function. e.g. let rec loop () = read_from_file kv >>= fun () -> (* wait here? *) loop () in loop ()
How to make a loop break when using Lwt in OCaml
I'm writing code to monitor the content of a file. When the program reaches the end of the the file I want it to terminate cleanly. let log () : input_channel Lwt.t = openfile "log" [O_RDONLY] 0 >>= fun fd -> Lwt.return (of_fd input fd);; let rec loop (ic: input_channel) = Lwt_io.read_line ic >>= fun text -> Lwt_io.printl text >>= fun _ -> loop ic;; let monitor () : unit Lwt.t = log () >>= loop;; let handler : exn -> unit Lwt.t = fun e -> match e with | End_of_file -> let (p: unit Lwt.t), r = Lwt.wait() in p | x -> Lwt.fail x;; let main () : unit Lwt.t = Lwt.catch monitor handler;; let _ = Lwt_main.run (main ());; However, when reading a file and reaching the end, the program does not terminate, it just hangs and I have to escape with Ctrl+c. I am not sure what is going on under the hood with bind but I figured whatever it's doing, eventually Lwt_io.readline ic should eventually hit the end of the file and return an End_of_file exception, which presumably would get passed over to the handler, etc. If I had to guess at a resolution, I would think maybe in the last bind of the definition of >>= I would include some if check. But I'd be checking, I think, whether Lwt_io.read_line returned End_of_file, which I though should be handled by the handler.
The Lwt.wait function creates a promise which could only be resolved using the second element of the returned pair, basically, this function will never terminate: let never_ready () = let (p,_) = Lwt.wait in p and this is exactly what you've written. Concerning a graceful termination, ideally, you should do this in the loop function so that you can close the channel and prevent leaking of the valuable resources, e.g., let rec loop (ic: input_channel) = Lwt_io.read_line ic >>= function | exception End_of_file -> Lwt.close ic | text-> Lwt_io.printl text >>= fun () -> loop ic The minimum change to your code would be, however, to use Lwt.return () instead of Lwt.wait in the body of your handler.
Interrupt a call in OCaml
I'd like to interrupt a call if it takes too long to compute, like this try do_something () with Too_long -> something_else () Is it possible to do something like that in OCaml? The function do_something may not be modified.
In general the only way to interrupt a function is to use a signal, as Basile suggested. Unfortunately the control flow will be transferred to a signal handler, so that you will be unable to return a value that you like. To get a more fine-grained control, you can run you do_something in separate thread. A first approximation would be the following function: exception Timeout let with_timeout timeout f = let result = ref None in let finished = Condition.create () in let guard = Mutex.create () in let set x = Mutex.lock guard; result := Some x; Mutex.unlock guard in Mutex.lock guard; let work () = let x = f () in set x; Condition.signal finished in let delay () = Thread.delay timeout; Condition.signal finished in let task = Thread.create work () in let wait = Thread.create delay () in Condition.wait finished guard; match !result with | None -> Thread.kill task; raise Timeout | Some x -> Thread.kill wait; x The solution with threads as well as with signal function has some drawbacks. For example, threads are switched in OCaml in specific iterruption points, in general this is any allocations. So if your code doesn't perform any allocations or external calls, then it may never yield to other thread and will run forever. A good example of such function is let rec f () = f (). In this is your case, then you should run your function in another process instead of thread. There're many libraries for multiprocessing in OCaml, to name a few: parmap forkwork async-parallel lwt-parallel
There is no built-in facility to perform this precise operation in the standard library, but it is rather straightforward to implement. Using the Thread module, run one thread to perform your main program and a monitoring thread that will kill the program if it lasts too long. Here is a starting implementation: type 'a state = | Running | Finished of 'a | Failed of exn | Cancelled of 'a let bounded_run d f g x = let state = ref Running in let p = ref None in let m = ref None in let cancel t' = match !t' with | Some(t) -> Thread.kill t | None -> () in let program () = (try state := Finished(f x) with exn -> state := Failed (exn)); cancel m; in let monitor () = Thread.delay d; match !state with | Running -> cancel p; state := Cancelled(g x) | _ -> () in p := Some(Thread.create program ()); m := Some(Thread.create monitor p); (match !m with | None -> () | Some(t) -> Thread.join t); !state The call bounded_run d f g x runs f x for at most d seconds and returns Finished(f x) if the computation runs in the given time. It might return Failed(exn) if the computation throws an exception. When the computation lasts too long, the returned value is Cancelled(g x). This implementation has many defaults, for instance, the state and the returned values should have different types (the value Running should not be possible in the returned type), it does not use mutexes to prevent concurrent accesses to the p and m variables holding references to the threads we use. While it is rough at the edges, this should get you started, but for more advanced usage, you should also learn Event or 3rd party libraries such as Lwt or Async – the former will require you to change your function.
(I guess that you are on Linux) Read more about signal(7)-s. You could use Ocaml's Sys.signal for Sys.sigalarm and Unix module (notably Unix.setitimer)
OCaml writing a timeout function using Async
I'm trying to write a function that tries to evaluate a function, but stops after a specific timeout. I tried to use Deferred.any, which returns a deferred that is fulfilled when one of the underlying deferred is fulfilled. type 'a output = OK of 'a | Exn of exn let fun_test msg f eq (inp,ans) = let outp = wait_for (Deferred.any [ return (try OK (f inp) with e -> Exn e) ; (after (Core.Std.sec 0.0) >>| (fun () -> Exn TIMEOUT))]) in {msg = msg;inp = inp;outp = outp;ans = ans;pass = eq outp ans} I was not sure how to extract a value from the deferred monad, so I wrote a function 'wait_for' which just spins until the underlying value is determined. let rec wait_for x = match Deferred.peek x with | None -> wait_for x | Some done -> done;; This did not work. After reading through the Async chapter of Real World OCaml, I realized I needed to start the scheduler. However I'm not sure where I would call Schedule.go in my code. I do not see where the type go : ?raise_unhandled_exn:bool -> unit -> Core.Std.never_returns would fit into code where you actually want your asynchronous code to return. The documentation for go says "Async programs do not exit until shutdown is called." I was beginning to doubt I had taken the entirely wrong approach to the problem until I found a very similar solution to that same problem on this Cornell website let timeout (thunk:unit -> 'a Deferred.t) (n:float) : ('a option) Deferred.t = Deferred.any [ after (sec n) >>| (fun () -> None) ; thunk () >>= (fun x -> Some x) ] Anyway, I'm not quite sure my use of wait_for is correct. Is there a canonical way to extract a value from the deferred monad? Also how do I start the scheduler? Update: I tried writing a timeout function using only Core.Std.Thread and Core.Std.Mutex. let rec wait_for lck ptr = Core.Std.Thread.delay 0.25; Core.Std.Mutex.lock lck; (match !ptr with | None -> Core.Std.Mutex.unlock lck; wait_for lck ptr | Some x -> Core.Std.Mutex.unlock lck; x);; let timeout t f = let lck = Core.Std.Mutex.create () in let ptr = ref None in let _ = Core.Std.Thread.create (fun () -> Core.Std.Thread.delay t; Core.Std.Mutex.lock lck; (match !ptr with | None -> ptr := Some (Exn TIMEOUT) | Some _ -> ()); Core.Std.Mutex.unlock lck;) () in let _ = Core.Std.Thread.create (fun () -> let x = f () in Core.Std.Mutex.lock lck; (match !ptr with | None -> ptr := Some x | Some _ -> ()); Core.Std.Mutex.unlock lck;) () in wait_for lck ptr I think this is pretty close to working. It works on computations like let rec loop x = print_string ".\n"; loop x, but it does not work on computations like let rec loop x = loop x. I believe the problem right now is that if the computation f () loops infinitely, then its thread is never preempted, so none of other threads can notice the timeout has expired. If the thread does IO like printing a string, then the thread does get preempted. Also I don't know how to kill a thread, I couldn't find such a function in the documentation for Core.Std.Thread
The solution I came up with is let kill pid sign = try Unix.kill pid sign with | Unix.Unix_error (e,f,p) -> debug_print ((Unix.error_message e)^"|"^f^"|"^p) | e -> raise e;; let timeout f arg time default = let pipe_r,pipe_w = Unix.pipe () in (match Unix.fork () with | 0 -> let x = Some (f arg) in let oc = Unix.out_channel_of_descr pipe_w in Marshal.to_channel oc x []; close_out oc; exit 0 | pid0 -> (match Unix.fork () with | 0 -> Unix.sleep time; kill pid0 Sys.sigkill; let oc = Unix.out_channel_of_descr pipe_w in Marshal.to_channel oc default []; close_out oc; exit 0 | pid1 -> let ic = Unix.in_channel_of_descr pipe_r in let result = (Marshal.from_channel ic : 'b option) in result ));; I think I might be creating two zombie processes with this though. But it is the only solution that works on let rec loop x = loop x when compiled using ocamlopt (The solution using Unix.alarm given here works when compiled with ocamlc but not when compiled with ocamlopt).
Sending messages in circles.
I am new to functional programming and just switched from haskell (Didn't like it much) to erlang (quite fond of it). As I am learning as an autodidact, I stumbled over these Exercises and started doing them. I came as far as this problem: Write a function which starts 2 processes, and sends a message M times forewards and backwards between them. After the messages have been sent the processes should terminate gracefully. I resolved it like this and it works (maybe it can be done better; any comment highly appreciated): -module (concur). -export ( [pingpong/1, pingpong/2] ). pingpong (Msg, TTL) -> A = spawn (concur, pingpong, ["Alice"] ), B = spawn (concur, pingpong, ["Bob"] ), B ! {A, TTL * 2, Msg}. pingpong (Name) -> receive {From, 1, Msg} -> io:format ("~s received ~p and dying.~n", [Name, Msg] ), exit (From); {From, TTL, Msg} -> io:format ("~s received ~p.~n", [Name, Msg] ), From ! {self (), TTL - 1, Msg}, pingpong (Name) end. The real problem is the next exercise: 2) Write a function which starts N processes in a ring, and sends a message M times around all the processes in the ring. After the messages have been sent the processes should terminate gracefully. As I am not sending the message back to its originator, but to the next node in the chain, I somehow have to pass to the sending process the process of the recipient. So I imagined that the function would look something like this: pingCircle (Name, Next) -> ... receive {TTL, Msg} -> Next ! {TTL - 1, Msg} ... But how do I start this whole thing. When I spawn the first function in the circle, I still haven't spawned the next node and hence I cannot pass it as an argument. So my naive approach doesn't work: First = spawn (concur, pingCirle, ["Alice", Second] ), Second = spawn (concur, pingCirle, ["Bob", Third] ), ... Also the approach of passing the spawn call of the next node recursively as a parameter to it predecessor, doesn't solve the problem how to close the circle, i.e. passing the last node to the first. The question is: How can I build this circle? EDIT: Thanks to your great answers, I managed to what I intended. Hence this question is solved. One possible solution is: -module (concur). -export ( [pingCircle/3, pingCircle/2] ). pingCircle (Names, Message, TTL) -> Processes = lists:map (fun (Name) -> spawn (?MODULE, pingCircle, [Name, nobody] ) end, Names), ProcessPairs = lists:zip (Processes, rot1 (Processes) ), lists:map (fun ( {Process, Recipient} ) -> Process ! {setRecipient, Recipient} end, ProcessPairs), Circle = lists:map (fun ( {Process, _} ) -> Process end, ProcessPairs), hd (Circle) ! {Message, TTL - 1, lists:last (Circle) }. rot1 ( [] ) -> []; rot1 ( [Head | Tail] ) -> Tail ++ [Head]. pingCircle (Name, Recipient) -> receive {setRecipient, NewRecipient} -> pingCircle (Name, NewRecipient); {Message, 0, Originator} -> io:format ("~s received ~p with TTL 0 and dying.~n", [Name, Message] ), if Originator == self () -> io:format ("All dead.~n"); true -> Recipient ! {Message, 0, Originator} end; {Message, TTL, Originator} -> io:format ("~s received ~p with TTL ~p.~n", [Name, Message, TTL] ), if Originator == self () -> Recipient ! {Message, TTL - 1, Originator}; true -> Recipient ! {Message, TTL, Originator} end, pingCircle (Name, Recipient) end. Here is my peer review link.
This exercise has become a rite of passage for all erlang programmers. I gave a working solution to it here, along with an explanation that may be helpful.
Spawn them first, then send them a start signal. The start signal would be sent after all the processes are already running.
Someone already came up with the answer here -> http://simplehappy.iteye.com/?show_full=true
My answer. -module(con_test). start_ring(Msg, M, N) -> [First|_]=Processes=[spawn(?MODULE, ring, []) || _ <- lists:seq(1,N)], First ! {rotLeft(Processes), {Msg, M*N}}. ring() -> receive {_List, {Msg, Count}} when Count == 0 -> io:format("~p got ~s. Enough! I'm out.~n", [self(), Msg]), exit(normal); {[Next|_] = List, {Msg, Count}} when Count > 0 -> io:format("~p got ~s. Passing it forward to ~p.~n", [self(), Msg, Next]), Next ! {rotLeft(List), {Msg, Count-1}}, ring() after 1000 -> io:format("~p is out.~n", [self()]), exit(normal) end. rotLeft([]) -> []; rotLeft([H|T]) -> T ++[H].