C++ API

Flock provides a modern C++ API. It offers a more intuitive interface using C++ features like RAII, exceptions, and STL containers.

Important

To use the C++ API when using cmake, link again the flock::cxx-headers target in addition to the appropriate flock::client or flock::server targets.

Prerequisites

The C++ API requires Thallium and a C++17 compatible compiler:

spack install mochi-flock +bedrock
spack install mochi-thallium

Include headers

#include <flock/cxx/server.hpp> // if server API is required
#include <flock/cxx/client.hpp> // if client API is required
#include <flock/cxx/group.hpp>
#include <flock/cxx/group-view.hpp>

Namespaces

All C++ API is in the flock namespace:

using namespace flock;

Provider (server-side)

Here’s a complete example of creating a Flock provider:

/*
 * (C) 2024 The University of Chicago
 *
 * See COPYRIGHT in top-level directory.
 */
#include <thallium.hpp>
#include <flock/cxx/server.hpp>
#include <iostream>

namespace tl = thallium;

int main(int argc, char** argv)
{
    (void)argc;
    (void)argv;

    // Initialize Thallium engine
    tl::engine engine("na+sm", THALLIUM_SERVER_MODE);

    std::cout << "Server running at address: " << engine.self() << std::endl;

    // Initialize group view with self as the only member
    flock::GroupView initial_view;
    uint16_t provider_id = 42;

    // Add self to the group view
    std::string my_address = static_cast<std::string>(engine.self());
    initial_view.members().add(my_address.c_str(), provider_id);

    // Provider configuration (static backend)
    std::string config = R"(
    {
        "group": {
            "type": "static",
            "config": {}
        }
    }
    )";

    // Create Flock provider
    flock::Provider provider(engine, provider_id, config.c_str(), initial_view);

    std::cout << "Flock provider registered with provider_id="
              << provider_id << std::endl;

    // Wait for finalize
    engine.wait_for_finalize();

    return 0;
}

The Provider class uses RAII - it registers on construction and deregisters on destruction.

Client

Here’s a complete example of using the Flock client:

/*
 * (C) 2024 The University of Chicago
 *
 * See COPYRIGHT in top-level directory.
 */
#include <thallium.hpp>
#include <flock/cxx/client.hpp>
#include <flock/cxx/group.hpp>
#include <iostream>
#include <cstdlib>

namespace tl = thallium;

int main(int argc, char** argv)
{
    if(argc != 3) {
        std::cerr << "Usage: " << argv[0]
                  << " <server_address> <provider_id>" << std::endl;
        return -1;
    }

    std::string server_addr_str = argv[1];
    uint16_t provider_id = std::atoi(argv[2]);

    // Initialize Thallium engine
    tl::engine engine("na+sm", THALLIUM_CLIENT_MODE);

    // Initialize Flock client
    flock::Client client(engine);

    // Lookup server address
    tl::endpoint server_endpoint = engine.lookup(server_addr_str);

    // Create group handle
    flock::GroupHandle group = client.makeGroupHandle(
        server_endpoint.get_addr(), provider_id, 0);

    std::cout << "Connected to Flock group" << std::endl;

    // Get group view
    flock::GroupView view = group.view();

    std::cout << "\n=== Group Information ===" << std::endl;
    std::cout << "Group size: " << view.members().count() << " members" << std::endl;
    std::cout << "View digest: " << view.digest() << std::endl;

    // Print all members
    std::cout << "\nGroup members:" << std::endl;
    auto members = view.members();
    for(size_t i = 0; i < members.count(); i++) {
        auto member = members[i];
        std::cout << "  [" << i << "] Address: " << member.address << std::endl;
        std::cout << "      Provider ID: " << member.provider_id << std::endl;
    }

    // Print metadata if any
    auto metadata = view.metadata();
    if(metadata.count() > 0) {
        std::cout << "\nMetadata:" << std::endl;
        for(size_t i = 0; i < metadata.count(); i++) {
            auto md = metadata[i];
            std::cout << "  " << md.key << " = " << md.value << std::endl;
        }
    }

    std::cout << "\nFlock C++ client operations completed successfully" << std::endl;

    return 0;
}

The client is automatically finalized when the Client object is destroyed.

Group view operations

The C++ API provides a GroupView class:

Adding members:

flock::GroupView view;
view.members().add("na+sm://12345-0", 42);
view.members().add("na+sm://12345-1", 42);

Adding metadata:

view.metadata().add("service", "my_service");
view.metadata().add("version", "1.0.0");

Accessing members:

auto members = view.members();
size_t count = members.count();

for(size_t i = 0; i < count; i++) {
    auto member = members[i];
    std::cout << "Member " << i << ": "
              << member.address << " (id=" << member.provider_id << ")\n";
}

Accessing metadata:

auto metadata = view.metadata();
for(size_t i = 0; i < metadata.count(); i++) {
    auto md = metadata[i];
    std::cout << md.key << " = " << md.value << "\n";
}