| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "content/browser/device_orientation/data_fetcher_shared_memory_base.h" | |
| 6 | |
| 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
" | |
| 14 | |
| 15 namespace content { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 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(); | |
| 27 } | |
| 28 return 0; | |
| 29 } | |
| 30 | |
| 31 } | |
| 32 | |
| 33 class DataFetcherSharedMemoryBase::PollingThread : public base::Thread { | |
| 34 public: | |
| 35 PollingThread(const char* name, DataFetcherSharedMemoryBase* fetcher); | |
| 36 virtual ~PollingThread(); | |
| 37 | |
| 38 void AddConsumer(ConsumerType consumer_type, void* buffer); | |
| 39 void RemoveConsumer(ConsumerType consumer_type); | |
| 40 | |
| 41 unsigned GetConsumersBitmask() const { return consumers_bitmask_; } | |
| 42 bool IsTimerRunning() const { return timer_ ? timer_->IsRunning() : false; } | |
| 43 | |
| 44 private: | |
| 45 | |
| 46 void DoPoll(); | |
| 47 | |
| 48 unsigned consumers_bitmask_; | |
| 49 DataFetcherSharedMemoryBase* fetcher_; | |
| 50 scoped_ptr<base::RepeatingTimer<PollingThread> > timer_; | |
| 51 | |
| 52 DISALLOW_COPY_AND_ASSIGN(PollingThread); | |
| 53 }; | |
| 54 | |
| 55 // --- PollingThread methods | |
| 56 | |
| 57 DataFetcherSharedMemoryBase::PollingThread::PollingThread( | |
| 58 const char* name, DataFetcherSharedMemoryBase* fetcher) | |
| 59 : base::Thread(name), | |
| 60 consumers_bitmask_(0), | |
| 61 fetcher_(fetcher) { | |
| 62 } | |
| 63 | |
| 64 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() { | |
| 65 } | |
| 66 | |
| 67 void DataFetcherSharedMemoryBase::PollingThread::AddConsumer( | |
| 68 ConsumerType consumer_type, void* buffer) { | |
| 69 DCHECK(fetcher_); | |
| 70 if (!fetcher_->Start(consumer_type, buffer)) | |
| 71 return; | |
| 72 | |
| 73 consumers_bitmask_ |= consumer_type; | |
| 74 | |
| 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); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 void DataFetcherSharedMemoryBase::PollingThread::RemoveConsumer( | |
| 84 ConsumerType consumer_type) { | |
| 85 DCHECK(fetcher_); | |
| 86 if (!fetcher_->Stop(consumer_type)) | |
| 87 return; | |
| 88 | |
| 89 consumers_bitmask_ ^= consumer_type; | |
| 90 | |
| 91 if (!consumers_bitmask_) | |
| 92 timer_.reset(); // will also stop the timer. | |
| 93 } | |
| 94 | |
| 95 void DataFetcherSharedMemoryBase::PollingThread::DoPoll() { | |
| 96 DCHECK(fetcher_); | |
| 97 DCHECK(consumers_bitmask_); | |
| 98 fetcher_->Fetch(consumers_bitmask_); | |
| 99 } | |
| 100 | |
| 101 // --- end of PollingThread methods | |
| 102 | |
| 103 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase() | |
| 104 : started_consumers_(0) { | |
| 105 } | |
| 106 | |
| 107 DataFetcherSharedMemoryBase::~DataFetcherSharedMemoryBase() { | |
| 108 StopFetchingDeviceData(CONSUMER_TYPE_MOTION); | |
| 109 StopFetchingDeviceData(CONSUMER_TYPE_ORIENTATION); | |
| 110 | |
| 111 // make sure polling thread stops asap. | |
| 112 if (polling_thread_) | |
| 113 polling_thread_->Stop(); | |
| 114 | |
| 115 STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(), | |
| 116 shared_memory_map_.end()); | |
| 117 } | |
| 118 | |
| 119 bool DataFetcherSharedMemoryBase::StartFetchingDeviceData( | |
| 120 ConsumerType consumer_type) { | |
| 121 if (started_consumers_ & consumer_type) | |
| 122 return true; | |
| 123 | |
| 124 void* buffer = GetSharedMemoryBuffer(consumer_type); | |
| 125 if (!buffer) | |
| 126 return false; | |
| 127 | |
| 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; | |
| 139 } | |
| 140 | |
| 141 started_consumers_ |= consumer_type; | |
| 142 | |
| 143 return true; | |
| 144 } | |
| 145 | |
| 146 bool DataFetcherSharedMemoryBase::StopFetchingDeviceData( | |
| 147 ConsumerType consumer_type) { | |
| 148 if (!(started_consumers_ & consumer_type)) | |
| 149 return true; | |
| 150 | |
| 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; | |
| 160 } | |
| 161 | |
| 162 started_consumers_ ^= consumer_type; | |
| 163 | |
| 164 return true; | |
| 165 } | |
| 166 | |
| 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(); | |
| 173 | |
| 174 base::SharedMemoryHandle renderer_handle; | |
| 175 it->second->ShareToProcess(process, &renderer_handle); | |
| 176 return renderer_handle; | |
| 177 } | |
| 178 | |
| 179 bool DataFetcherSharedMemoryBase::InitAndStartPollingThreadIfNecessary() { | |
| 180 if (polling_thread_) | |
| 181 return true; | |
| 182 | |
| 183 polling_thread_.reset( | |
| 184 new PollingThread("Inertial Device Sensor poller", this)); | |
| 185 | |
| 186 if (!polling_thread_->Start()) { | |
| 187 LOG(ERROR) << "Failed to start inertial sensor data polling thread"; | |
| 188 return false; | |
| 189 } | |
| 190 return true; | |
| 191 } | |
| 192 | |
| 193 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) { | |
| 194 NOTIMPLEMENTED(); | |
| 195 } | |
| 196 | |
| 197 DataFetcherSharedMemoryBase::FetcherType | |
| 198 DataFetcherSharedMemoryBase::GetType() const { | |
| 199 return FETCHER_TYPE_DEFAULT; | |
| 200 } | |
| 201 | |
| 202 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const { | |
| 203 return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis); | |
| 204 } | |
| 205 | |
| 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; | |
| 211 | |
| 212 size_t buffer_size = GetConsumerSharedMemoryBufferSize(consumer_type); | |
| 213 if (buffer_size == 0) | |
| 214 return NULL; | |
| 215 | |
| 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; | |
| 223 } | |
| 224 } | |
| 225 LOG(ERROR) << "Failed to initialize shared memory"; | |
| 226 return NULL; | |
| 227 } | |
| 228 | |
| 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; | |
| 234 } | |
| 235 | |
| 236 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const { | |
| 237 return polling_thread_ ? polling_thread_->message_loop() : NULL; | |
| 238 } | |
| 239 | |
| 240 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const { | |
| 241 return polling_thread_ ? polling_thread_->IsTimerRunning() : false; | |
| 242 } | |
| 243 | |
| 244 | |
| 245 } // namespace content | |
| OLD | NEW |