Home > Mobile >  How to create multiple Threads in OCaml
How to create multiple Threads in OCaml

Time:07-30

The function run_counter may create m threads, each counting from 0 to n:

let run_counters m n = 
            let rec count x = 
              if x > n then ()
              else ( Printf.printf "%d" x;
            Thread.yield ();
            count (x 1) ) 
            in 
            Thread.create count 0

However I don't know how to create multiple Threads, I tried to write a recursive call with a counter m but I get an Error:This expression has type t but an expression was expected of type unit

let run_counters m n = 
            let rec count x = 
              if x > n then ()
              else ( Printf.printf "%d" x;
            Thread.yield ();
            count (x 1) ) 
            in 
            let rec inc n =
            if n = 0 then () else
            inc (n-1);
            Thread.create count 0; 
        

CodePudding user response:

Ok so your function is a bit of mess, first there is a syntax error:

let run_counters m n = 
            let rec count x = 
              if x > n then ()
              else ( Printf.printf "%d" x;
            Thread.yield ();
            count (x 1) ) 
            in 
            let rec inc n =
            if n = 0 then () else
    >>>>>   inc (n-1);
            Thread.create count 0; 
        

At location >>>>>, there is a let rec inc... without an in ... following it, you just interrupt the expression with a semicolon. If we replace it with in, then the function inc is reported as being unused.

Let's take a step back for a minute, and write each functions separately, this will become a lot easier than trying to do everything at once. Also, you can test individual functions more easily.

Do something n times

First, write a function that calls some function f for its side-effects, n times. We could write a recursive version (and if that's homework, you probably are asked to do that), but OCaml has for loops so let's use them:

let rec call_n_times f n =
  for i = 0 to (n-1) do
    f i
  done

For example, this prints number from 0 to 2, and returns nothing (unit type):

# call_n_times (fun n -> Printf.printf "%d\n" n) 3;;
0
1
2
- : unit = ()

In fact, this example is what your threads are supposed to do (what a coincidence).

Print increasing numbers

In our future tests we will be calling different counters, so let's add a parameter that is the name of the counter:

# let print_n name = call_n_times (fun i -> Printf.printf "%s %d\n" name i);;
val print_n : string -> int -> unit = <fun>

As you can see, we name print_n the partial application of call_n_times with a function, the remaining argument n is implicit here.

# print_n "test" 3;;
test: 0
test: 1
test: 2

Spawn 1 thread

The next step is writing a function that just spawns one thread, and ask it to execute print_n (so it needs an integer argument) with the name of the thread.

Using partial application as previously, this is:

# let spawn_counter name = Thread.create (print_n name);;
val spawn_counter : string -> int -> Thread.t = <fun>

For example:

# spawn_counter "single-thread" 3;;
- : Thread.t = <abstr>

# Thread.yield();;
single-thread: 0
single-thread: 1
single-thread: 2
- : unit = ()

Name a thread from a number

We need also an intermediate function that produces a name (a string) from a number, let's quickly write that:

# let thread_name = Printf.sprintf "<thread %d>";;
val thread_name : int -> string = <fun>

Spawn m threads

Now we can write spawn_m_n_counters:

# let spawn_m_n_counters m n =
    call_n_times (fun i -> spawn_counter (thread_name i) n) m;;
val spawn_m_n_counters : int -> int -> unit = <fun>

# spawn_m_n_counters 3 5;;
- : unit = ()

Refactor

You have a basic skeleton of your functions, but I left Thread.yield() out of the functions.

Also, you want to collect all the spawn threads so that you can join them. That means you need a call_n_times that collects the output of the function. See if you can write that recursively.

  • Related