Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/proxy/ppb_message_loop_proxy.h" | 5 #include "ppapi/proxy/ppb_message_loop_proxy.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/threading/thread_local_storage.h" | |
| 13 #include "ppapi/c/dev/ppb_message_loop_dev.h" | 12 #include "ppapi/c/dev/ppb_message_loop_dev.h" |
| 14 #include "ppapi/c/pp_errors.h" | 13 #include "ppapi/c/pp_errors.h" |
| 15 #include "ppapi/proxy/plugin_dispatcher.h" | 14 #include "ppapi/proxy/plugin_dispatcher.h" |
| 15 #include "ppapi/proxy/plugin_globals.h" | |
| 16 #include "ppapi/shared_impl/resource.h" | 16 #include "ppapi/shared_impl/resource.h" |
| 17 #include "ppapi/thunk/enter.h" | 17 #include "ppapi/thunk/enter.h" |
| 18 #include "ppapi/thunk/ppb_message_loop_api.h" | 18 #include "ppapi/thunk/ppb_message_loop_api.h" |
| 19 | 19 |
| 20 using ppapi::thunk::PPB_MessageLoop_API; | 20 using ppapi::thunk::PPB_MessageLoop_API; |
| 21 | 21 |
| 22 namespace ppapi { | 22 namespace ppapi { |
| 23 namespace proxy { | 23 namespace proxy { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 typedef thunk::EnterResource<PPB_MessageLoop_API> EnterMessageLoop; | 27 typedef thunk::EnterResource<PPB_MessageLoop_API> EnterMessageLoop; |
| 28 | 28 |
| 29 static base::ThreadLocalStorage::StaticSlot tls_slot = TLS_INITIALIZER; | |
|
Nico
2012/02/05 03:13:37
I think this stopped needing a static initializer
brettw
2012/02/05 03:33:21
Yeah, I did this patch actually before you wrote y
| |
| 30 | |
| 31 class MessageLoopResource : public Resource, public PPB_MessageLoop_API { | 29 class MessageLoopResource : public Resource, public PPB_MessageLoop_API { |
| 32 public: | 30 public: |
| 33 MessageLoopResource(PP_Instance instance); | 31 MessageLoopResource(PP_Instance instance); |
| 34 virtual ~MessageLoopResource(); | 32 virtual ~MessageLoopResource(); |
| 35 | 33 |
| 36 // Resource overrides. | 34 // Resource overrides. |
| 37 virtual PPB_MessageLoop_API* AsPPB_MessageLoop_API() OVERRIDE; | 35 virtual PPB_MessageLoop_API* AsPPB_MessageLoop_API() OVERRIDE; |
| 38 | 36 |
| 39 // PPB_MessageLoop_API implementation. | 37 // PPB_MessageLoop_API implementation. |
| 40 virtual int32_t AttachToCurrentThread() OVERRIDE; | 38 virtual int32_t AttachToCurrentThread() OVERRIDE; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 } | 93 } |
| 96 | 94 |
| 97 MessageLoopResource::~MessageLoopResource() { | 95 MessageLoopResource::~MessageLoopResource() { |
| 98 } | 96 } |
| 99 | 97 |
| 100 PPB_MessageLoop_API* MessageLoopResource::AsPPB_MessageLoop_API() { | 98 PPB_MessageLoop_API* MessageLoopResource::AsPPB_MessageLoop_API() { |
| 101 return this; | 99 return this; |
| 102 } | 100 } |
| 103 | 101 |
| 104 int32_t MessageLoopResource::AttachToCurrentThread() { | 102 int32_t MessageLoopResource::AttachToCurrentThread() { |
| 105 if (tls_slot.initialized()) | 103 PluginGlobals* globals = PluginGlobals::Get(); |
| 106 return PP_ERROR_INPROGRESS; | 104 |
| 105 base::ThreadLocalStorage::Slot* slot = globals->msg_loop_slot(); | |
| 106 if (!slot) { | |
| 107 slot = new base::ThreadLocalStorage::Slot(&ReleaseMessageLoop); | |
| 108 globals->set_msg_loop_slot(slot); | |
| 109 } else { | |
| 110 if (slot->Get()) | |
| 111 return PP_ERROR_INPROGRESS; | |
| 112 } | |
| 107 // TODO(brettw) check that the current thread can support a message loop. | 113 // TODO(brettw) check that the current thread can support a message loop. |
| 108 | 114 |
| 109 // Take a ref to the MessageLoop on behalf of the TLS. Note that this is an | 115 // Take a ref to the MessageLoop on behalf of the TLS. Note that this is an |
| 110 // internal ref and not a plugin ref so the plugin can't accidentally | 116 // internal ref and not a plugin ref so the plugin can't accidentally |
| 111 // release it. This is released by ReleaseMessageLoop(). | 117 // release it. This is released by ReleaseMessageLoop(). |
| 112 AddRef(); | 118 AddRef(); |
| 113 tls_slot.Initialize(&ReleaseMessageLoop); | 119 slot->Set(this); |
| 114 tls_slot.Set(this); | |
| 115 | 120 |
| 116 loop_.reset(new MessageLoop(MessageLoop::TYPE_DEFAULT)); | 121 loop_.reset(new MessageLoop(MessageLoop::TYPE_DEFAULT)); |
| 117 | 122 |
| 118 // Post all pending work to the message loop. | 123 // Post all pending work to the message loop. |
| 119 for (size_t i = 0; i < pending_tasks_.size(); i++) { | 124 for (size_t i = 0; i < pending_tasks_.size(); i++) { |
| 120 const TaskInfo& info = pending_tasks_[i]; | 125 const TaskInfo& info = pending_tasks_[i]; |
| 121 PostClosure(info.from_here, info.closure, info.delay_ms); | 126 PostClosure(info.from_here, info.closure, info.delay_ms); |
| 122 } | 127 } |
| 123 pending_tasks_.clear(); | 128 pending_tasks_.clear(); |
| 124 | 129 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 // Note that the message loop must be destroyed on the thread is was created | 178 // Note that the message loop must be destroyed on the thread is was created |
| 174 // on. | 179 // on. |
| 175 loop_.reset(); | 180 loop_.reset(); |
| 176 | 181 |
| 177 // Cancel out the AddRef in AttachToCurrentThread(). | 182 // Cancel out the AddRef in AttachToCurrentThread(). |
| 178 Release(); | 183 Release(); |
| 179 // DANGER: may delete this. | 184 // DANGER: may delete this. |
| 180 } | 185 } |
| 181 | 186 |
| 182 bool MessageLoopResource::IsCurrent() const { | 187 bool MessageLoopResource::IsCurrent() const { |
| 183 if (!tls_slot.initialized()) | 188 PluginGlobals* globals = PluginGlobals::Get(); |
| 189 if (!globals->msg_loop_slot()) | |
| 184 return false; // Can't be current if there's nothing in the slot. | 190 return false; // Can't be current if there's nothing in the slot. |
| 185 return static_cast<const void*>(tls_slot.Get()) == | 191 return static_cast<const void*>(globals->msg_loop_slot()->Get()) == |
| 186 static_cast<const void*>(this); | 192 static_cast<const void*>(this); |
| 187 } | 193 } |
| 188 | 194 |
| 189 void MessageLoopResource::PostClosure( | 195 void MessageLoopResource::PostClosure( |
| 190 const tracked_objects::Location& from_here, | 196 const tracked_objects::Location& from_here, |
| 191 const base::Closure& closure, | 197 const base::Closure& closure, |
| 192 int64 delay_ms) { | 198 int64 delay_ms) { |
| 193 if (loop_.get()) { | 199 if (loop_.get()) { |
| 194 loop_->PostDelayedTask( | 200 loop_->PostDelayedTask( |
| 195 from_here, closure, base::TimeDelta::FromMilliseconds(delay_ms)); | 201 from_here, closure, base::TimeDelta::FromMilliseconds(delay_ms)); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 216 return 0; | 222 return 0; |
| 217 return (new MessageLoopResource(instance))->GetReference(); | 223 return (new MessageLoopResource(instance))->GetReference(); |
| 218 } | 224 } |
| 219 | 225 |
| 220 PP_Resource GetForMainThread() { | 226 PP_Resource GetForMainThread() { |
| 221 // TODO(brettw). | 227 // TODO(brettw). |
| 222 return 0; | 228 return 0; |
| 223 } | 229 } |
| 224 | 230 |
| 225 PP_Resource GetCurrent() { | 231 PP_Resource GetCurrent() { |
| 226 if (!tls_slot.initialized()) | 232 PluginGlobals* globals = PluginGlobals::Get(); |
| 233 if (!globals->msg_loop_slot()) | |
| 227 return 0; | 234 return 0; |
| 228 MessageLoopResource* loop = reinterpret_cast<MessageLoopResource*>( | 235 MessageLoopResource* loop = reinterpret_cast<MessageLoopResource*>( |
| 229 tls_slot.Get()); | 236 globals->msg_loop_slot()->Get()); |
| 230 return loop->GetReference(); | 237 return loop->GetReference(); |
| 231 } | 238 } |
| 232 | 239 |
| 233 int32_t AttachToCurrentThread(PP_Resource message_loop) { | 240 int32_t AttachToCurrentThread(PP_Resource message_loop) { |
| 234 EnterMessageLoop enter(message_loop, true); | 241 EnterMessageLoop enter(message_loop, true); |
| 235 if (enter.succeeded()) | 242 if (enter.succeeded()) |
| 236 return enter.object()->AttachToCurrentThread(); | 243 return enter.object()->AttachToCurrentThread(); |
| 237 return PP_ERROR_BADRESOURCE; | 244 return PP_ERROR_BADRESOURCE; |
| 238 } | 245 } |
| 239 | 246 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 PPB_MessageLoop_Proxy::~PPB_MessageLoop_Proxy() { | 286 PPB_MessageLoop_Proxy::~PPB_MessageLoop_Proxy() { |
| 280 } | 287 } |
| 281 | 288 |
| 282 // static | 289 // static |
| 283 const PPB_MessageLoop_Dev_0_1* PPB_MessageLoop_Proxy::GetInterface() { | 290 const PPB_MessageLoop_Dev_0_1* PPB_MessageLoop_Proxy::GetInterface() { |
| 284 return &ppb_message_loop_interface; | 291 return &ppb_message_loop_interface; |
| 285 } | 292 } |
| 286 | 293 |
| 287 } // namespace proxy | 294 } // namespace proxy |
| 288 } // namespace ppapi | 295 } // namespace ppapi |
| OLD | NEW |