Index: content/browser/gamepad/gamepad_provider.cc |
diff --git a/content/browser/gamepad/gamepad_provider.cc b/content/browser/gamepad/gamepad_provider.cc |
index c8eed65a30f00b447a888bfa75eedf7932c9f521..80ca1a6f4636f60cf6492d251f2994fa0bb0b563 100644 |
--- a/content/browser/gamepad/gamepad_provider.cc |
+++ b/content/browser/gamepad/gamepad_provider.cc |
@@ -9,6 +9,7 @@ |
#include "base/bind.h" |
#include "base/logging.h" |
#include "base/message_loop.h" |
+#include "base/synchronization/lock.h" |
#include "base/task.h" |
#include "base/threading/thread.h" |
#include "base/threading/thread_restrictions.h" |
@@ -23,8 +24,6 @@ |
namespace content { |
-GamepadProvider* GamepadProvider::instance_ = NULL; |
- |
// Define the default data fetcher that GamepadProvider will use if none is |
// supplied. (GamepadPlatformDataFetcher). |
#if defined(OS_WIN) |
@@ -44,9 +43,10 @@ typedef GamepadEmptyDataFetcher GamepadPlatformDataFetcher; |
#endif |
GamepadProvider::GamepadProvider(GamepadDataFetcher* fetcher) |
- : creator_loop_(MessageLoop::current()->message_loop_proxy()), |
- provided_fetcher_(fetcher), |
+ : is_paused_(false), |
devices_changed_(true), |
+ creator_loop_(MessageLoop::current()->message_loop_proxy()), |
+ provided_fetcher_(fetcher), |
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
size_t data_size = sizeof(GamepadHardwareBuffer); |
base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
@@ -55,13 +55,29 @@ GamepadProvider::GamepadProvider(GamepadDataFetcher* fetcher) |
gamepad_shared_memory_.CreateAndMapAnonymous(data_size); |
GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer(); |
memset(hwbuf, 0, sizeof(GamepadHardwareBuffer)); |
+ |
+ DCHECK(MessageLoop::current()->message_loop_proxy() == creator_loop_); |
+ |
+ polling_thread_.reset(new base::Thread("Gamepad polling thread")); |
+ if (!polling_thread_->Start()) { |
+ LOG(ERROR) << "Failed to start gamepad polling thread"; |
+ polling_thread_.reset(); |
+ return; |
+ } |
+ |
+ MessageLoop* polling_loop = polling_thread_->message_loop(); |
+ polling_loop->PostTask( |
+ FROM_HERE, |
+ base::Bind(&GamepadProvider::DoInitializePollingThread, this)); |
} |
GamepadProvider::~GamepadProvider() { |
base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
if (monitor) |
monitor->RemoveDevicesChangedObserver(this); |
- Stop(); |
+ |
+ polling_thread_.reset(); |
+ data_fetcher_.reset(); |
} |
base::SharedMemoryHandle GamepadProvider::GetRendererSharedMemoryHandle( |
@@ -71,34 +87,27 @@ base::SharedMemoryHandle GamepadProvider::GetRendererSharedMemoryHandle( |
return renderer_handle; |
} |
-void GamepadProvider::OnDevicesChanged() { |
- devices_changed_ = true; |
+void GamepadProvider::Pause() { |
+ base::AutoLock lock(is_paused_lock_); |
+ is_paused_ = true; |
} |
-void GamepadProvider::Start() { |
- DCHECK(MessageLoop::current()->message_loop_proxy() == creator_loop_); |
+void GamepadProvider::Resume() { |
+ base::AutoLock lock(is_paused_lock_); |
- if (polling_thread_.get()) |
+ if (!is_paused_) |
return; |
- polling_thread_.reset(new base::Thread("Gamepad polling thread")); |
- if (!polling_thread_->Start()) { |
- LOG(ERROR) << "Failed to start gamepad polling thread"; |
- polling_thread_.reset(); |
- return; |
- } |
- |
+ is_paused_ = false; |
MessageLoop* polling_loop = polling_thread_->message_loop(); |
polling_loop->PostTask( |
FROM_HERE, |
- base::Bind(&GamepadProvider::DoInitializePollingThread, this)); |
+ base::Bind(&GamepadProvider::ScheduleDoPoll, this)); |
} |
-void GamepadProvider::Stop() { |
- DCHECK(MessageLoop::current()->message_loop_proxy() == creator_loop_); |
- |
- polling_thread_.reset(); |
- data_fetcher_.reset(); |
+void GamepadProvider::OnDevicesChanged() { |
+ base::AutoLock lock(devices_changed_lock_); |
+ devices_changed_ = true; |
} |
void GamepadProvider::DoInitializePollingThread() { |
@@ -123,18 +132,27 @@ void GamepadProvider::DoPoll() { |
sizeof(WebKit::WebGamepads), |
"Racey reads are discarded"); |
+ devices_changed_lock_.Acquire(); |
+ |
// Acquire the SeqLock. There is only ever one writer to this data. |
// See gamepad_hardware_buffer.h. |
hwbuf->sequence.WriteBegin(); |
data_fetcher_->GetGamepadData(&hwbuf->buffer, devices_changed_); |
hwbuf->sequence.WriteEnd(); |
devices_changed_ = false; |
+ |
+ devices_changed_lock_.Release(); |
+ |
// Schedule our next interval of polling. |
ScheduleDoPoll(); |
} |
void GamepadProvider::ScheduleDoPoll() { |
DCHECK(MessageLoop::current() == polling_thread_->message_loop()); |
+ base::AutoLock lock(is_paused_lock_); |
+ |
+ if (is_paused_) |
+ return; |
MessageLoop::current()->PostDelayedTask( |
FROM_HERE, |