-
chevron_right
Tobias Bernard: GNOME STF 2024 Project Report
news.movim.eu / PlanetGnome • 11 April
-
chevron_right
Sam Thursfield: Status update, 11/04/2025
news.movim.eu / PlanetGnome • 11 April
-
chevron_right
Felipe Borges: Fedora 42 GNOME 48 Test Week from April 8 to 15
news.movim.eu / PlanetGnome • 10 April
-
chevron_right
This Week in GNOME: #193 Image Loading
news.movim.eu / PlanetGnome • 28 March
-
chevron_right
Christian Hergert: Fiber cancellation in libdex
news.movim.eu / PlanetGnome • 27 March • 2 minutes
-
chevron_right
GNOME Foundation News: GUADEC 2025 Registration is Open!
news.movim.eu / PlanetGnome • 27 March
-
chevron_right
Robert Roth: GNOME Calculator updates
news.movim.eu / PlanetGnome • 27 March
-
chevron_right
Georges Basile Stavracas Neto: A Sysprof enhancement
news.movim.eu / PlanetGnome • 26 March
-
chevron_right
Michael Meeks: 2025-03-26 Wednesday
news.movim.eu / PlanetGnome • 26 March
With GNOME 48 I released libdex 0.10 on the march towards a 1.0. One of the major improved features there was around fiber cancellation.
I’m not going to go into detail about the differences between threads and fibers as wikipedia or your local CS department can probably help you there. But what I will say is that combining
__attribute__((cleanup))
(e.g.
g_autoptr()
) with futures and fibers makes such a nicer experience when writing C.
Thread cancellation is a rather non-portable part of the threading stack across platforms. Some POSIX platforms support it, some don’t. Having safe places to cancel can be a real challenge even if you are depending on a threading implementation that can do it.
With fibers, we have a natural cancellation point due to the cooperative nature of scheduling. All (well behaved) fibers are either making progress or awaiting completion of a future. We use the natural
await()
points to implement cancellation. If everything that was awaiting the future of the fiber has been cancelled, then the fiber can naturally cancel too. The next time it awaits that will just happen and natural exit paths will occur.
When you don’t want cancellation to propagate, you still use
dex_future_disown()
like always (as the fiber itself is a future).
Just to give a quick example of how fibers and futures makes writing C code nicer, here is an excerpt from libfoundry that asynchronously implements the necessary phases to build/run your project with a specific tool, possibly on a non-local system. In the GNOME Builder IDE, this is a series of async callbacks that is extremely difficult to read/debug. But with Foundry using libdex, it’s just a few lines of code and every bit as non-blocking.
From foundry-run-manager.c .
g_autoptr(FoundryDeployStrategy) deploy_strategy = NULL; g_autoptr(FoundryBuildProgress) progress = NULL; g_autoptr(GSubprocess) subprocess = NULL; GError *error = NULL; if (!(deploy_strategy = dex_await_object (foundry_deploy_strategy_new (state->pipeline), &error)) || !dex_await (foundry_deploy_strategy_deploy (deploy_strategy, state->build_pty_fd, state->cancellable), &error) || !dex_await (foundry_deploy_strategy_prepare (deploy_strategy, state->launcher, state->pipeline, state->build_pty_fd, state->cancellable), &error) || !dex_await (foundry_run_tool_prepare (state->run_tool, state->pipeline, state->command, state->launcher, state->run_pty_fd), &error) || !(subprocess = foundry_process_launcher_spawn (state->launcher, &error))) return dex_future_new_for_error (error);
At each
dex_await*()
function call the fiber is suspended and we return to the main loop for additional processing.
In a better world we’d be able to do these without fibers and instead do stackless coroutines. But maybe with a little compiler help we can have that too.
- cloud_queue