[Video] Swift as C++ Successor in FoundationDB

Hi everyone,
I'm very happy to be able to share with the forums a talk we did about adoption of Swift / C++ interop in FoundationDB.

This work already was mentioned a little bit during WWDC23, but this is a full deep dive into how the C++ interop was utilized and the problems it aims to solve in the project.

It's a great testament to how far the C++ interop has already gotten, even at its early stages.

I also want to extend a shout out here to @Alex_L, @zoecarver and @etcwilde who were all instrumental to the work being shown in this presentation.

https://www.youtube.com/watch?v=ZQc9-seU-5k

32 Likes

I'm watching this right now, thanks for this details information

1 Like

The section on actor runtime interoperability went by very quickly… can you elaborate on that? If I heard correctly, it sounds like FDB found & utilises some way to have Swift's Structured Concurrency primitives (Task, TaskGroup, etc) actually map to C++ code instead of the native Swift runtime…?

The Swift concurrency runtime has a hook called swift_task_enqueueGlobal_hook which some libraries (like async-algorithms) use for testing; It takes over all enqueues made by the concurrency runtime. In FDB this is exactly what we need, since all tasks must be enqueued on FDB's event loop.

The implementation FDB is simple:

 void sim2_enqueueGlobal_hook_impl(swift::Job* _Nonnull job, void (*_Nonnull)(swift::Job*) __attribute__((swiftcall))) {
 	ISimulator* sim = g_simulator;
 	sim->_swiftEnqueue(job);
 }

// installing the hook:
// swift_task_enqueueGlobal_hook = sim2_enqueueGlobal_hook_impl

void _swiftEnqueue(void* _job) override {
    ASSERT(getCurrentProcess());
    swift::Job* job = (swift::Job*)_job; // Swift runtime type
    ...
    auto t = new PromiseTask(machine, job); // FDB runtime type
 	taskQueue.addReady(priority, t); // FDB event loop
}

and the FDB eventloop gained:

if (t.swiftJob) {
    // swift logic
    swift_job_run(t.swiftJob, ExecutorRef::generic());
} else {
    t.promise.send(Void()); // normal logic
}

and that's pretty much it.

The hook can be used with Swift functions as well, as async-algorithms do -- but really it is only for taking over all scheduling -- and in most cases people should rather use custom executors.

// edit: minor corrections

3 Likes

Pointfreeco also use this for the withMainSerialExecutor test helper function.

There’s also a blog post and video series on it.

1 Like