blob: c876fe4d0a59f5ab550564878112ba7b03e6a261 [file] [log] [blame]
// Copyright 2020 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 REMOTING_BASE_TASK_UTIL_H_
#define REMOTING_BASE_TASK_UTIL_H_
#include "base/bind.h"
#include "base/threading/sequence_bound.h"
#include "base/threading/sequenced_task_runner_handle.h"
namespace remoting {
// Wraps and returns a callback such that it will call the original callback on
// the thread where this method is called.
template <typename... Args>
base::OnceCallback<void(Args...)> WrapCallbackToCurrentSequence(
const base::Location& from_here,
base::OnceCallback<void(Args...)> callback) {
return base::BindOnce(
[](scoped_refptr<base::SequencedTaskRunner> task_runner,
const base::Location& from_here,
base::OnceCallback<void(Args...)> callback, Args... args) {
base::OnceClosure closure =
base::BindOnce(std::move(callback), std::forward<Args>(args)...);
if (task_runner->RunsTasksInCurrentSequence()) {
std::move(closure).Run();
return;
}
task_runner->PostTask(from_here, std::move(closure));
},
base::SequencedTaskRunnerHandle::Get(), from_here, std::move(callback));
}
// Similar to base::SequenceBound::Post, but executes the callback (which should
// be the last method argument) on the sequence where the task is posted from.
// Say if you want to call this method and make |callback| run on the current
// sequence:
//
// client_.Post(FROM_HERE, &DirectoryClient::DeleteHost, host_id, callback);
//
// You can just do:
//
// PostWithCallback(FROM_HERE, &client_, &DirectoryClient::DeleteHost,
// callback, host_id);
//
// Note that |callback| is moved before other arguments, as type deduction does
// not work the other way around.
//
// Also you should probably bind a WeakPtr in your callback rather than using
// base::Unretained, since the underlying sequence bound object will generally
// be deleted after the owning object.
template <typename SequenceBoundType,
typename... MethodArgs,
typename... Args,
typename... CallbackArgs>
void PostWithCallback(const base::Location& from_here,
base::SequenceBound<SequenceBoundType>* client,
void (SequenceBoundType::*method)(MethodArgs...),
base::OnceCallback<void(CallbackArgs...)> callback,
Args&&... args) {
client->Post(from_here, method, std::forward<Args>(args)...,
WrapCallbackToCurrentSequence(from_here, std::move(callback)));
}
} // namespace remoting
#endif // REMOTING_BASE_TASK_UTIL_H_