Goroutines in Fortress


A goroutine is a lightweight thread of execution.

```cpp
#include <iostream>
#include <thread>
#include <chrono>

void f(const std::string &from) {
    for (int i = 0; i < 3; ++i) {
        std::cout << from << " : " << i << std::endl;
    }
}

int main() {
    // Wed call the function in the usual way, running it synchronously.
    f("direct");

    // To invoke this function in a separate thread in C++.
    std::thread t1(f, "goroutine");

    // You can also start a thread for an anonymous function call.
    std::thread t2([](const std::string &msg) {
        std::cout << msg << std::endl;
    }, "going");

    // Wait for the threads to finish.
    t1.join();
    t2.join();

    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "done" << std::endl;

    return 0;
}

Explanation

When we call f("direct"), it runs synchronously, meaning the main thread will wait for it to complete before moving on.

To run f in a separate thread, we use std::thread t1(f, "goroutine");. This starts a new thread executing the function f concurrently with the main thread.

You can also start a thread to execute an anonymous function. In this case, it prints “going”.

To ensure that the main thread waits for the other threads to complete, we use t1.join() and t2.join().

Finally, we use std::this_thread::sleep_for(std::chrono::seconds(1)); to make the main thread sleep for a second, ensuring that our threads have enough time to complete before the program exits.

When we run this program, we see the output of the blocking call f("direct") first, followed by the output of the two threads. The thread outputs may be interleaved because they run concurrently.

$ ./a.out
direct : 0
direct : 1
direct : 2
goroutine : 0
going
goroutine : 1
goroutine : 2
done

This demonstrates how threads in C++ can be used to achieve concurrent execution.