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