Directories in Cilk

Here’s the translation of the Go code to Cilk, with explanations in Markdown format suitable for Hugo:

#include <cilk/cilk.h>
#include <iostream>
#include <string>
#include <vector>
#include <filesystem>
#include <fstream>

namespace fs = std::filesystem;

void check(const std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
    std::exit(1);
}

void createEmptyFile(const std::string& name) {
    std::ofstream file(name);
    if (!file) {
        check(std::runtime_error("Failed to create file: " + name));
    }
}

void visit(const fs::path& path, const fs::directory_entry& entry) {
    std::cout << "  " << path.string() << " " << fs::is_directory(entry) << std::endl;
}

int main() {
    try {
        // Create a new sub-directory in the current working directory.
        fs::create_directory("subdir");

        // When creating temporary directories, it's good practice to remove them after use.
        // We'll use a try-catch block to ensure cleanup.
        try {
            createEmptyFile("subdir/file1");

            // We can create a hierarchy of directories, including parents.
            fs::create_directories("subdir/parent/child");

            createEmptyFile("subdir/parent/file2");
            createEmptyFile("subdir/parent/file3");
            createEmptyFile("subdir/parent/child/file4");

            // List directory contents
            std::cout << "Listing subdir/parent" << std::endl;
            for (const auto& entry : fs::directory_iterator("subdir/parent")) {
                std::cout << "  " << entry.path().filename().string() << " " << entry.is_directory() << std::endl;
            }

            // Change the current working directory
            fs::current_path("subdir/parent/child");

            // Now we'll see the contents of subdir/parent/child when listing the current directory.
            std::cout << "Listing subdir/parent/child" << std::endl;
            for (const auto& entry : fs::directory_iterator(".")) {
                std::cout << "  " << entry.path().filename().string() << " " << entry.is_directory() << std::endl;
            }

            // Change back to where we started
            fs::current_path("../../..");

            // We can also visit a directory recursively, including all its sub-directories.
            std::cout << "Visiting subdir" << std::endl;
            for (const auto& entry : fs::recursive_directory_iterator("subdir")) {
                visit(entry.path(), entry);
            }
        }
        catch (...) {
            // Ensure cleanup even if an exception occurs
            fs::remove_all("subdir");
            throw;
        }

        // Clean up
        fs::remove_all("subdir");
    }
    catch (const std::exception& e) {
        check(e);
    }

    return 0;
}

This Cilk program demonstrates working with directories in the file system. Here’s a breakdown of the functionality:

  1. We use the <filesystem> library, which provides similar functionality to Go’s file and directory operations.

  2. The createEmptyFile function creates an empty file with the given name.

  3. We create a directory structure using fs::create_directory and fs::create_directories.

  4. We list directory contents using fs::directory_iterator.

  5. We change the current working directory using fs::current_path.

  6. We recursively visit all files and directories using fs::recursive_directory_iterator.

  7. We use a try-catch block to ensure cleanup of the created directory structure, even if an exception occurs.

To compile and run this program:

$ g++ -fcilkplus -std=c++17 directories.cpp -o directories
$ ./directories

This will output the directory structure and file information similar to the Go example.

Note that Cilk extends C++ with parallel programming constructs, but in this example, we’re not using any parallel features. The filesystem operations are performed sequentially.