130 lines
4.7 KiB
C++
130 lines
4.7 KiB
C++
//
|
|
// Copyright (C) 2012 The Android Open Source Project
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#ifndef SHILL_HOOK_TABLE_H_
|
|
#define SHILL_HOOK_TABLE_H_
|
|
|
|
// HookTable provides a facility for starting a set of generic actions and
|
|
// reporting for their completion. For example, on shutdown, each service gets
|
|
// disconnected. A disconnect action may be instantaneous or it may require
|
|
// some time to complete. Users of this facility use the Add() function to
|
|
// provide a closure for starting an action. Users report the completion of an
|
|
// action. When an event occurs, the Run() function is called, which starts
|
|
// each action and sets a timer. Upon completion or timeout, Run() calls a
|
|
// user-supplied callback to notify the caller of the state of actions.
|
|
//
|
|
// Usage example. Add an action to a hook table like this:
|
|
//
|
|
// HookTable hook_table_(&event_dispatcher);
|
|
// Closure start_callback = Bind(&MyService::Disconnect, &my_service);
|
|
// hook_table_.Add("MyService", start_callback);
|
|
//
|
|
// The code that catches an event runs the actions of the hook table like this:
|
|
//
|
|
// ResultCallback done_callback = Bind(Manager::OnDisconnect, &manager);
|
|
// hook_table_.Run(kTimeout, done_callback);
|
|
//
|
|
// When |my_service| has completed its disconnect process,
|
|
// Manager::OnDisconnect() gets called with Error::kSuccess. If |my_service|
|
|
// does not finish its disconnect processing before kTimeout, then it gets
|
|
// called with kOperationTimeout.
|
|
|
|
#include <map>
|
|
#include <string>
|
|
|
|
#include <base/cancelable_callback.h>
|
|
#include <base/macros.h>
|
|
#include <gtest/gtest_prod.h>
|
|
|
|
#include "shill/callbacks.h"
|
|
|
|
namespace shill {
|
|
class EventDispatcher;
|
|
class Error;
|
|
|
|
class HookTable {
|
|
public:
|
|
explicit HookTable(EventDispatcher* event_dispatcher);
|
|
~HookTable();
|
|
|
|
// Adds a closure to the hook table. |name| should be unique; otherwise, a
|
|
// previous closure by the same name will be replaced. |start| will be called
|
|
// when Run() is called.
|
|
void Add(const std::string& name, const base::Closure& start);
|
|
|
|
// Users call this function to report the completion of an action |name|.
|
|
void ActionComplete(const std::string& name);
|
|
|
|
// Removes the action associated with |name| from the hook table. If |name|
|
|
// does not exist, the hook table is unchanged.
|
|
void Remove(const std::string& name);
|
|
|
|
// Runs the actions that have been added to the HookTable via Add(). It
|
|
// starts a timer for completion in |timeout_ms|. If all actions complete
|
|
// successfully within the timeout period, |done| is called with a value of
|
|
// Error::kSuccess. Otherwise, it is called with Error::kOperationTimeout.
|
|
void Run(int timeout_ms, const ResultCallback& done);
|
|
|
|
bool IsEmpty() const { return hook_table_.empty(); }
|
|
|
|
private:
|
|
friend class HookTableTest;
|
|
|
|
// For each action, there is a |start| callback which is stored in this
|
|
// structure.
|
|
struct HookAction {
|
|
explicit HookAction(const base::Closure& start_callback)
|
|
: start_callback(start_callback),
|
|
started(false),
|
|
completed(false) {}
|
|
const base::Closure start_callback;
|
|
bool started;
|
|
bool completed;
|
|
};
|
|
|
|
// Each action is stored in this table. The key is |name| passed to Add().
|
|
typedef std::map<std::string, HookAction> HookTableMap;
|
|
|
|
// Returns true if all started actions have completed; false otherwise. If no
|
|
// actions have started, returns true.
|
|
bool AllActionsComplete() const;
|
|
|
|
// This function runs if all the actions do not complete before the timeout
|
|
// period. It invokes the user-supplied callback to Run() with an error value
|
|
// kOperationTimeout.
|
|
void ActionsTimedOut();
|
|
|
|
// Each action is stored in this table.
|
|
HookTableMap hook_table_;
|
|
|
|
// This is the user-supplied callback to Run().
|
|
ResultCallback done_callback_;
|
|
|
|
// This callback is created in Run() and is queued to the event dispatcher to
|
|
// run after a timeout period. If all the actions complete before the
|
|
// timeout, then this callback is canceled.
|
|
base::CancelableClosure timeout_callback_;
|
|
|
|
// Used for setting a timeout action to run in case all the actions do not
|
|
// complete in time.
|
|
EventDispatcher* const event_dispatcher_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(HookTable);
|
|
};
|
|
|
|
} // namespace shill
|
|
|
|
#endif // SHILL_HOOK_TABLE_H_
|