Vala async methods and GLib MainContext thread-affinity under concurrent requests
0 reputation · 20 Jan 2020, 20:43 UTC
0 reputation · 20 Jan 2020, 20:43 UTC
Determine whether a Vala async method resumes on the same thread-default GLib MainContext that started the call when several requests run concurrently, or whether resumption can move to another thread and create latency that appears only under load.
Vala async methods compile to state machines driven by GLib main-loop primitives. Vala specifies no language-level memory model or concurrency contract, and it does not guarantee same-thread resumption. Resumption is typically posted to the caller's thread-default context, but the exact context and thread depend on the installed Vala compiler and GLib release.
Does Vala guarantee that async resumption runs on the thread-default MainContext of the calling thread? Can concurrent requests cause resumption to be scheduled on a different GLib MainContext or thread, and what controls that choice? Which Vala and GLib versions document or change this thread-affinity behavior?
35775 reputation · 21 Jan 2020, 02:59 UTC
Vala does not guarantee that an async method resumes on the same thread-default GLib.MainContext that started the call. In practice, continuations are dispatched through GLib main-loop primitives and usually run in the thread that owns and iterates the thread-default context captured for the call. Concurrent requests alone do not move resumption to another thread; the break comes from missing or misused context plumbing.
Confirmed: Vala async methods compile to callback-driven state machines. The language defines no memory model or thread-affinity contract. The normal mechanism is the thread-default MainContext: if a worker pushes a context and runs its loop, continuations for calls made there are dispatched to that context and execute when its loop iterates.
Likely under load: Latency appears because completions are posted to a shared, busy, or blocked MainContext, so resumption waits behind unrelated events. If a request thread does not push its own context, work falls back to the global default and competes with other sources. Movement to a different thread typically requires explicit g_main_context_invoke, a GTask targeting another context, or a third-party library with its own scheduler or thread pool.
MainContext for the entire request.g_main_context_invoke or GTask with another context or thread.MainContext and MainLoop.Confirm the toolchain before assuming version behavior:
valac --version
pkg-config --modversion glib-2.0 gio-2.0
Inspect the generated C for the async call to see which scheduling or context API is used. For a minimal repro, each worker thread should create a MainContext/MainLoop, push it as thread-default, start an async method that yields on a real GIO operation, and record the thread-default context plus a thread id at call start and after resumption. Run with and without push_thread_default and with many concurrent workers; mismatches identify the affinity break. For load-only latency, instrument queue depth and timestamps around the yield and continuation.
Confirm whether each request thread pushes and iterates its own MainContext for the entire request. If it does not, fix that before tuning anything else.
Exact behavior depends on the installed Vala compiler and GLib/GIO release. Do not rely on remembered version numbers; verify against your toolchain and generated code.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.