blob: bb261ec71313325fe03365865d4e3d2042d51e7b [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);
Ben Chan3fbf8bd2014-06-07 20:49:52 -070020// Closure start_callback = Bind(&MyService::Disconnect, &my_service);
21// hook_table_.Add("MyService", start_callback);
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//
Ben Chan3fbf8bd2014-06-07 20:49:52 -070025// ResultCallback done_callback = Bind(Manager::OnDisconnect, &manager);
26// hook_table_.Run(kTimeout, done_callback);
Gary Morainf80ef062012-05-16 14:57:04 -070027//
28// When |my_service| has completed its disconnect process,
29// Manager::OnDisconnect() gets called with Error::kSuccess. If |my_service|
30// does not finish its disconnect processing before kTimeout, then it gets
31// called with kOperationTimeout.
32
33#include <map>
34#include <string>
35
36#include <base/basictypes.h>
Gary Moraina9fb3252012-05-31 12:05:31 -070037#include <base/cancelable_callback.h>
Gary Morainf80ef062012-05-16 14:57:04 -070038#include <gtest/gtest_prod.h>
39
Ben Chan3fbf8bd2014-06-07 20:49:52 -070040#include "shill/callbacks.h"
41
Gary Morainf80ef062012-05-16 14:57:04 -070042namespace 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
Ben Chan3fbf8bd2014-06-07 20:49:52 -070059 // Removes the action associated with |name| from the hook table. If |name|
Gary Moraina9fb3252012-05-31 12:05:31 -070060 // 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
Ben Chan3fbf8bd2014-06-07 20:49:52 -070065 // successfully within the timeout period, |done| is called with a value of
Gary Moraina9fb3252012-05-31 12:05:31 -070066 // Error::kSuccess. Otherwise, it is called with Error::kOperationTimeout.
Ben Chan3fbf8bd2014-06-07 20:49:52 -070067 void Run(int timeout_ms, const ResultCallback &done);
Gary Morainf80ef062012-05-16 14:57:04 -070068
Darin Petkov3ec55342012-09-28 14:04:44 +020069 bool IsEmpty() const { return hook_table_.empty(); }
70
Gary Morainf80ef062012-05-16 14:57:04 -070071 private:
Darin Petkov3ec55342012-09-28 14:04:44 +020072 friend class HookTableTest;
73
Gary Moraina9fb3252012-05-31 12:05:31 -070074 // For each action, there is a |start| callback which is stored in this
75 // structure.
76 struct HookAction {
Ben Chan3fbf8bd2014-06-07 20:49:52 -070077 explicit HookAction(const base::Closure &start_callback)
78 : start_callback(start_callback),
Gary Moraina9fb3252012-05-31 12:05:31 -070079 started(false),
80 completed(false) {}
Ben Chan3fbf8bd2014-06-07 20:49:52 -070081 const base::Closure start_callback;
Gary Moraina9fb3252012-05-31 12:05:31 -070082 bool started;
83 bool completed;
Gary Morainf80ef062012-05-16 14:57:04 -070084 };
85
86 // Each action is stored in this table. The key is |name| passed to Add().
Gary Moraina9fb3252012-05-31 12:05:31 -070087 typedef std::map<std::string, HookAction> HookTableMap;
Gary Morainf80ef062012-05-16 14:57:04 -070088
Gary Moraina9fb3252012-05-31 12:05:31 -070089 // Returns true if all started actions have completed; false otherwise. If no
90 // actions have started, returns true.
Ben Chan3fbf8bd2014-06-07 20:49:52 -070091 bool AllActionsComplete() const;
Gary Moraina9fb3252012-05-31 12:05:31 -070092
93 // This function runs if all the actions do not complete before the timeout
94 // period. It invokes the user-supplied callback to Run() with an error value
95 // kOperationTimeout.
96 void ActionsTimedOut();
Gary Morainf80ef062012-05-16 14:57:04 -070097
98 // Each action is stored in this table.
99 HookTableMap hook_table_;
100
Gary Moraina9fb3252012-05-31 12:05:31 -0700101 // This is the user-supplied callback to Run().
Ben Chan3fbf8bd2014-06-07 20:49:52 -0700102 ResultCallback done_callback_;
Gary Morainf80ef062012-05-16 14:57:04 -0700103
Ben Chan3fbf8bd2014-06-07 20:49:52 -0700104 // This callback is created in Run() and is queued to the event dispatcher to
Gary Moraina9fb3252012-05-31 12:05:31 -0700105 // run after a timeout period. If all the actions complete before the
Alex Vakulenko8a532292014-06-16 17:18:44 -0700106 // timeout, then this callback is canceled.
Ben Chan3fbf8bd2014-06-07 20:49:52 -0700107 base::CancelableClosure timeout_callback_;
Gary Moraina9fb3252012-05-31 12:05:31 -0700108
109 // Used for setting a timeout action to run in case all the actions do not
110 // complete in time.
111 EventDispatcher *const event_dispatcher_;
Gary Morainf80ef062012-05-16 14:57:04 -0700112
113 DISALLOW_COPY_AND_ASSIGN(HookTable);
114};
115
116} // namespace shill
117
118#endif // SHILL_HOOK_TABLE_H_