Goroutines in Pascal

Our example demonstrates the concept of lightweight threads of execution called goroutines. Here’s the original source code:

package main

import (
    "fmt"
    "time"
)

func f(from string) {
    for i := 0; i < 3; i++ {
        fmt.Println(from, ":", i)
    }
}

func main() {
    f("direct")

    go f("goroutine")

    go func(msg string) {
        fmt.Println(msg)
    }("going")

    time.Sleep(time.Second)
    fmt.Println("done")
}

Let’s convert this example to Pascal, a language with a similar concept for concurrent execution using threads:

program GoroutinesExample;

uses
  crt, sysutils;

procedure f(from: string);
var
  i: integer;
begin
  for i := 0 to 2 do
  begin
    writeln(from, ' : ', i);
    sleep(100); // Add a slight delay to mimic concurrent behavior
  end;
end;

begin
  // Direct call
  f('direct');

  // Goroutine in Pascal: use a thread
  begin
    // Create a new thread
    TThread.CreateAnonymousThread(
      procedure
      begin
        f('goroutine');
      end
    ).Start;
  end;

  // Anonymous function
  begin
    // Create another thread for the anonymous function
    TThread.CreateAnonymousThread(
      procedure
      begin
        writeln('going');
      end
    ).Start;
  end;
  
  // Wait for the threads to complete
  sleep(1000);
  writeln('done');
end.

To run the program, save the code in a file named GoroutinesExample.pas and use a Pascal compiler like Free Pascal to compile and run it.

$ fpc GoroutinesExample.pas
$ ./GoroutinesExample
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done

When we run this Pascal program, we see the output of the blocking call first, then the output of the two threads. The thread outputs may be interleaved, as threads are running concurrently.

Next, we’ll look at a complement to goroutines in concurrent programs: channels (though not natively available in Pascal, equivalent synchronization techniques can be explored).