Goroutines in Modelica

Based on your instructions, here is the translated code and explanation from the provided example in Modelica, in Markdown format suitable for Hugo:

A goroutine is a lightweight thread of execution.

model Main
  function f
    input String from;
  algorithm 
    for i in 1:3 loop
      Modelica.Utilities.Streams.print(from + " : " + String(i));
    end for;
  end f;

  algorithm
    // Running a function call synchronously
    f("direct");
    
    // Running a function call asynchronously using 'synchronous'
    Modelica_Utilities.Internal.PartialThreads.Synchronous->
      (?&(f("goroutine")) start(f("goroutine")));

    // Running an anonymous function asynchronously
    model Anonymous
      algorithm
        Modelica.Utilities.Streams.print("going");
    end Anonymous;

    Modelica_Utilities.Internal.PartialThreads.Synchronous->
      (?&(Anonymous()) start(Anonymous()));

    // Waiting for a while to let the asynchronous calls complete
    delay(1.0);
    Modelica.Utilities.Streams.print("done");
end Main;

Suppose we have a function call f(s). Here’s how we’d call that in the usual way, running it synchronously.

f("direct");

To invoke this function in a concurrent process, use constructs available in Modelica for concurrency. This new process will execute concurrently with the calling one.

Modelica supports concurrent execution but doesn’t have constructs called goroutines like the language you’re translating from. However, we can create similar concurrency using blocks and the synchronous library.

Here, the provided utility Modelica_Utilities.Internal.PartialThreads.Synchronous is extracted from Modelica’s standard libraries to simulate concurrency. You can also start a concurrent execution for an anonymous function.

model Anonymous
  algorithm
    Modelica.Utilities.Streams.print("going");
end Anonymous;

Modelica_Utilities.Internal.PartialThreads.Synchronous->
  (?&(Anonymous()) start(Anonymous()));

Our function calls are now running asynchronously in separate concurrent processes. Wait for them to finish to ensure all output is collected (in a more robust approach, you might synchronize using advanced Modelica features).

delay(1.0);
Modelica.Utilities.Streams.print("done");

When we run this program, we see the output of the blocking call first, then the output of the concurrent processes. The processes’ output may be interleaved, because they are being run concurrently by the Modelica runtime.

$ simulate(Main)
direct : 1
direct : 2
direct : 3
goroutine : 1
going
goroutine : 2
goroutine : 3
done

Next, we’ll look at a complement to concurrent processes in concurrent programming: channels.