• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetConsumerSharedMemoryBufferSize(ConsumerType consumer_type)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 
GetConsumersBitmask() const41   unsigned GetConsumersBitmask() const { return consumers_bitmask_; }
IsTimerRunning() const42   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 
PollingThread(const char * name,DataFetcherSharedMemoryBase * fetcher)57 DataFetcherSharedMemoryBase::PollingThread::PollingThread(
58     const char* name, DataFetcherSharedMemoryBase* fetcher)
59     : base::Thread(name),
60       consumers_bitmask_(0),
61       fetcher_(fetcher) {
62 }
63 
~PollingThread()64 DataFetcherSharedMemoryBase::PollingThread::~PollingThread() {
65 }
66 
AddConsumer(ConsumerType consumer_type,void * buffer)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 
RemoveConsumer(ConsumerType consumer_type)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 
DoPoll()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 
DataFetcherSharedMemoryBase()103 DataFetcherSharedMemoryBase::DataFetcherSharedMemoryBase()
104     : started_consumers_(0) {
105 }
106 
~DataFetcherSharedMemoryBase()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 
StartFetchingDeviceData(ConsumerType consumer_type)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 
StopFetchingDeviceData(ConsumerType consumer_type)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
GetSharedMemoryHandleForProcess(ConsumerType consumer_type,base::ProcessHandle process)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 
InitAndStartPollingThreadIfNecessary()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 
Fetch(unsigned consumer_bitmask)193 void DataFetcherSharedMemoryBase::Fetch(unsigned consumer_bitmask) {
194   NOTIMPLEMENTED();
195 }
196 
197 DataFetcherSharedMemoryBase::FetcherType
GetType() const198 DataFetcherSharedMemoryBase::GetType() const {
199   return FETCHER_TYPE_DEFAULT;
200 }
201 
GetInterval() const202 base::TimeDelta DataFetcherSharedMemoryBase::GetInterval() const {
203   return base::TimeDelta::FromMilliseconds(kInertialSensorIntervalMillis);
204 }
205 
GetSharedMemory(ConsumerType consumer_type)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 
GetSharedMemoryBuffer(ConsumerType consumer_type)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 
GetPollingMessageLoop() const236 base::MessageLoop* DataFetcherSharedMemoryBase::GetPollingMessageLoop() const {
237   return polling_thread_ ? polling_thread_->message_loop() : NULL;
238 }
239 
IsPollingTimerRunningForTesting() const240 bool DataFetcherSharedMemoryBase::IsPollingTimerRunningForTesting() const {
241   return polling_thread_ ? polling_thread_->IsTimerRunning() : false;
242 }
243 
244 
245 }  // namespace content
246