15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/post_task_and_reply_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/single_thread_task_runner.h"
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This relay class remembers the MessageLoop that it was created on, and
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ensures that both the |task| and |reply| Closures are deleted on this same
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread. Also, |task| is guaranteed to be deleted before |reply| is run or
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deleted.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If this is not possible because the originating MessageLoop is no longer
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// available, the the |task| and |reply| Closures are leaked.  Leaking is
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// considered preferable to having a thread-safetey violations caused by
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// invoking the Closure destructor on the wrong thread.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PostTaskAndReplyRelay {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostTaskAndReplyRelay(const tracked_objects::Location& from_here,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const Closure& task, const Closure& reply)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : from_here_(from_here),
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        origin_loop_(ThreadTaskRunnerHandle::Get()) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_ = task;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_ = reply;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PostTaskAndReplyRelay() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(origin_loop_->BelongsToCurrentThread());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_.Reset();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_.Reset();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Run() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_.Run();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    origin_loop_->PostTask(
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        from_here_,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Bind(&PostTaskAndReplyRelay::RunReplyAndSelfDestruct,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             base::Unretained(this)));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunReplyAndSelfDestruct() {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(origin_loop_->BelongsToCurrentThread());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Force |task_| to be released before |reply_| is to ensure that no one
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // accidentally depends on |task_| keeping one of its arguments alive while
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |reply_| is executing.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    task_.Reset();
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reply_.Run();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cue mission impossible theme.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete this;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tracked_objects::Location from_here_;
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_refptr<SingleThreadTaskRunner> origin_loop_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Closure reply_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Closure task_;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PostTaskAndReplyImpl::PostTaskAndReply(
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Closure& task,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Closure& reply) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PostTaskAndReplyRelay* relay =
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PostTaskAndReplyRelay(from_here, task, reply);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PostTask(from_here, Bind(&PostTaskAndReplyRelay::Run,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Unretained(relay)))) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete relay;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
92