1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/threading/post_task_and_reply_impl.h"
6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <utility>
836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe
9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/bind.h"
1036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/debug/leak_annotations.h"
1136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/logging.h"
1236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/memory/ref_counted.h"
1336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/sequence_checker.h"
1436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/sequenced_task_runner.h"
1536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/threading/sequenced_task_runner_handle.h"
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace {
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
2136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// This relay class remembers the sequence that it was created on, and ensures
2236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// that both the |task| and |reply| Closures are deleted on this same sequence.
2336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Also, |task| is guaranteed to be deleted before |reply| is run or deleted.
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
2536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// If RunReplyAndSelfDestruct() doesn't run because the originating execution
2636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// context is no longer available, then the |task| and |reply| Closures are
2736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// leaked. Leaking is considered preferable to having a thread-safetey
2836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// violations caused by invoking the Closure destructor on the wrong sequence.
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratclass PostTaskAndReplyRelay {
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat public:
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  PostTaskAndReplyRelay(const tracked_objects::Location& from_here,
32f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                        OnceClosure task,
33f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe                        OnceClosure reply)
3436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      : sequence_checker_(),
3536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        from_here_(from_here),
3636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        origin_task_runner_(SequencedTaskRunnerHandle::Get()),
3736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        reply_(std::move(reply)),
3836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe        task_(std::move(task)) {}
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ~PostTaskAndReplyRelay() {
4136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK(sequence_checker_.CalledOnValidSequence());
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
4436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  void RunTaskAndPostReply() {
45f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    std::move(task_).Run();
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    origin_task_runner_->PostTask(
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        from_here_, Bind(&PostTaskAndReplyRelay::RunReplyAndSelfDestruct,
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                         base::Unretained(this)));
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat private:
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  void RunReplyAndSelfDestruct() {
5336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe    DCHECK(sequence_checker_.CalledOnValidSequence());
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
55f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    // Ensure |task_| has already been released before |reply_| to ensure that
56f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    // no one accidentally depends on |task_| keeping one of its arguments alive
57f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    // while |reply_| is executing.
58f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    DCHECK(!task_);
59b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
60f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    std::move(reply_).Run();
61b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Cue mission impossible theme.
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    delete this;
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
6636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const SequenceChecker sequence_checker_;
6736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const tracked_objects::Location from_here_;
6836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  const scoped_refptr<SequencedTaskRunner> origin_task_runner_;
69f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  OnceClosure reply_;
70f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe  OnceClosure task_;
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat};
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace internal {
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool PostTaskAndReplyImpl::PostTaskAndReply(
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    const tracked_objects::Location& from_here,
79f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    OnceClosure task,
80f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe    OnceClosure reply) {
8136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(!task.is_null()) << from_here.ToString();
8236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  DCHECK(!reply.is_null()) << from_here.ToString();
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  PostTaskAndReplyRelay* relay =
8436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe      new PostTaskAndReplyRelay(from_here, std::move(task), std::move(reply));
8536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // PostTaskAndReplyRelay self-destructs after executing |reply|. On the flip
8636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // side though, it is intentionally leaked if the |task| doesn't complete
8736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // before the origin sequence stops executing tasks. Annotate |relay| as leaky
8836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // to avoid having to suppress every callsite which happens to flakily trigger
8936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  // this race.
9036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  ANNOTATE_LEAKING_OBJECT_PTR(relay);
9136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe  if (!PostTask(from_here, Bind(&PostTaskAndReplyRelay::RunTaskAndPostReply,
92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                Unretained(relay)))) {
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    delete relay;
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return true;
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace internal
101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
103