blob: d53f78c45da73a360c41554ed7b8cbc1ee861b9d [file] [log] [blame]
Gary Morainf80ef062012-05-16 14:57:04 -07001// Copyright (c) 2012 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#include "shill/hook_table.h"
6
7#include <string>
8
9#include <base/bind.h>
10#include <base/callback.h>
Gary Moraina9fb3252012-05-31 12:05:31 -070011#include <base/cancelable_callback.h>
Gary Morainf80ef062012-05-16 14:57:04 -070012
13#include "shill/error.h"
14#include "shill/event_dispatcher.h"
15
16using base::Bind;
Gary Moraina9fb3252012-05-31 12:05:31 -070017using base::Callback;
Gary Morainf80ef062012-05-16 14:57:04 -070018using base::Closure;
19using base::ConstRef;
20using base::Unretained;
21using std::string;
22
23namespace shill {
24
Gary Morainf80ef062012-05-16 14:57:04 -070025HookTable::HookTable(EventDispatcher *event_dispatcher)
Gary Moraina9fb3252012-05-31 12:05:31 -070026 : event_dispatcher_(event_dispatcher) {}
Gary Morainf80ef062012-05-16 14:57:04 -070027
Gary Moraina9fb3252012-05-31 12:05:31 -070028void HookTable::Add(const string &name, const base::Closure &start) {
29 Remove(name);
Gary Morainf80ef062012-05-16 14:57:04 -070030 hook_table_.insert(
Gary Moraina9fb3252012-05-31 12:05:31 -070031 HookTableMap::value_type(name, HookAction(start)));
Gary Morainf80ef062012-05-16 14:57:04 -070032}
33
Gary Moraina9fb3252012-05-31 12:05:31 -070034HookTable::~HookTable() {
35 timeout_cb_.Cancel();
36}
37
38void HookTable::Remove(const std::string &name) {
39 HookTableMap::iterator it = hook_table_.find(name);
40 if (it != hook_table_.end()) {
41 hook_table_.erase(it);
Gary Morainf80ef062012-05-16 14:57:04 -070042 }
Gary Morainf80ef062012-05-16 14:57:04 -070043}
44
Gary Moraina9fb3252012-05-31 12:05:31 -070045void HookTable::ActionComplete(const std::string &name) {
46 HookTableMap::iterator it = hook_table_.find(name);
47 if (it != hook_table_.end()) {
48 HookAction *action = &it->second;
49 if (action->started && !action->completed) {
50 action->completed = true;
Gary Morainf80ef062012-05-16 14:57:04 -070051 }
52 }
Gary Moraina9fb3252012-05-31 12:05:31 -070053 if (AllActionsComplete() && !done_cb_.is_null()) {
54 timeout_cb_.Cancel();
55 done_cb_.Run(Error(Error::kSuccess));
56 done_cb_.Reset();
57 }
58}
Gary Morainf80ef062012-05-16 14:57:04 -070059
Gary Moraina9fb3252012-05-31 12:05:31 -070060void HookTable::Run(int timeout_ms,
61 const Callback<void(const Error &)> &done) {
62 if (hook_table_.empty()) {
Gary Morainf80ef062012-05-16 14:57:04 -070063 done.Run(Error(Error::kSuccess));
64 return;
65 }
Gary Moraina9fb3252012-05-31 12:05:31 -070066 done_cb_ = done;
67 timeout_cb_.Reset(Bind(&HookTable::ActionsTimedOut, Unretained(this)));
68 event_dispatcher_->PostDelayedTask(timeout_cb_.callback(), timeout_ms);
Gary Morainf80ef062012-05-16 14:57:04 -070069
Gary Moraina9fb3252012-05-31 12:05:31 -070070 // Mark all actions as having started before we execute any actions.
71 // Otherwise, if the first action completes inline, its call to
72 // ActionComplete() will cause the |done| callback to be invoked before the
73 // rest of the actions get started.
74 for (HookTableMap::iterator it = hook_table_.begin();
75 it != hook_table_.end(); ++it) {
76 HookAction *action = &it->second;
77 action->started = true;
78 action->completed = false;
Gary Morainf80ef062012-05-16 14:57:04 -070079 }
Gary Moraina9fb3252012-05-31 12:05:31 -070080 // Now start the actions.
81 for (HookTableMap::iterator it = hook_table_.begin();
82 it != hook_table_.end(); ++it) {
83 it->second.start.Run();
84 }
85}
Gary Morainf80ef062012-05-16 14:57:04 -070086
Gary Moraina9fb3252012-05-31 12:05:31 -070087bool HookTable::AllActionsComplete() {
88 for (HookTableMap::const_iterator it = hook_table_.begin();
89 it != hook_table_.end(); ++it) {
90 const HookAction &action = it->second;
91 if (action.started && !action.completed) {
92 return false;
93 }
94 }
95 return true;
96}
97
98void HookTable::ActionsTimedOut() {
99 done_cb_.Run(Error(Error::kOperationTimeout));
Gary Morainf80ef062012-05-16 14:57:04 -0700100}
101
102} // namespace shill