| Index: ppapi/proxy/ppb_message_loop_proxy.cc
|
| diff --git a/ppapi/proxy/ppb_message_loop_proxy.cc b/ppapi/proxy/ppb_message_loop_proxy.cc
|
| index bcbb82a72a940e6086c450f695104a07f01840a2..916002d0795981d4be027dc4b2034ea080c33044 100644
|
| --- a/ppapi/proxy/ppb_message_loop_proxy.cc
|
| +++ b/ppapi/proxy/ppb_message_loop_proxy.cc
|
| @@ -9,14 +9,13 @@
|
| #include "base/bind.h"
|
| #include "base/compiler_specific.h"
|
| #include "base/message_loop.h"
|
| +#include "base/message_loop_proxy.h"
|
| #include "ppapi/c/dev/ppb_message_loop_dev.h"
|
| #include "ppapi/c/pp_errors.h"
|
| #include "ppapi/proxy/plugin_dispatcher.h"
|
| #include "ppapi/proxy/plugin_globals.h"
|
| #include "ppapi/shared_impl/proxy_lock.h"
|
| -#include "ppapi/shared_impl/resource.h"
|
| #include "ppapi/thunk/enter.h"
|
| -#include "ppapi/thunk/ppb_message_loop_api.h"
|
|
|
| using ppapi::thunk::PPB_MessageLoop_API;
|
|
|
| @@ -24,78 +23,42 @@ namespace ppapi {
|
| namespace proxy {
|
|
|
| namespace {
|
| -
|
| typedef thunk::EnterResource<PPB_MessageLoop_API> EnterMessageLoop;
|
| -
|
| -class MessageLoopResource : public Resource, public PPB_MessageLoop_API {
|
| - public:
|
| - MessageLoopResource(PP_Instance instance);
|
| - virtual ~MessageLoopResource();
|
| -
|
| - // Resource overrides.
|
| - virtual PPB_MessageLoop_API* AsPPB_MessageLoop_API() OVERRIDE;
|
| -
|
| - // PPB_MessageLoop_API implementation.
|
| - virtual int32_t AttachToCurrentThread() OVERRIDE;
|
| - virtual int32_t Run() OVERRIDE;
|
| - virtual int32_t PostWork(PP_CompletionCallback callback,
|
| - int64_t delay_ms) OVERRIDE;
|
| - virtual int32_t PostQuit(PP_Bool should_destroy) OVERRIDE;
|
| -
|
| - void DetachFromThread();
|
| -
|
| - private:
|
| - struct TaskInfo {
|
| - tracked_objects::Location from_here;
|
| - base::Closure closure;
|
| - int64 delay_ms;
|
| - };
|
| -
|
| - // Returns true if the object is associated with the current thread.
|
| - bool IsCurrent() const;
|
| -
|
| - // 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 delay_ms);
|
| -
|
| - // 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.
|
| - scoped_ptr<MessageLoop> loop_;
|
| -
|
| - // 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_;
|
| -
|
| - // 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);
|
| -};
|
| +}
|
|
|
| MessageLoopResource::MessageLoopResource(PP_Instance instance)
|
| : Resource(OBJECT_IS_PROXY, instance),
|
| nested_invocations_(0),
|
| destroyed_(false),
|
| - should_destroy_(false) {
|
| + should_destroy_(false),
|
| + is_main_thread_loop_(false) {
|
| +}
|
| +
|
| +MessageLoopResource::MessageLoopResource(ForMainThread)
|
| + : Resource(Resource::Untracked()),
|
| + nested_invocations_(0),
|
| + destroyed_(false),
|
| + should_destroy_(false),
|
| + is_main_thread_loop_(true) {
|
| + // We attach the main thread immediately. We can't use AttachToCurrentThread,
|
| + // because the MessageLoop already exists.
|
| +
|
| + // This must be called only once, so the slot must be empty.
|
| + CHECK(!PluginGlobals::Get()->msg_loop_slot());
|
| + base::ThreadLocalStorage::Slot* slot =
|
| + new base::ThreadLocalStorage::Slot(&ReleaseMessageLoop);
|
| + PluginGlobals::Get()->set_msg_loop_slot(slot);
|
| +
|
| + // Take a ref to the MessageLoop on behalf of the TLS. Note that this is an
|
| + // internal ref and not a plugin ref so the plugin can't accidentally
|
| + // release it. This is released by ReleaseMessageLoop().
|
| + AddRef();
|
| + slot->Set(this);
|
| +
|
| + loop_proxy_ = base::MessageLoopProxy::current();
|
| }
|
|
|
| +
|
| MessageLoopResource::~MessageLoopResource() {
|
| }
|
|
|
| @@ -104,6 +67,9 @@ PPB_MessageLoop_API* MessageLoopResource::AsPPB_MessageLoop_API() {
|
| }
|
|
|
| int32_t MessageLoopResource::AttachToCurrentThread() {
|
| + if (is_main_thread_loop_)
|
| + return PP_ERROR_INPROGRESS;
|
| +
|
| PluginGlobals* globals = PluginGlobals::Get();
|
|
|
| base::ThreadLocalStorage::Slot* slot = globals->msg_loop_slot();
|
| @@ -123,6 +89,7 @@ int32_t MessageLoopResource::AttachToCurrentThread() {
|
| slot->Set(this);
|
|
|
| loop_.reset(new MessageLoop(MessageLoop::TYPE_DEFAULT));
|
| + loop_proxy_ = base::MessageLoopProxy::current();
|
|
|
| // Post all pending work to the message loop.
|
| for (size_t i = 0; i < pending_tasks_.size(); i++) {
|
| @@ -137,9 +104,8 @@ int32_t MessageLoopResource::AttachToCurrentThread() {
|
| int32_t MessageLoopResource::Run() {
|
| if (!IsCurrent())
|
| return PP_ERROR_WRONG_THREAD;
|
| - // TODO(brettw) prevent this from happening on the main thread & return
|
| - // PP_ERROR_BLOCKS_MAIN_THREAD. Maybe have a special constructor for that
|
| - // one?
|
| + if (is_main_thread_loop_)
|
| + return PP_ERROR_INPROGRESS;
|
|
|
| nested_invocations_++;
|
| CallWhileUnlocked(base::Bind(&MessageLoop::Run,
|
| @@ -147,6 +113,7 @@ int32_t MessageLoopResource::Run() {
|
| nested_invocations_--;
|
|
|
| if (should_destroy_ && nested_invocations_ == 0) {
|
| + loop_proxy_ = NULL;
|
| loop_.reset();
|
| destroyed_ = true;
|
| }
|
| @@ -167,6 +134,9 @@ int32_t MessageLoopResource::PostWork(PP_CompletionCallback callback,
|
| }
|
|
|
| int32_t MessageLoopResource::PostQuit(PP_Bool should_destroy) {
|
| + if (is_main_thread_loop_)
|
| + return PP_ERROR_WRONG_THREAD;
|
| +
|
| if (PP_ToBool(should_destroy))
|
| should_destroy_ = true;
|
|
|
| @@ -178,8 +148,14 @@ int32_t MessageLoopResource::PostQuit(PP_Bool should_destroy) {
|
| }
|
|
|
| void MessageLoopResource::DetachFromThread() {
|
| + // Never detach the main thread from its loop resource. Other plugin instances
|
| + // might need it.
|
| + if (is_main_thread_loop_)
|
| + return;
|
| +
|
| // Note that the message loop must be destroyed on the thread is was created
|
| // on.
|
| + loop_proxy_ = NULL;
|
| loop_.reset();
|
|
|
| // Cancel out the AddRef in AttachToCurrentThread().
|
| @@ -199,10 +175,10 @@ void MessageLoopResource::PostClosure(
|
| const tracked_objects::Location& from_here,
|
| const base::Closure& closure,
|
| int64 delay_ms) {
|
| - if (loop_.get()) {
|
| - loop_->PostDelayedTask(from_here,
|
| - closure,
|
| - base::TimeDelta::FromMilliseconds(delay_ms));
|
| + if (loop_proxy_) {
|
| + loop_proxy_->PostDelayedTask(from_here,
|
| + closure,
|
| + base::TimeDelta::FromMilliseconds(delay_ms));
|
| } else {
|
| TaskInfo info;
|
| info.from_here = FROM_HERE;
|
| @@ -228,8 +204,7 @@ PP_Resource Create(PP_Instance instance) {
|
| }
|
|
|
| PP_Resource GetForMainThread() {
|
| - // TODO(brettw).
|
| - return 0;
|
| + return PluginGlobals::Get()->loop_for_main_thread()->GetReference();
|
| }
|
|
|
| PP_Resource GetCurrent() {
|
| @@ -281,8 +256,6 @@ const PPB_MessageLoop_Dev_0_1 ppb_message_loop_interface = {
|
| &PostQuit
|
| };
|
|
|
| -} // namespace
|
| -
|
| PPB_MessageLoop_Proxy::PPB_MessageLoop_Proxy(Dispatcher* dispatcher)
|
| : InterfaceProxy(dispatcher) {
|
| }
|
|
|