1// Copyright 2014 The Chromium 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 CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_TRACKER_H_
6#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_TRACKER_H_
7
8#include <map>
9
10#include "base/bind.h"
11#include "base/callback_forward.h"
12#include "base/memory/weak_ptr.h"
13#include "chrome/browser/sync_file_system/drive_backend/callback_tracker_internal.h"
14
15namespace sync_file_system {
16namespace drive_backend {
17
18// A helper class to ensure one-shot callback to be called exactly once.
19//
20// Usage:
21//   class Foo {
22//    private:
23//     CallbackTracker callback_tracker_;
24//   };
25//
26//   void DoSomethingAsync(const SomeCallbackType& callback) {
27//     base::Closure abort_case_handler = base::Bind(callback, ABORT_ERROR);
28//
29//     SomeCallbackType wrapped_callback =
30//         callback_tracker_.Register(
31//             abort_case_handler, callback);
32//
33//     // The body of the operation goes here.
34//   }
35class CallbackTracker {
36 public:
37  typedef std::map<internal::AbortHelper*, base::Closure> AbortClosureByHelper;
38
39  CallbackTracker();
40  ~CallbackTracker();
41
42  // Returns a wrapped callback.
43  // Upon AbortAll() call, CallbackTracker invokes |abort_closure| and voids all
44  // wrapped callbacks returned by Register().
45  // Invocation of the wrapped callback unregisters |callback| from
46  // CallbackTracker.
47  template <typename T>
48  base::Callback<T> Register(const base::Closure& abort_closure,
49                             const base::Callback<T>& callback) {
50    internal::AbortHelper* helper = new internal::AbortHelper(this);
51    helpers_[helper] = abort_closure;
52    return base::Bind(&internal::InvokeAndInvalidateHelper<T>::Run,
53                      helper->AsWeakPtr(), callback);
54  }
55
56  void AbortAll();
57
58 private:
59  friend class internal::AbortHelper;
60
61  scoped_ptr<internal::AbortHelper> PassAbortHelper(
62      internal::AbortHelper* helper);
63
64  AbortClosureByHelper helpers_;  // Owns AbortHelpers.
65
66  DISALLOW_COPY_AND_ASSIGN(CallbackTracker);
67};
68
69}  // namespace drive_backend
70}  // namespace sync_file_system
71
72#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_TRACKER_H_
73