blob: 91426a1aa4684b477fa7740f8943fbb65b4951c7 [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#ifndef SHILL_HOOK_TABLE_H_
6#define SHILL_HOOK_TABLE_H_
7
8// HookTable provides a facility for starting a set of generic actions and
Gary Moraina9fb3252012-05-31 12:05:31 -07009// reporting for their completion. For example, on shutdown, each service gets
Gary Morainf80ef062012-05-16 14:57:04 -070010// disconnected. A disconnect action may be instantaneous or it may require
11// some time to complete. Users of this facility use the Add() function to
Gary Moraina9fb3252012-05-31 12:05:31 -070012// provide a closure for starting an action. Users report the completion of an
13// action. When an event occurs, the Run() function is called, which starts
14// each action and sets a timer. Upon completion or timeout, Run() calls a
15// user-supplied callback to notify the caller of the state of actions.
Gary Morainf80ef062012-05-16 14:57:04 -070016//
17// Usage example. Add an action to a hook table like this:
18//
19// HookTable hook_table_(&event_dispatcher);
20// Closure start_cb = Bind(&MyService::Disconnect, &my_service);
Gary Moraina9fb3252012-05-31 12:05:31 -070021// hook_table_.Add("MyService", start_cb);
Gary Morainf80ef062012-05-16 14:57:04 -070022//
23// The code that catches an event runs the actions of the hook table like this:
24//
25// Callback<void(const Error &)> done_cb =
26// Bind(Manager::OnDisconnect, &manager);
27// hook_table_.Run(kTimeout, done_cb);
28//
29// When |my_service| has completed its disconnect process,
30// Manager::OnDisconnect() gets called with Error::kSuccess. If |my_service|
31// does not finish its disconnect processing before kTimeout, then it gets
32// called with kOperationTimeout.
33
34#include <map>
35#include <string>
36
37#include <base/basictypes.h>
38#include <base/callback.h>
Gary Moraina9fb3252012-05-31 12:05:31 -070039#include <base/cancelable_callback.h>
Gary Morainf80ef062012-05-16 14:57:04 -070040#include <gtest/gtest_prod.h>
41
42namespace shill {
Gary Morainf80ef062012-05-16 14:57:04 -070043class EventDispatcher;
Gary Moraina9fb3252012-05-31 12:05:31 -070044class Error;
Gary Morainf80ef062012-05-16 14:57:04 -070045
46class HookTable {
47 public:
48 explicit HookTable(EventDispatcher *event_dispatcher);
Gary Moraina9fb3252012-05-31 12:05:31 -070049 ~HookTable();
Gary Morainf80ef062012-05-16 14:57:04 -070050
51 // Adds a closure to the hook table. |name| should be unique; otherwise, a
Gary Moraina9fb3252012-05-31 12:05:31 -070052 // previous closure by the same name will be replaced. |start| will be called
53 // when Run() is called.
54 void Add(const std::string &name, const base::Closure &start);
Gary Morainf80ef062012-05-16 14:57:04 -070055
Gary Moraina9fb3252012-05-31 12:05:31 -070056 // Users call this function to report the completion of an action |name|.
57 void ActionComplete(const std::string &name);
58
59 // Removes the action associtated with |name| from the hook table. If |name|
60 // does not exist, the hook table is unchanged.
61 void Remove(const std::string &name);
62
63 // Runs the actions that have been added to the HookTable via Add(). It
64 // starts a timer for completion in |timeout_ms|. If all actions complete
65 // succesfully within the timeout period, |done| is called with a value of
66 // Error::kSuccess. Otherwise, it is called with Error::kOperationTimeout.
67 void Run(int timeout_ms,
Gary Morainf80ef062012-05-16 14:57:04 -070068 const base::Callback<void(const Error &)> &done);
69
70 private:
Gary Moraina9fb3252012-05-31 12:05:31 -070071 // For each action, there is a |start| callback which is stored in this
72 // structure.
73 struct HookAction {
74 HookAction(const base::Closure &start_cb)
75 : start(start_cb),
76 started(false),
77 completed(false) {}
Gary Morainf80ef062012-05-16 14:57:04 -070078 const base::Closure start;
Gary Moraina9fb3252012-05-31 12:05:31 -070079 bool started;
80 bool completed;
Gary Morainf80ef062012-05-16 14:57:04 -070081 };
82
83 // Each action is stored in this table. The key is |name| passed to Add().
Gary Moraina9fb3252012-05-31 12:05:31 -070084 typedef std::map<std::string, HookAction> HookTableMap;
Gary Morainf80ef062012-05-16 14:57:04 -070085
Gary Moraina9fb3252012-05-31 12:05:31 -070086 // Returns true if all started actions have completed; false otherwise. If no
87 // actions have started, returns true.
88 bool AllActionsComplete();
89
90 // This function runs if all the actions do not complete before the timeout
91 // period. It invokes the user-supplied callback to Run() with an error value
92 // kOperationTimeout.
93 void ActionsTimedOut();
Gary Morainf80ef062012-05-16 14:57:04 -070094
95 // Each action is stored in this table.
96 HookTableMap hook_table_;
97
Gary Moraina9fb3252012-05-31 12:05:31 -070098 // This is the user-supplied callback to Run().
99 base::Callback<void(const Error &)> done_cb_;
Gary Morainf80ef062012-05-16 14:57:04 -0700100
Gary Moraina9fb3252012-05-31 12:05:31 -0700101 // This callback is creted in Run() and is queued to the event dispatcher to
102 // run after a timeout period. If all the actions complete before the
103 // timeout, then this callback is cancelled.
104 base::CancelableClosure timeout_cb_;
105
106 // Used for setting a timeout action to run in case all the actions do not
107 // complete in time.
108 EventDispatcher *const event_dispatcher_;
Gary Morainf80ef062012-05-16 14:57:04 -0700109
110 DISALLOW_COPY_AND_ASSIGN(HookTable);
111};
112
113} // namespace shill
114
115#endif // SHILL_HOOK_TABLE_H_