summaryrefslogtreecommitdiff
path: root/chromium/ppapi/proxy/ppb_message_loop_proxy.h
blob: f78c377225409b66dc7566fd7d489a14359c2c93 (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
// Copyright (c) 2012 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 PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_
#define PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_

#include <stdint.h>

#include <memory>

#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "ppapi/proxy/interface_proxy.h"
#include "ppapi/proxy/ppapi_proxy_export.h"
#include "ppapi/shared_impl/ppb_message_loop_shared.h"
#include "ppapi/thunk/ppb_message_loop_api.h"

struct PPB_MessageLoop_1_0;

namespace ppapi {
namespace proxy {

class PPAPI_PROXY_EXPORT MessageLoopResource : public MessageLoopShared {
 public:
  explicit MessageLoopResource(PP_Instance instance);
  // Construct the one MessageLoopResource for the main thread. This must be
  // invoked on the main thread.
  explicit MessageLoopResource(ForMainThread);
  ~MessageLoopResource() override;

  // Resource overrides.
  thunk::PPB_MessageLoop_API* AsPPB_MessageLoop_API() override;

  // PPB_MessageLoop_API implementation.
  int32_t AttachToCurrentThread() override;
  int32_t Run() override;
  int32_t PostWork(PP_CompletionCallback callback, int64_t delay_ms) override;
  int32_t PostQuit(PP_Bool should_destroy) override;

  static MessageLoopResource* GetCurrent();
  void DetachFromThread();
  bool is_main_thread_loop() const {
    return is_main_thread_loop_;
  }

  const scoped_refptr<base::SingleThreadTaskRunner>& task_runner() {
    return task_runner_;
  }

  void set_currently_handling_blocking_message(bool handling_blocking_message) {
    currently_handling_blocking_message_ = handling_blocking_message;
  }

 private:
  struct TaskInfo {
    tracked_objects::Location from_here;
    base::Closure closure;
    int64_t delay_ms;
  };

  // Returns true if the object is associated with the current thread.
  bool IsCurrent() const;

  // MessageLoopShared implementation.
  //
  // Handles posting to the message loop if there is one, or the pending queue
  // if there isn't.
  // NOTE: The given closure will be run *WITHOUT* acquiring the Proxy lock.
  //       This only makes sense for user code and completely thread-safe
  //       proxy operations (e.g., MessageLoop::QuitClosure).
  void PostClosure(const tracked_objects::Location& from_here,
                   const base::Closure& closure,
                   int64_t delay_ms) override;
  base::SingleThreadTaskRunner* GetTaskRunner() override;
  bool CurrentlyHandlingBlockingMessage() override;

  // Quits |run_loop_|. Must be called from the thread that runs the RunLoop.
  void QuitRunLoopWhenIdle();

  // TLS destructor function.
  static void ReleaseMessageLoop(void* value);

  // Created when we attach to the current thread, since MessageLoop assumes
  // that it's created on the thread it will run on. NULL for the main thread
  // loop, since that's owned by somebody else. This is needed for Run and Quit.
  // Any time we post tasks, we should post them using task_runner_.
  std::unique_ptr<base::MessageLoop> loop_;
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;

  // RunLoop currently on the stack.
  base::RunLoop* run_loop_ = nullptr;

  // Number of invocations of Run currently on the stack.
  int nested_invocations_;

  // Set to true when the message loop is destroyed to prevent forther
  // posting of work.
  bool destroyed_;

  // Set to true if all message loop invocations should exit and that the
  // loop should be destroyed once it reaches the outermost Run invocation.
  bool should_destroy_;

  bool is_main_thread_loop_;

  bool currently_handling_blocking_message_;

  // Since we allow tasks to be posted before the message loop is actually
  // created (when it's associated with a thread), we keep tasks posted here
  // until that happens. Once the loop_ is created, this is unused.
  std::vector<TaskInfo> pending_tasks_;

  DISALLOW_COPY_AND_ASSIGN(MessageLoopResource);
};

class PPB_MessageLoop_Proxy : public InterfaceProxy {
 public:
  explicit PPB_MessageLoop_Proxy(Dispatcher* dispatcher);
  virtual ~PPB_MessageLoop_Proxy();

  static const PPB_MessageLoop_1_0* GetInterface();

 private:
  DISALLOW_COPY_AND_ASSIGN(PPB_MessageLoop_Proxy);
};

}  // namespace proxy
}  // namespace ppapi

#endif  // PPAPI_PROXY_PPB_MESSAGE_LOOP_PROXY_H_