Commit 759ba8a4 authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Docs] Update synchronous-runloop.md to differentiate states and events

Waiting for a state and waiting for an event are subtly different: for
an event, the waiter *must* be constructed before the event is fired
(or else will spin forever), whereas for a state, a waiter may be
constructed at any point (because the state can be queried).

Update the docs with this differentiation and an example.

Bug: None
Change-Id: Ice984ee861df46d9010986e72779639e6c19e400
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2151470
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#759698}
parent 38532dbb
...@@ -113,7 +113,7 @@ about observing any intermediate states too: ...@@ -113,7 +113,7 @@ about observing any intermediate states too:
} }
// GizmoObserver: // GizmoObserver:
void OnThingDone(Gizmo* observed_gismo) { void OnThingDone(Gizmo* observed_gizmo) {
run_loop_.Quit(); run_loop_.Quit();
} }
...@@ -126,9 +126,49 @@ about observing any intermediate states too: ...@@ -126,9 +126,49 @@ about observing any intermediate states too:
waiter.Wait(); waiter.Wait();
``` ```
## Events vs States
It's important to differentiate between waiting on an *event* (such as a
notification or callback being fired) vs waiting for a *state* (such as a
property on a given object).
When waiting for events, it is crucial that the observer is constructed in time
to see the event (see also [waiting to late](#starting-waiting-too-late)).
States, on the other hand, can be queried beforehand in the body of a
Wait()-style function.
The following is an example of a Waiter helper class that waits for a state, as
opposed to an event:
```c++
class GizmoReadyWaiter : public GizmoObserver {
public:
GizmoReadyObserver(Gizmo* gizmo)
: gizmo_(gizmo) {}
~GizmoReadyObserver() override = default;
void WaitForGizmoReady() {
if (!gizmo_->ready()) {
gizmo_observer_.Add(gizmo_);
run_loop_.Run();
}
}
// GizmoObserver:
void OnGizmoReady(Gizmo* observed_gizmo) {
run_loop_.Quit();
}
private:
RunLoop run_loop_;
Gizmo* gizmo_;
ScopedObserver<Gizmo, GizmoObserver> gizmo_observer_{this};
};
```
## Sharp edges ## Sharp edges
### Starting waiting too late ### Starting to wait for an event too late
A common mis-use of this pattern is like so: A common mis-use of this pattern is like so:
...@@ -184,6 +224,9 @@ with the test code being: ...@@ -184,6 +224,9 @@ with the test code being:
NiceFriendlyDoThingAndWait(gizmo); NiceFriendlyDoThingAndWait(gizmo);
``` ```
Note that this is not an issue when waiting on a *state*, since the observer can
query to see if that state is already the current state.
### Guessing RunLoop cycles ### Guessing RunLoop cycles
Sometimes, there's no easy way to observe completion of an event. In that case, Sometimes, there's no easy way to observe completion of an event. In that case,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment