Skip to content

CONCEPT Cited by 1 source

Runtime flavor dispatch

Definition

Runtime flavor dispatch is the technique of selecting between multiple implementations of the same interface based on a runtime flag (flavor) set once at app startup, with shared logic in generic templates and version-specific behavior in template specializations.

The canonical shape is a shim that statically links N copies of an underlying library and dispatches each call to exactly one of them based on the flavor enum — see concepts/shim-layer and systems/meta-webrtc-shim.

Why at runtime

Compile-time dispatch (e.g. preprocessor macros or build-variant binaries) would require shipping and managing multiple binaries. For an A/B experiment that must toggle per-user/per-session, the same binary must contain both implementations and pick between them dynamically. That's why runtime dispatch is the default mechanism for patterns/shim-for-dual-stack-ab-testing.

Per-call dispatch (choosing a flavor at each call site individually) is strictly more flexible than whole-binary dispatch (one flavor for the entire process). Meta chose per-call: the same binary can run WebRTC in latest for a Messenger test cohort while keeping legacy for Instagram users who haven't been flipped yet.

The template-specialization shape

Generic templates carry the shared code, which dominates the adapter/converter code volume. Version-specific hooks live in template specializations:

// shared logic — DRY across flavors
template <Flavor F>
class FooAdapter {
    typename FlavorTraits<F>::Foo underlying_;
    void Commonplace() { ... }                     // identical both flavors
    void FlavorSpecific() { SpecializedDoWork<F>(this); }
};

// per-flavor behavior
template<> void SpecializedDoWork<Flavor::Legacy>(FooAdapter*) { ... }
template<> void SpecializedDoWork<Flavor::Latest>(FooAdapter*) { ... }

The global flavor enum is consulted once, at the entry point, and used to select which concrete FooAdapter<F> instance is built.

Bridging the legacy API surface

Legacy call sites target webrtc::*. The shim preserves that API surface via C++ using declarations — the chosen flavor namespace is bulk-imported into webrtc:: at compile time, so existing code works without modification. That sits orthogonal to runtime dispatch: the which-namespace-is-visible-as-webrtc question is compile-time, the which-underlying-object-handles-this-call question is runtime.

Single-flavor builds are supported for migration continuity — some apps still build against a constant flavor, not dual-stack. The same template machinery produces both shapes.

Canonical disclosure

"With the shim layer wrapping both WebRTC versions, the next question was: How do we dispatch to the correct version at runtime? Each adapter and converter needs to instantiate the right underlying object — webrtc_legacy:: or webrtc_latest::, based on a global configuration flag. We addressed this with a template-based helper library. Shared logic (which constitutes a large portion of the adapter code) is written once. Version-specific behavior is expressed through C++ template specializations. This keeps the code DRY while supporting backward compatibility with single-flavor builds during the transition period. A global flavor enum, set early in each app's startup sequence, determines which flavor to activate." (sources/2026-04-09-meta-escaping-the-fork-webrtc-modernization)

Seen in

Last updated · 319 distilled / 1,201 read