diff options
author | Samuel Holland <samuel@sholland.org> | 2018-01-09 10:03:06 -0600 |
---|---|---|
committer | Samuel Holland <samuel@sholland.org> | 2018-01-09 10:03:29 -0600 |
commit | 933a68558525ae634c8f78113f9ce02adf7146de (patch) | |
tree | 2e63762944476269ddf21bdffc71f27d40cd87b3 /app/src/main/java/com/wireguard/android/model/TunnelManager.java | |
parent | daacc06a0dcf4e8de371b9e177627ecd82e0ba17 (diff) |
model: Chain completions to avoid race conditions
Otherwise getConfigAsync().thenCompose(x -> setState()) would be unsafe.
This reverts commit a6595a273afd50524cc66765c6bfbdcc34cb12e4.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'app/src/main/java/com/wireguard/android/model/TunnelManager.java')
-rw-r--r-- | app/src/main/java/com/wireguard/android/model/TunnelManager.java | 32 |
1 files changed, 12 insertions, 20 deletions
diff --git a/app/src/main/java/com/wireguard/android/model/TunnelManager.java b/app/src/main/java/com/wireguard/android/model/TunnelManager.java index 1916ab74..4c053e9a 100644 --- a/app/src/main/java/com/wireguard/android/model/TunnelManager.java +++ b/app/src/main/java/com/wireguard/android/model/TunnelManager.java @@ -110,24 +110,18 @@ public final class TunnelManager extends BaseObservable { } CompletionStage<Config> getTunnelConfig(final Tunnel tunnel) { - final CompletionStage<Config> completion = - asyncWorker.supplyAsync(() -> configStore.load(tunnel.getName())); - completion.thenAccept(tunnel::onConfigChanged); - return completion; + return asyncWorker.supplyAsync(() -> configStore.load(tunnel.getName())) + .thenApply(tunnel::onConfigChanged); } CompletionStage<State> getTunnelState(final Tunnel tunnel) { - final CompletionStage<State> completion = - asyncWorker.supplyAsync(() -> backend.getState(tunnel)); - completion.thenAccept(tunnel::onStateChanged); - return completion; + return asyncWorker.supplyAsync(() -> backend.getState(tunnel)) + .thenApply(tunnel::onStateChanged); } CompletionStage<Statistics> getTunnelStatistics(final Tunnel tunnel) { - final CompletionStage<Statistics> completion = - asyncWorker.supplyAsync(() -> backend.getStatistics(tunnel)); - completion.thenAccept(tunnel::onStatisticsChanged); - return completion; + return asyncWorker.supplyAsync(() -> backend.getStatistics(tunnel)) + .thenApply(tunnel::onStatisticsChanged); } public ObservableKeyedList<String, Tunnel> getTunnels() { @@ -227,23 +221,21 @@ public final class TunnelManager extends BaseObservable { } CompletionStage<Config> setTunnelConfig(final Tunnel tunnel, final Config config) { - final CompletionStage<Config> completion = asyncWorker.supplyAsync(() -> { + return asyncWorker.supplyAsync(() -> { final Config appliedConfig = backend.applyConfig(tunnel, config); return configStore.save(tunnel.getName(), appliedConfig); - }); - completion.thenAccept(tunnel::onConfigChanged); - return completion; + }).thenApply(tunnel::onConfigChanged); } CompletionStage<State> setTunnelState(final Tunnel tunnel, final State state) { - final CompletionStage<State> completion = - asyncWorker.supplyAsync(() -> backend.setState(tunnel, state)); - completion.whenComplete((newState, e) -> { + // Ensure the configuration is loaded before trying to use it. + return tunnel.getConfigAsync().thenCompose(x -> + asyncWorker.supplyAsync(() -> backend.setState(tunnel, state)) + ).whenComplete((newState, e) -> { // Ensure onStateChanged is always called (failure or not), and with the correct state. tunnel.onStateChanged(e == null ? newState : tunnel.getState()); if (e == null && newState == State.UP) setLastUsedTunnel(tunnel); }); - return completion; } } |