| 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 "content/browser/browser_thread_impl.h" | 5 #include "content/browser/browser_thread_impl.h" |
| 6 | 6 |
| 7 #include "base/atomicops.h" | 7 #include "base/atomicops.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 "Threads must be listed in the reverse order that they die"; | 134 "Threads must be listed in the reverse order that they die"; |
| 135 } | 135 } |
| 136 #endif | 136 #endif |
| 137 } | 137 } |
| 138 | 138 |
| 139 // static | 139 // static |
| 140 bool BrowserThreadImpl::PostTaskHelper( | 140 bool BrowserThreadImpl::PostTaskHelper( |
| 141 BrowserThread::ID identifier, | 141 BrowserThread::ID identifier, |
| 142 const tracked_objects::Location& from_here, | 142 const tracked_objects::Location& from_here, |
| 143 const base::Closure& task, | 143 const base::Closure& task, |
| 144 int64 delay_ms, | 144 base::TimeDelta delay, |
| 145 bool nestable) { | 145 bool nestable) { |
| 146 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 146 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
| 147 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in | 147 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in |
| 148 // order of lifetime. So no need to lock if we know that the other thread | 148 // order of lifetime. So no need to lock if we know that the other thread |
| 149 // outlives this one. | 149 // outlives this one. |
| 150 // Note: since the array is so small, ok to loop instead of creating a map, | 150 // Note: since the array is so small, ok to loop instead of creating a map, |
| 151 // which would require a lock because std::map isn't thread safe, defeating | 151 // which would require a lock because std::map isn't thread safe, defeating |
| 152 // the whole purpose of this optimization. | 152 // the whole purpose of this optimization. |
| 153 BrowserThread::ID current_thread; | 153 BrowserThread::ID current_thread; |
| 154 bool guaranteed_to_outlive_target_thread = | 154 bool guaranteed_to_outlive_target_thread = |
| 155 GetCurrentThreadIdentifier(¤t_thread) && | 155 GetCurrentThreadIdentifier(¤t_thread) && |
| 156 current_thread <= identifier; | 156 current_thread <= identifier; |
| 157 | 157 |
| 158 BrowserThreadGlobals& globals = g_globals.Get(); | 158 BrowserThreadGlobals& globals = g_globals.Get(); |
| 159 if (!guaranteed_to_outlive_target_thread) | 159 if (!guaranteed_to_outlive_target_thread) |
| 160 globals.lock.Acquire(); | 160 globals.lock.Acquire(); |
| 161 | 161 |
| 162 MessageLoop* message_loop = globals.threads[identifier] ? | 162 MessageLoop* message_loop = globals.threads[identifier] ? |
| 163 globals.threads[identifier]->message_loop() : NULL; | 163 globals.threads[identifier]->message_loop() : NULL; |
| 164 if (message_loop) { | 164 if (message_loop) { |
| 165 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); | |
| 166 if (nestable) { | 165 if (nestable) { |
| 167 message_loop->PostDelayedTask(from_here, task, delay); | 166 message_loop->PostDelayedTask(from_here, task, delay); |
| 168 } else { | 167 } else { |
| 169 message_loop->PostNonNestableDelayedTask(from_here, task, delay); | 168 message_loop->PostNonNestableDelayedTask(from_here, task, delay); |
| 170 } | 169 } |
| 171 } | 170 } |
| 172 | 171 |
| 173 if (!guaranteed_to_outlive_target_thread) | 172 if (!guaranteed_to_outlive_target_thread) |
| 174 globals.lock.Release(); | 173 globals.lock.Release(); |
| 175 | 174 |
| 176 return !!message_loop; | 175 return !!message_loop; |
| 177 } | 176 } |
| 178 | 177 |
| 179 // An implementation of MessageLoopProxy to be used in conjunction | 178 // An implementation of MessageLoopProxy to be used in conjunction |
| 180 // with BrowserThread. | 179 // with BrowserThread. |
| 181 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { | 180 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { |
| 182 public: | 181 public: |
| 183 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) | 182 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) |
| 184 : id_(identifier) { | 183 : id_(identifier) { |
| 185 } | 184 } |
| 186 | 185 |
| 187 // MessageLoopProxy implementation. | 186 // MessageLoopProxy implementation. |
| 188 virtual bool PostDelayedTask( | 187 virtual bool PostDelayedTask( |
| 189 const tracked_objects::Location& from_here, | 188 const tracked_objects::Location& from_here, |
| 190 const base::Closure& task, int64 delay_ms) OVERRIDE{ | 189 const base::Closure& task, int64 delay_ms) OVERRIDE { |
| 191 return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms); | 190 return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms); |
| 192 } | 191 } |
| 192 virtual bool PostDelayedTask( |
| 193 const tracked_objects::Location& from_here, |
| 194 const base::Closure& task, base::TimeDelta delay) OVERRIDE { |
| 195 return BrowserThread::PostDelayedTask(id_, from_here, task, delay); |
| 196 } |
| 193 | 197 |
| 194 virtual bool PostNonNestableDelayedTask( | 198 virtual bool PostNonNestableDelayedTask( |
| 195 const tracked_objects::Location& from_here, | 199 const tracked_objects::Location& from_here, |
| 196 const base::Closure& task, | 200 const base::Closure& task, |
| 197 int64 delay_ms) OVERRIDE { | 201 int64 delay_ms) OVERRIDE { |
| 198 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, | 202 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, |
| 199 delay_ms); | 203 delay_ms); |
| 200 } | 204 } |
| 205 virtual bool PostNonNestableDelayedTask( |
| 206 const tracked_objects::Location& from_here, |
| 207 const base::Closure& task, |
| 208 base::TimeDelta delay) OVERRIDE { |
| 209 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, |
| 210 delay); |
| 211 } |
| 201 | 212 |
| 202 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { | 213 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { |
| 203 return BrowserThread::CurrentlyOn(id_); | 214 return BrowserThread::CurrentlyOn(id_); |
| 204 } | 215 } |
| 205 | 216 |
| 206 private: | 217 private: |
| 207 BrowserThread::ID id_; | 218 BrowserThread::ID id_; |
| 208 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); | 219 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); |
| 209 }; | 220 }; |
| 210 | 221 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 270 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
| 260 return globals.threads[identifier] && | 271 return globals.threads[identifier] && |
| 261 globals.threads[identifier]->message_loop(); | 272 globals.threads[identifier]->message_loop(); |
| 262 } | 273 } |
| 263 | 274 |
| 264 // static | 275 // static |
| 265 bool BrowserThread::PostTask(ID identifier, | 276 bool BrowserThread::PostTask(ID identifier, |
| 266 const tracked_objects::Location& from_here, | 277 const tracked_objects::Location& from_here, |
| 267 const base::Closure& task) { | 278 const base::Closure& task) { |
| 268 return BrowserThreadImpl::PostTaskHelper( | 279 return BrowserThreadImpl::PostTaskHelper( |
| 269 identifier, from_here, task, 0, true); | 280 identifier, from_here, task, base::TimeDelta(), true); |
| 270 } | 281 } |
| 271 | 282 |
| 272 // static | 283 // static |
| 273 bool BrowserThread::PostDelayedTask(ID identifier, | 284 bool BrowserThread::PostDelayedTask(ID identifier, |
| 274 const tracked_objects::Location& from_here, | 285 const tracked_objects::Location& from_here, |
| 275 const base::Closure& task, | 286 const base::Closure& task, |
| 276 int64 delay_ms) { | 287 int64 delay_ms) { |
| 277 return BrowserThreadImpl::PostTaskHelper( | 288 return BrowserThreadImpl::PostTaskHelper( |
| 278 identifier, from_here, task, delay_ms, true); | 289 identifier, |
| 290 from_here, |
| 291 task, |
| 292 base::TimeDelta::FromMilliseconds(delay_ms), |
| 293 true); |
| 279 } | 294 } |
| 280 | 295 |
| 281 // static | 296 // static |
| 297 bool BrowserThread::PostDelayedTask(ID identifier, |
| 298 const tracked_objects::Location& from_here, |
| 299 const base::Closure& task, |
| 300 base::TimeDelta delay) { |
| 301 return BrowserThreadImpl::PostTaskHelper( |
| 302 identifier, from_here, task, delay, true); |
| 303 } |
| 304 |
| 305 // static |
| 282 bool BrowserThread::PostNonNestableTask( | 306 bool BrowserThread::PostNonNestableTask( |
| 283 ID identifier, | 307 ID identifier, |
| 284 const tracked_objects::Location& from_here, | 308 const tracked_objects::Location& from_here, |
| 285 const base::Closure& task) { | 309 const base::Closure& task) { |
| 286 return BrowserThreadImpl::PostTaskHelper( | 310 return BrowserThreadImpl::PostTaskHelper( |
| 287 identifier, from_here, task, 0, false); | 311 identifier, from_here, task, base::TimeDelta(), false); |
| 288 } | 312 } |
| 289 | 313 |
| 290 // static | 314 // static |
| 291 bool BrowserThread::PostNonNestableDelayedTask( | 315 bool BrowserThread::PostNonNestableDelayedTask( |
| 292 ID identifier, | 316 ID identifier, |
| 293 const tracked_objects::Location& from_here, | 317 const tracked_objects::Location& from_here, |
| 294 const base::Closure& task, | 318 const base::Closure& task, |
| 295 int64 delay_ms) { | 319 int64 delay_ms) { |
| 296 return BrowserThreadImpl::PostTaskHelper( | 320 return BrowserThreadImpl::PostTaskHelper( |
| 297 identifier, from_here, task, delay_ms, false); | 321 identifier, |
| 322 from_here, |
| 323 task, |
| 324 base::TimeDelta::FromMilliseconds(delay_ms), |
| 325 false); |
| 298 } | 326 } |
| 299 | 327 |
| 300 // static | 328 // static |
| 329 bool BrowserThread::PostNonNestableDelayedTask( |
| 330 ID identifier, |
| 331 const tracked_objects::Location& from_here, |
| 332 const base::Closure& task, |
| 333 base::TimeDelta delay) { |
| 334 return BrowserThreadImpl::PostTaskHelper( |
| 335 identifier, from_here, task, delay, false); |
| 336 } |
| 337 |
| 338 // static |
| 301 bool BrowserThread::PostTaskAndReply( | 339 bool BrowserThread::PostTaskAndReply( |
| 302 ID identifier, | 340 ID identifier, |
| 303 const tracked_objects::Location& from_here, | 341 const tracked_objects::Location& from_here, |
| 304 const base::Closure& task, | 342 const base::Closure& task, |
| 305 const base::Closure& reply) { | 343 const base::Closure& reply) { |
| 306 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here, | 344 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here, |
| 307 task, | 345 task, |
| 308 reply); | 346 reply); |
| 309 } | 347 } |
| 310 | 348 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 AtomicWord* storage = reinterpret_cast<AtomicWord*>( | 392 AtomicWord* storage = reinterpret_cast<AtomicWord*>( |
| 355 &globals.thread_delegates[identifier]); | 393 &globals.thread_delegates[identifier]); |
| 356 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 394 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
| 357 storage, reinterpret_cast<AtomicWord>(delegate)); | 395 storage, reinterpret_cast<AtomicWord>(delegate)); |
| 358 | 396 |
| 359 // This catches registration when previously registered. | 397 // This catches registration when previously registered. |
| 360 DCHECK(!delegate || !old_pointer); | 398 DCHECK(!delegate || !old_pointer); |
| 361 } | 399 } |
| 362 | 400 |
| 363 } // namespace content | 401 } // namespace content |
| OLD | NEW |