1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/message_loop_proxy_impl.h"
6#include "base/threading/thread_restrictions.h"
7
8namespace base {
9
10MessageLoopProxyImpl::~MessageLoopProxyImpl() {
11  AutoLock lock(message_loop_lock_);
12  // If the target message loop still exists, the d'tor WILL execute on the
13  // target loop.
14  if (target_message_loop_) {
15    DCHECK(MessageLoop::current() == target_message_loop_);
16    MessageLoop::current()->RemoveDestructionObserver(this);
17  }
18}
19
20  // MessageLoopProxy implementation
21bool MessageLoopProxyImpl::PostTask(const tracked_objects::Location& from_here,
22                                    Task* task) {
23  return PostTaskHelper(from_here, task, 0, true);
24}
25
26bool MessageLoopProxyImpl::PostDelayedTask(
27    const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
28  return PostTaskHelper(from_here, task, delay_ms, true);
29}
30
31bool MessageLoopProxyImpl::PostNonNestableTask(
32    const tracked_objects::Location& from_here, Task* task) {
33  return PostTaskHelper(from_here, task, 0, false);
34}
35
36bool MessageLoopProxyImpl::PostNonNestableDelayedTask(
37    const tracked_objects::Location& from_here,
38    Task* task,
39    int64 delay_ms) {
40  return PostTaskHelper(from_here, task, delay_ms, false);
41}
42
43bool MessageLoopProxyImpl::BelongsToCurrentThread() {
44  // We shouldn't use MessageLoop::current() since it uses LazyInstance which
45  // may be deleted by ~AtExitManager when a WorkerPool thread calls this
46  // function.
47  // http://crbug.com/63678
48  base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
49  AutoLock lock(message_loop_lock_);
50  return (target_message_loop_ &&
51          (MessageLoop::current() == target_message_loop_));
52}
53
54// MessageLoop::DestructionObserver implementation
55void MessageLoopProxyImpl::WillDestroyCurrentMessageLoop() {
56  AutoLock lock(message_loop_lock_);
57  target_message_loop_ = NULL;
58}
59
60void MessageLoopProxyImpl::OnDestruct() const {
61  // We shouldn't use MessageLoop::current() since it uses LazyInstance which
62  // may be deleted by ~AtExitManager when a WorkerPool thread calls this
63  // function.
64  // http://crbug.com/63678
65  base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
66  bool delete_later = false;
67  {
68    AutoLock lock(message_loop_lock_);
69    if (target_message_loop_ &&
70        (MessageLoop::current() != target_message_loop_)) {
71      target_message_loop_->DeleteSoon(FROM_HERE, this);
72      delete_later = true;
73    }
74  }
75  if (!delete_later)
76    delete this;
77}
78
79MessageLoopProxyImpl::MessageLoopProxyImpl()
80    : target_message_loop_(MessageLoop::current()) {
81  target_message_loop_->AddDestructionObserver(this);
82}
83
84bool MessageLoopProxyImpl::PostTaskHelper(
85    const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
86    bool nestable) {
87  bool ret = false;
88  {
89    AutoLock lock(message_loop_lock_);
90    if (target_message_loop_) {
91      if (nestable) {
92        target_message_loop_->PostDelayedTask(from_here, task, delay_ms);
93      } else {
94        target_message_loop_->PostNonNestableDelayedTask(from_here, task,
95                                                         delay_ms);
96      }
97      ret = true;
98    }
99  }
100  if (!ret)
101    delete task;
102  return ret;
103}
104
105scoped_refptr<MessageLoopProxy>
106MessageLoopProxy::CreateForCurrentThread() {
107  scoped_refptr<MessageLoopProxy> ret(new MessageLoopProxyImpl());
108  return ret;
109}
110
111}  // namespace base
112