tree: 370f91ddf03fc418fd221348b11e6f008b0721f5 [search]
  1. src/
  2. BUILD.gn
  3. README.md
src/power/lib/election/README.md

election

election provides Election<K, V>, which arbitrates a single setting across multiple voters and elects the winning value (the result).

It is FIDL-agnostic and shared by components that combine requests from several clients into one hardware setting, such as charger drivers (arbitrating Controller, Debug, and Vreg votes) and battery-manager (arbitrating votes from charge governors).

Linux charger drivers call the same object a votable (Qualcomm pmic-voter) or an election (Google gvotable).

Concepts

  • Voter (K): identifies who cast a vote, such as an enum of client types or a governor's name (String). Each voter has at most one vote.
  • Vote (V): the value a voter requests. A voter casts a vote with cast and withdraws it with withdraw (set_vote takes Some or None).
  • Result: the winning vote across all active voters, or None if no votes are active. Callers apply their own default when it is None.
  • Comparator: ranks active votes; the vote ranked Ordering::Greater wins.
    • Election::min(): the lowest vote wins (for example, current or voltage ceilings, where every voter's limit must be honored).
    • Election::max(): the highest vote wins.
    • Election::new(cmp): a custom precedence, for value types without Ord (such as FIDL enums).
  • Override voter (optional): with_override_voter(k) designates a voter whose active vote wins over all other voters regardless of the comparator (for example, a debug override).

Usage

use election::Election;

let fcc_ua = Election::<&str, u32>::min().with_override_voter("debug");

fcc_ua.cast("msc", 2_000_000);
fcc_ua.cast("thermal", 1_000_000);
assert_eq!(fcc_ua.result(), Some(1_000_000));

// The override voter wins even under `min()`.
fcc_ua.cast("debug", 3_000_000);
assert_eq!(fcc_ua.result(), Some(3_000_000));

// Withdrawing a vote restores the election across the remaining voters.
fcc_ua.withdraw("debug");
assert_eq!(fcc_ua.result(), Some(1_000_000));

Applying single-field changes

try_cast and try_withdraw (or try_set_vote with Some or None) update a voter‘s vote and, only if the result changes, run an async apply closure (for example, a register write). If apply fails, or the returned future is dropped before apply completes, the voter’s previous vote is restored so that the election matches what was last applied and the request can be retried:

let changed = fcc_ua
    .try_cast("msc", 1_500_000, |result| async move {
        program_fcc(result.unwrap_or(DEFAULT_FCC_UA)).await
    })
    .await?;

They return Ok(true) if the result changed and was applied, or Ok(false) if the result was unchanged (and apply did not run). A failed or cancelled apply may still have partially taken effect.

Multi-field transactions

When one request updates several Elections that must be applied together (for example, a single driver call carrying every changed field), use the lower-level APIs and roll back on failure:

  1. Snapshot each voter's previous votes with vote (or keep the value returned by set_vote).
  2. Cast or withdraw the new votes with set_vote.
  3. Read each result and apply them together.
  4. On failure, restore the previous votes with set_vote.

Election holds its internal lock only for short map operations, never across .await points, so callers must serialize multi-field transactions themselves (for example, behind an async mutex).

Inspect

record_inspect(parent, name) records a node for the election:

<name>:
  result: <winning vote, omitted when no votes are active>
  overridden: <whether the override voter has an active vote>
  votes:
    <voter>: <vote>

Values implement InspectValue (provided for u32, u64, i64, and bool). For value types defined in other crates, which cannot implement InspectValue, use record_inspect_with and pass a closure that records each value:

mode.record_inspect_with(node, "operating_mode", |mode, node, key| {
    node.record_string(key, format!("{mode:?}"));
});

Voter keys must implement AsRef<str> to be recorded.

Testing

fx test election-tests