1// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIBBRILLO_BRILLO_DBUS_ASYNC_EVENT_SEQUENCER_H_
6#define LIBBRILLO_BRILLO_DBUS_ASYNC_EVENT_SEQUENCER_H_
7
8#include <set>
9#include <string>
10#include <vector>
11
12#include <base/bind.h>
13#include <base/macros.h>
14#include <base/memory/ref_counted.h>
15#include <brillo/brillo_export.h>
16
17namespace brillo {
18
19namespace dbus_utils {
20
21// A helper class for coordinating the multiple async tasks.  A consumer
22// may grab any number of callbacks via Get*Handler() and schedule a list
23// of completion actions to take.  When all handlers obtained via Get*Handler()
24// have been called, the AsyncEventSequencer will call its CompletionActions.
25//
26// Usage:
27//
28// void Init(const base::Callback<void(bool success)> cb) {
29//   scoped_refptr<AsyncEventSequencer> sequencer(
30//       new AsyncEventSequencer());
31//   one_delegate_needing_init_.Init(sequencer->GetHandler(
32//       "my delegate failed to init", false));
33//   dbus_init_delegate_.Init(sequencer->GetExportHandler(
34//       "org.test.Interface", "ExposedMethodName",
35//       "another delegate is flaky", false));
36//   sequencer->OnAllTasksCompletedCall({cb});
37// }
38class BRILLO_EXPORT AsyncEventSequencer
39    : public base::RefCounted<AsyncEventSequencer> {
40 public:
41  using Handler = base::Callback<void(bool success)>;
42  using ExportHandler = base::Callback<void(const std::string& interface_name,
43                                            const std::string& method_name,
44                                            bool success)>;
45  using CompletionAction = base::Callback<void(bool all_succeeded)>;
46  using CompletionTask = base::Callback<void(void)>;
47
48  AsyncEventSequencer();
49
50  // Get a Finished handler callback.  Each callback is "unique" in the sense
51  // that subsequent calls to GetHandler() will create new handlers
52  // which will need to be called before completion actions are run.
53  Handler GetHandler(const std::string& descriptive_message,
54                     bool failure_is_fatal);
55
56  // Like GetHandler except with a signature tailored to
57  // ExportedObject's ExportMethod callback requirements.  Will also assert
58  // that the passed interface/method names from ExportedObject are correct.
59  ExportHandler GetExportHandler(const std::string& interface_name,
60                                 const std::string& method_name,
61                                 const std::string& descriptive_message,
62                                 bool failure_is_fatal);
63
64  // Once all handlers obtained via GetHandler have run,
65  // we'll run each CompletionAction, then discard our references.
66  // No more handlers may be obtained after this call.
67  void OnAllTasksCompletedCall(std::vector<CompletionAction> actions);
68
69  // Wrap a CompletionTask with a function that discards the result.
70  // This CompletionTask retains no references to the AsyncEventSequencer.
71  static CompletionAction WrapCompletionTask(const CompletionTask& task);
72  // Create a default CompletionAction that doesn't do anything when called.
73  static CompletionAction GetDefaultCompletionAction();
74
75 private:
76  // We'll partially bind this function before giving it back via
77  // GetHandler.  Note that the returned callbacks have
78  // references to *this, which gives us the neat property that we'll
79  // destroy *this only when all our callbacks have been destroyed.
80  BRILLO_PRIVATE void HandleFinish(int registration_number,
81                                   const std::string& error_message,
82                                   bool failure_is_fatal,
83                                   bool success);
84  // Similar to HandleFinish.
85  BRILLO_PRIVATE void HandleDBusMethodExported(
86      const Handler& finish_handler,
87      const std::string& expected_interface_name,
88      const std::string& expected_method_name,
89      const std::string& actual_interface_name,
90      const std::string& actual_method_name,
91      bool success);
92  BRILLO_PRIVATE void RetireRegistration(int registration_number);
93  BRILLO_PRIVATE void CheckForFailure(bool failure_is_fatal,
94                                      bool success,
95                                      const std::string& error_message);
96  BRILLO_PRIVATE void PossiblyRunCompletionActions();
97
98  bool started_{false};
99  int registration_counter_{0};
100  std::set<int> outstanding_registrations_;
101  std::vector<CompletionAction> completion_actions_;
102  bool had_failures_{false};
103  // Ref counted objects have private destructors.
104  ~AsyncEventSequencer();
105  friend class base::RefCounted<AsyncEventSequencer>;
106  DISALLOW_COPY_AND_ASSIGN(AsyncEventSequencer);
107};
108
109}  // namespace dbus_utils
110
111}  // namespace brillo
112
113#endif  // LIBBRILLO_BRILLO_DBUS_ASYNC_EVENT_SEQUENCER_H_
114