| // 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 { | |
| base::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 base::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); | |
| ~PPB_MessageLoop_Proxy() override; | |
| 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_ |