mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
128 lines
4.4 KiB
C++
128 lines
4.4 KiB
C++
|
// Copyright (c) 2011 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.
|
||
|
|
||
|
#include "base/threading/post_task_and_reply_impl.h"
|
||
|
|
||
|
#include <utility>
|
||
|
|
||
|
#include "base/bind.h"
|
||
|
#include "base/debug/leak_annotations.h"
|
||
|
#include "base/logging.h"
|
||
|
#include "base/memory/ref_counted.h"
|
||
|
#include "base/sequenced_task_runner.h"
|
||
|
#include "base/threading/sequenced_task_runner_handle.h"
|
||
|
|
||
|
namespace base {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
class PostTaskAndReplyRelay {
|
||
|
public:
|
||
|
PostTaskAndReplyRelay(const Location& from_here,
|
||
|
OnceClosure task,
|
||
|
OnceClosure reply)
|
||
|
: from_here_(from_here),
|
||
|
task_(std::move(task)),
|
||
|
reply_(std::move(reply)) {}
|
||
|
PostTaskAndReplyRelay(PostTaskAndReplyRelay&&) = default;
|
||
|
|
||
|
~PostTaskAndReplyRelay() {
|
||
|
if (reply_) {
|
||
|
// This can run:
|
||
|
// 1) On origin sequence, when:
|
||
|
// 1a) Posting |task_| fails.
|
||
|
// 1b) |reply_| is cancelled before running.
|
||
|
// 1c) The DeleteSoon() below is scheduled.
|
||
|
// 2) On destination sequence, when:
|
||
|
// 2a) |task_| is cancelled before running.
|
||
|
// 2b) Posting |reply_| fails.
|
||
|
|
||
|
if (!reply_task_runner_->RunsTasksInCurrentSequence()) {
|
||
|
// Case 2a) or 2b).
|
||
|
//
|
||
|
// Destroy callbacks asynchronously on |reply_task_runner| since their
|
||
|
// destructors can rightfully be affine to it. As always, DeleteSoon()
|
||
|
// might leak its argument if the target execution environment is
|
||
|
// shutdown (e.g. MessageLoop deleted, TaskScheduler shutdown).
|
||
|
//
|
||
|
// Note: while it's obvious why |reply_| can be affine to
|
||
|
// |reply_task_runner|, the reason that |task_| can also be affine to it
|
||
|
// is that it if neither tasks ran, |task_| may still hold an object
|
||
|
// which was intended to be moved to |reply_| when |task_| ran (such an
|
||
|
// object's destruction can be affine to |reply_task_runner_| -- e.g.
|
||
|
// https://crbug.com/829122).
|
||
|
auto relay_to_delete =
|
||
|
std::make_unique<PostTaskAndReplyRelay>(std::move(*this));
|
||
|
ANNOTATE_LEAKING_OBJECT_PTR(relay_to_delete.get());
|
||
|
reply_task_runner_->DeleteSoon(from_here_, std::move(relay_to_delete));
|
||
|
}
|
||
|
|
||
|
// Case 1a), 1b), 1c).
|
||
|
//
|
||
|
// Callbacks will be destroyed synchronously at the end of this scope.
|
||
|
} else {
|
||
|
// This can run when both callbacks have run or have been moved to another
|
||
|
// PostTaskAndReplyRelay instance. If |reply_| is null, |task_| must be
|
||
|
// null too.
|
||
|
DCHECK(!task_);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// No assignment operator because of const members.
|
||
|
PostTaskAndReplyRelay& operator=(PostTaskAndReplyRelay&&) = delete;
|
||
|
|
||
|
// Static function is used because it is not possible to bind a method call to
|
||
|
// a non-pointer type.
|
||
|
static void RunTaskAndPostReply(PostTaskAndReplyRelay relay) {
|
||
|
DCHECK(relay.task_);
|
||
|
std::move(relay.task_).Run();
|
||
|
|
||
|
// Keep a reference to the reply TaskRunner for the PostTask() call before
|
||
|
// |relay| is moved into a callback.
|
||
|
scoped_refptr<SequencedTaskRunner> reply_task_runner =
|
||
|
relay.reply_task_runner_;
|
||
|
|
||
|
reply_task_runner->PostTask(
|
||
|
relay.from_here_,
|
||
|
BindOnce(&PostTaskAndReplyRelay::RunReply, std::move(relay)));
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
// Static function is used because it is not possible to bind a method call to
|
||
|
// a non-pointer type.
|
||
|
static void RunReply(PostTaskAndReplyRelay relay) {
|
||
|
DCHECK(!relay.task_);
|
||
|
DCHECK(relay.reply_);
|
||
|
std::move(relay.reply_).Run();
|
||
|
}
|
||
|
|
||
|
const Location from_here_;
|
||
|
OnceClosure task_;
|
||
|
OnceClosure reply_;
|
||
|
const scoped_refptr<SequencedTaskRunner> reply_task_runner_ =
|
||
|
SequencedTaskRunnerHandle::Get();
|
||
|
|
||
|
DISALLOW_COPY_AND_ASSIGN(PostTaskAndReplyRelay);
|
||
|
};
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
namespace internal {
|
||
|
|
||
|
bool PostTaskAndReplyImpl::PostTaskAndReply(const Location& from_here,
|
||
|
OnceClosure task,
|
||
|
OnceClosure reply) {
|
||
|
DCHECK(task) << from_here.ToString();
|
||
|
DCHECK(reply) << from_here.ToString();
|
||
|
|
||
|
return PostTask(from_here,
|
||
|
BindOnce(&PostTaskAndReplyRelay::RunTaskAndPostReply,
|
||
|
PostTaskAndReplyRelay(from_here, std::move(task),
|
||
|
std::move(reply))));
|
||
|
}
|
||
|
|
||
|
} // namespace internal
|
||
|
|
||
|
} // namespace base
|