// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_HELPER_H_ #define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_HELPER_H_ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" #include "base/sequenced_task_runner.h" #include "base/thread_task_runner_handle.h" // TODO(tzik): Merge this file to media/base/bind_to_current_loop.h. namespace sync_file_system { namespace drive_backend { namespace internal { template typename base::enable_if< base::internal::IsMoveOnlyType::value, base::internal::PassedWrapper >::type RebindForward(T& t) { return base::Passed(&t); } template typename base::enable_if< !base::internal::IsMoveOnlyType::value, T&>::type RebindForward(T& t) { return t; } template class CallbackHolder { public: CallbackHolder(const scoped_refptr& task_runner, const tracked_objects::Location& from_here, const base::Callback& callback) : task_runner_(task_runner), from_here_(from_here), callback_(new base::Callback(callback)) { DCHECK(task_runner_.get()); } ~CallbackHolder() { base::Callback* callback = callback_.release(); if (!task_runner_->DeleteSoon(from_here_, callback)) delete callback; } base::SequencedTaskRunner* task_runner() const { return task_runner_.get(); } const tracked_objects::Location& from_here() const { return from_here_; } const base::Callback& callback() const { return *callback_; } private: scoped_refptr task_runner_; const tracked_objects::Location from_here_; scoped_ptr > callback_; DISALLOW_COPY_AND_ASSIGN(CallbackHolder); }; template struct RelayToTaskRunnerHelper; template struct RelayToTaskRunnerHelper { static void Run(CallbackHolder* holder, Args... args) { holder->task_runner()->PostTask( holder->from_here(), base::Bind(holder->callback(), RebindForward(args)...)); } }; } // namespace internal template base::Callback RelayCallbackToTaskRunner( const scoped_refptr& task_runner, const tracked_objects::Location& from_here, const base::Callback& callback) { DCHECK(task_runner->RunsTasksOnCurrentThread()); if (callback.is_null()) return base::Callback(); return base::Bind(&internal::RelayToTaskRunnerHelper::Run, base::Owned(new internal::CallbackHolder( task_runner, from_here, callback))); } template base::Callback RelayCallbackToCurrentThread( const tracked_objects::Location& from_here, const base::Callback& callback) { return RelayCallbackToTaskRunner( base::ThreadTaskRunnerHandle::Get(), from_here, callback); } } // namespace drive_backend } // namespace sync_file_system #endif // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_CALLBACK_HELPER_H_