Timeouts in Cilk

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Cilk is possible using a combination of threads and timers.

#include <cilk/cilk.h>
#include <cilk/cilk_api.h>
#include <iostream>
#include <chrono>
#include <thread>
#include <future>

int main() {
    // For our example, suppose we're executing an external
    // call that returns its result after 2s. We'll use a
    // std::future to represent this asynchronous operation.
    auto c1 = std::async(std::launch::async, []() {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        return std::string("result 1");
    });

    // Here's the implementation of a timeout.
    // We'll use std::future_status::timeout to check if
    // the operation completed within the allowed time.
    if (c1.wait_for(std::chrono::seconds(1)) == std::future_status::ready) {
        std::cout << c1.get() << std::endl;
    } else {
        std::cout << "timeout 1" << std::endl;
    }

    // If we allow a longer timeout of 3s, then the operation
    // will succeed and we'll print the result.
    auto c2 = std::async(std::launch::async, []() {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        return std::string("result 2");
    });

    if (c2.wait_for(std::chrono::seconds(3)) == std::future_status::ready) {
        std::cout << c2.get() << std::endl;
    } else {
        std::cout << "timeout 2" << std::endl;
    }

    return 0;
}

Running this program shows the first operation timing out and the second succeeding.

$ g++ -fcilkplus timeouts.cpp -o timeouts
$ ./timeouts
timeout 1
result 2

In this Cilk version, we use std::async to create asynchronous tasks that simulate long-running operations. We then use std::future::wait_for to implement the timeout mechanism. If the future is ready within the specified time, we retrieve and print the result. Otherwise, we print a timeout message.

Note that Cilk doesn’t have built-in channels like Go, so we’ve used C++ futures and promises to achieve similar functionality. The cilk_spawn keyword, which is typically used for parallelism in Cilk, isn’t necessary here as we’re using C++’s standard library for asynchronous operations.

This approach provides a way to implement timeouts in Cilk, although it’s not as elegant as Go’s channel-based solution. The core concept of bounding execution time remains the same.