IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / browser / device_orientation / data_fetcher_shared_memory_base.cc
blob690d1f8aa7f83e3b83369312efa102632434c837
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/device_orientation/data_fetcher_shared_memory_base.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/stl_util.h"
10 #include "base/threading/thread.h"
11 #include "base/timer/timer.h"
12 #include "content/common/device_orientation/device_motion_hardware_buffer.h"
13 #include "content/common/device_orientation/device_orientation_hardware_buffer.h"
15 namespace content {
17 namespace {
19 static size_t GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type) {
20 switch (consumer_type) {
21 case CONSUMER_TYPE_MOTION:
22 return sizeof(DeviceMotionHardwareBuffer);
23 case CONSUMER_TYPE_ORIENTATION:
24 return sizeof(DeviceOrientationHardwareBuffer);
25 default:
26 NOTREACHED();
28 return 0;
33 class DataFetcherSharedMemoryBase::PollingThread : public base::Thread {
34 public:
35 PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher);
36 virtual ~PollingThread();
38 void AddConsumer(ConsumerType consumer_type, void* buffer);
39 void RemoveConsumer(ConsumerType consumer_type);
41 unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
42 bool IsTimerRunning() const { return timer_ ? timer_->IsRunning() : false; }
44 private:
46 void DoPoll();
48 unsigned consumers_bitmask_;
49 DataFetcherSharedMemoryBase* fetcher_;
50 scoped_ptr<base::RepeatingTimer<PollingThread> > timer_;
52 DISALLOW_COPY_AND_ASSIGN(PollingThread);
55 // --- PollingThread methods
57 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
58 const char* name, DataFetcherSharedMemoryBase* fetcher)
59 : base::Thread(name),
60 consumers_bitmask_(0),
61 fetcher_(fetcher) {
64 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
67 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer(
68 ConsumerType consumer_type, void* buffer) {
69 DCHECK(fetcher_);
70 if (!fetcher_->Start(consumer_type, buffer))
71 return;
73 consumers_bitmask_ |= consumer_type;
75 if (!timer_ && fetcher_->GetType() == FETCHER_TYPE_POLLING_CALLBACK) {
76 timer_.reset(new base::RepeatingTimer<PollingThread>());
77 timer_->Start(FROM_HERE,
78 fetcher_->GetInterval(),
79 this, &PollingThread::DoPoll);
83 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer(
84 ConsumerType consumer_type) {
85 DCHECK(fetcher_);
86 if (!fetcher_->Stop(consumer_type))
87 return;
89 consumers_bitmask_ ^= consumer_type;
91 if (!consumers_bitmask_)
92 timer_.reset(); // will also stop the timer.
95 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() {
96 DCHECK(fetcher_);
97 DCHECK(consumers_bitmask_);
98 fetcher_->Fetch(consumers_bitmask_);
101 // --- end of PollingThread methods
103 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
104 : started_consumers_(0) {
107 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() {
108 StopFetchingDeviceData(CONSUMER_TYPE_MOTION);
109 StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION);
111 // make sure polling thread stops asap.
112 if (polling_thread_)
113 polling_thread_->Stop();
115 STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
116 shared_memory_map_.end());
119 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData(
120 ConsumerType consumer_type) {
121 if (started_consumers_ & consumer_type)
122 return true;
124 void* buffer = GetSharedMemoryBuffer(consumer_type);
125 if (!buffer)
126 return false;
128 if (GetType() != FETCHER_TYPE_DEFAULT) {
129 if (!InitAndStartPollingThreadIfNecessary())
130 return false;
131 polling_thread_->message_loop()->PostTask(
132 FROM_HERE,
133 base::Bind(&PollingThread::AddConsumer,
134 base::Unretained(polling_thread_.get()),
135 consumer_type, buffer));
136 } else {
137 if (!Start(consumer_type, buffer))
138 return false;
141 started_consumers_ |= consumer_type;
143 return true;
146 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData(
147 ConsumerType consumer_type) {
148 if (!(started_consumers_ & consumer_type))
149 return true;
151 if (GetType() != FETCHER_TYPE_DEFAULT) {
152 polling_thread_->message_loop()->PostTask(
153 FROM_HERE,
154 base::Bind(&PollingThread::RemoveConsumer,
155 base::Unretained(polling_thread_.get()),
156 consumer_type));
157 } else {
158 if (!Stop(consumer_type))
159 return false;
162 started_consumers_ ^= consumer_type;
164 return true;
167 base::SharedMemoryHandle
168 DataFetcherSharedMemoryBase::GetSharedMemoryHandleForProcess(
169 ConsumerType consumer_type, base::ProcessHandle process) {
170 SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
171 if (it == shared_memory_map_.end())
172 return base::SharedMemory::NULLHandle();
174 base::SharedMemoryHandle renderer_handle;
175 it->second->ShareToProcess(process, &renderer_handle);
176 return renderer_handle;
179 bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() {
180 if (polling_thread_)
181 return true;
183 polling_thread_.reset(
184 new PollingThread("Inertial Device Sensor poller", this));
186 if (!polling_thread_->Start()) {
187 LOG(ERROR) << "Failed to start inertial sensor data polling thread";
188 return false;
190 return true;
193 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
194 NOTIMPLEMENTED();
197 DataFetcherSharedMemoryBase::FetcherType
198 DataFetcherSharedMemoryBase::GetType() const {
199 return FETCHER_TYPE_DEFAULT;
202 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
203 return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
206 base::SharedMemory* DataFetcherSharedMemoryBase::GetSharedMemory(
207 ConsumerType consumer_type) {
208 SharedMemoryMap::const_iterator it = shared_memory_map_.find(consumer_type);
209 if (it != shared_memory_map_.end())
210 return it->second;
212 size_t buffer_size = GetConsumerSharedMemoryBufferSize(consumer_type);
213 if (buffer_size == 0)
214 return NULL;
216 scoped_ptr<base::SharedMemory> new_shared_mem(new base::SharedMemory);
217 if (new_shared_mem->CreateAndMapAnonymous(buffer_size)) {
218 if (void* mem = new_shared_mem->memory()) {
219 memset(mem, 0, buffer_size);
220 base::SharedMemory* shared_mem = new_shared_mem.release();
221 shared_memory_map_[consumer_type] = shared_mem;
222 return shared_mem;
225 LOG(ERROR) << "Failed to initialize shared memory";
226 return NULL;
229 void* DataFetcherSharedMemoryBase::GetSharedMemoryBuffer(
230 ConsumerType consumer_type) {
231 if (base::SharedMemory* shared_memory = GetSharedMemory(consumer_type))
232 return shared_memory->memory();
233 return NULL;
236 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
237 return polling_thread_ ? polling_thread_->message_loop() : NULL;
240 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
241 return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
245 } // namespace content