settings/message/
action_fuse.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use fuchsia_async as fasync;
use futures::lock::Mutex;
use std::rc::Rc;

/// Closure definition for an action that can be triggered by ActionFuse.
pub type TriggeredAction = Box<dyn FnOnce()>;
/// The reference-counted handle to an ActionFuse. When all references go out of
/// scope, the action will be triggered (if not defused).
pub type ActionFuseHandle = Rc<Mutex<ActionFuse>>;

/// ActionFuse is a wrapper around a triggered action (a closure with no
/// arguments and no return value). This action is invoked once the fuse goes
/// out of scope (via the Drop trait). An ActionFuse can be defused, preventing
/// the action from automatically invoking when going out of scope.
pub struct ActionFuse {
    /// An optional action that will be invoked when the ActionFuse goes out of
    /// scope.
    actions: Option<TriggeredAction>,
}

impl ActionFuse {
    /// Returns an ActionFuse reference with the given TriggerAction.
    pub(crate) fn create(action: TriggeredAction) -> ActionFuseHandle {
        Rc::new(Mutex::new(ActionFuse { actions: Some(action) }))
    }

    /// Suppresses the action from automatically executing.
    pub(crate) fn defuse(handle: ActionFuseHandle) {
        fasync::Task::local(async move {
            let mut fuse = handle.lock().await;
            fuse.actions = None;
        })
        .detach();
    }
}

impl Drop for ActionFuse {
    fn drop(&mut self) {
        if let Some(action) = self.actions.take() {
            (action)();
        }
    }
}