summaryrefslogtreecommitdiffstats
path: root/base/message_loop_proxy.h
blob: d783b4e6bc7c61142a7a2458948441696103138b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// 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.

#ifndef BASE_MESSAGE_LOOP_PROXY_H_
#define BASE_MESSAGE_LOOP_PROXY_H_
#pragma once

#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/task.h"

namespace tracked_objects {
class Location;
} // namespace tracked_objects

namespace base {

struct MessageLoopProxyTraits;

// This class provides a thread-safe refcounted interface to the Post* methods
// of a message loop. This class can outlive the target message loop.
// MessageLoopProxy objects are constructed automatically for all MessageLoops.
// So, to access them, you can use any of the following:
//   Thread::message_loop_proxy()
//   MessageLoop::current()->message_loop_proxy()
//   MessageLoopProxy::current()
class BASE_EXPORT MessageLoopProxy
    : public base::RefCountedThreadSafe<MessageLoopProxy,
                                        MessageLoopProxyTraits> {
 public:
  // These methods are the same as in message_loop.h, but are guaranteed to
  // either post the Task to the MessageLoop (if it's still alive), or to
  // delete the Task otherwise.
  // They return true iff the thread existed and the task was posted.  Note that
  // even if the task is posted, there's no guarantee that it will run; for
  // example the target loop may already be quitting, or in the case of a
  // delayed task a Quit message may preempt it in the message loop queue.
  // Conversely, a return value of false is a guarantee the task will not run.
  virtual bool PostTask(const tracked_objects::Location& from_here,
                        Task* task) = 0;
  virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
                               Task* task,
                               int64 delay_ms) = 0;
  virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
                                   Task* task) = 0;
  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      Task* task,
      int64 delay_ms) = 0;

  // TODO(ajwong): Remove the functions above once the Task -> Closure migration
  // is complete.
  //
  // There are 2 sets of Post*Task functions, one which takes the older Task*
  // function object representation, and one that takes the newer base::Closure.
  // We have this overload to allow a staged transition between the two systems.
  // Once the transition is done, the functions above should be deleted.
  virtual bool PostTask(const tracked_objects::Location& from_here,
                        const base::Closure& task) = 0;
  virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
                               const base::Closure& task,
                               int64 delay_ms) = 0;
  virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
                                   const base::Closure& task) = 0;
  virtual bool PostNonNestableDelayedTask(
      const tracked_objects::Location& from_here,
      const base::Closure& task,
      int64 delay_ms) = 0;

  // A method which checks if the caller is currently running in the thread that
  // this proxy represents.
  virtual bool BelongsToCurrentThread() = 0;

  // Executes |task| on the given MessageLoopProxy.  On completion, |reply|
  // is passed back to the MessageLoopProxy for the thread that called
  // PostTaskAndReply().  Both |task| and |reply| are guaranteed to be deleted
  // on the thread from which PostTaskAndReply() is invoked.  This allows
  // objects that must be deleted on the originating thread to be bound into the
  // |task| and |reply| Closures.  In particular, it can be useful to use
  // WeakPtr<> in the |reply| Closure so that the reply operation can be
  // canceled. See the following pseudo-code:
  //
  // class DataBuffer : public RefCountedThreadSafe<DataBuffer> {
  //  public:
  //   // Called to add data into a buffer.
  //   void AddData(void* buf, size_t length);
  //   ...
  // };
  //
  //
  // class DataLoader : public SupportsWeakPtr<DataLoader> {
  //  public:
  //    void GetData() {
  //      scoped_refptr<DataBuffer> buffer = new DataBuffer();
  //      target_thread_.message_loop_proxy()->PostTaskAndReply(
  //          FROM_HERE,
  //          base::Bind(&DataBuffer::AddData, buffer),
  //          base::Bind(&DataLoader::OnDataReceived, AsWeakPtr(), buffer));
  //    }
  //
  //  private:
  //    void OnDataReceived(scoped_refptr<DataBuffer> buffer) {
  //      // Do something with buffer.
  //    }
  // };
  //
  //
  // Things to notice:
  //   * Results of |task| are shared with |reply| by binding a shared argument
  //     (a DataBuffer instance).
  //   * The DataLoader object has no special thread safety.
  //   * The DataLoader object can be deleted while |task| is still running,
  //     and the reply will cancel itself safely because it is bound to a
  //     WeakPtr<>.
  bool PostTaskAndReply(const tracked_objects::Location& from_here,
                        const Closure& task,
                        const Closure& reply);

  template <class T>
  bool DeleteSoon(const tracked_objects::Location& from_here,
                  T* object) {
    return PostNonNestableTask(from_here, new DeleteTask<T>(object));
  }
  template <class T>
  bool ReleaseSoon(const tracked_objects::Location& from_here,
                   T* object) {
    return PostNonNestableTask(from_here, new ReleaseTask<T>(object));
  }

  // Gets the MessageLoopProxy for the current message loop, creating one if
  // needed.
  static scoped_refptr<MessageLoopProxy> current();

 protected:
  friend class RefCountedThreadSafe<MessageLoopProxy, MessageLoopProxyTraits>;
  friend struct MessageLoopProxyTraits;

  MessageLoopProxy();
  virtual ~MessageLoopProxy();

  // Called when the proxy is about to be deleted. Subclasses can override this
  // to provide deletion on specific threads.
  virtual void OnDestruct() const;
};

struct MessageLoopProxyTraits {
  static void Destruct(const MessageLoopProxy* proxy) {
    proxy->OnDestruct();
  }
};

}  // namespace base

#endif  // BASE_MESSAGE_LOOP_PROXY_H_