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