146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// found in the LICENSE file.
446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_TRACKER_H_
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_TRACKER_H_
746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include <map>
946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/bind.h"
1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/callback_forward.h"
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/memory/weak_ptr.h"
1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/callback_tracker_internal.h"
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace sync_file_system {
1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace drive_backend {
1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// A helper class to ensure one-shot callback to be called exactly once.
1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Usage:
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//   class Foo {
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//    private:
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//     CallbackTracker callback_tracker_;
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//   };
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//   void DoSomethingAsync(const SomeCallbackType& callback) {
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//     base::Closure abort_case_handler = base::Bind(callback, ABORT_ERROR);
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//     SomeCallbackType wrapped_callback =
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//         callback_tracker_.Register(
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//             abort_case_handler, callback);
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//     // The body of the operation goes here.
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//   }
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class CallbackTracker {
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  typedef std::map<internal::AbortHelper*, base::Closure> AbortClosureByHelper;
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CallbackTracker();
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ~CallbackTracker();
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Returns a wrapped callback.
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Upon AbortAll() call, CallbackTracker invokes |abort_closure| and voids all
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // wrapped callbacks returned by Register().
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Invocation of the wrapped callback unregisters |callback| from
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // CallbackTracker.
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  template <typename T>
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::Callback<T> Register(const base::Closure& abort_closure,
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                             const base::Callback<T>& callback) {
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    internal::AbortHelper* helper = new internal::AbortHelper(this);
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    helpers_[helper] = abort_closure;
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return base::Bind(&internal::InvokeAndInvalidateHelper<T>::Run,
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                      helper->AsWeakPtr(), callback);
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void AbortAll();
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  friend class internal::AbortHelper;
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<internal::AbortHelper> PassAbortHelper(
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      internal::AbortHelper* helper);
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AbortClosureByHelper helpers_;  // Owns AbortHelpers.
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CallbackTracker);
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace drive_backend
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}  // namespace sync_file_system
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_TRACKER_H_
73