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 #ifndef PPAPI_SHARED_IMPL_PROXY_LOCK_H_ | 5 #ifndef PPAPI_SHARED_IMPL_PROXY_LOCK_H_ |
6 #define PPAPI_SHARED_IMPL_PROXY_LOCK_H_ | 6 #define PPAPI_SHARED_IMPL_PROXY_LOCK_H_ |
7 | 7 |
8 #include <memory> | 8 #include <memory> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 // CallWhileLocked and destruction might happen on a different thread from | 184 // CallWhileLocked and destruction might happen on a different thread from |
185 // creation. | 185 // creation. |
186 thread_checker_.DetachFromThread(); | 186 thread_checker_.DetachFromThread(); |
187 } | 187 } |
188 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr) { | 188 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr) { |
189 // Bind thread_checker_ to this thread so we can check in the destructor. | 189 // Bind thread_checker_ to this thread so we can check in the destructor. |
190 // *If* the callback gets invoked, it's important that RunWhileLockedHelper | 190 // *If* the callback gets invoked, it's important that RunWhileLockedHelper |
191 // is destroyed on the same thread (see the comments in the destructor). | 191 // is destroyed on the same thread (see the comments in the destructor). |
192 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 192 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
193 ProxyAutoLock lock; | 193 ProxyAutoLock lock; |
| 194 |
| 195 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 196 // |lock| above protects the access to Resource instances. |
| 197 base::ScopedAllowCrossThreadRefCountAccess |
| 198 allow_cross_thread_ref_count_access; |
| 199 |
194 { | 200 { |
195 // Use a scope and local Callback to ensure that the callback is cleared | 201 // Use a scope and local Callback to ensure that the callback is cleared |
196 // before the lock is released, even in the unlikely event that Run() | 202 // before the lock is released, even in the unlikely event that Run() |
197 // throws an exception. | 203 // throws an exception. |
198 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 204 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
199 temp_callback->Run(); | 205 temp_callback->Run(); |
200 } | 206 } |
201 } | 207 } |
202 | 208 |
203 ~RunWhileLockedHelper() { | 209 ~RunWhileLockedHelper() { |
(...skipping 11 matching lines...) Expand all Loading... |
215 // we got pushed to has been destroyed (e.g., the thread is shut down and | 221 // we got pushed to has been destroyed (e.g., the thread is shut down and |
216 // its MessageLoop destroyed before all tasks have run.) | 222 // its MessageLoop destroyed before all tasks have run.) |
217 // | 223 // |
218 // We still need to have the lock when we destroy the callback: | 224 // We still need to have the lock when we destroy the callback: |
219 // - Because Resource and Var inherit RefCounted (not | 225 // - Because Resource and Var inherit RefCounted (not |
220 // ThreadSafeRefCounted). | 226 // ThreadSafeRefCounted). |
221 // - Because if the callback owns the last ref to a Resource, it will | 227 // - Because if the callback owns the last ref to a Resource, it will |
222 // call the ResourceTracker and also the Resource's destructor, which | 228 // call the ResourceTracker and also the Resource's destructor, which |
223 // both require the ProxyLock. | 229 // both require the ProxyLock. |
224 ProxyAutoLock lock; | 230 ProxyAutoLock lock; |
| 231 |
| 232 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 233 // |lock| above protects the access to Resource instances. |
| 234 base::ScopedAllowCrossThreadRefCountAccess |
| 235 allow_cross_thread_ref_count_access; |
| 236 |
225 callback_.reset(); | 237 callback_.reset(); |
226 } | 238 } |
227 } | 239 } |
228 | 240 |
229 private: | 241 private: |
230 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 242 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
231 std::unique_ptr<CallbackType> callback_; | 243 std::unique_ptr<CallbackType> callback_; |
232 | 244 |
233 // Used to ensure that the Callback is run and deleted on the same thread. | 245 // Used to ensure that the Callback is run and deleted on the same thread. |
234 base::ThreadChecker thread_checker_; | 246 base::ThreadChecker thread_checker_; |
235 }; | 247 }; |
236 | 248 |
237 template <typename P1> | 249 template <typename P1> |
238 class RunWhileLockedHelper<void(P1)> { | 250 class RunWhileLockedHelper<void(P1)> { |
239 public: | 251 public: |
240 typedef base::Callback<void(P1)> CallbackType; | 252 typedef base::Callback<void(P1)> CallbackType; |
241 explicit RunWhileLockedHelper(const CallbackType& callback) | 253 explicit RunWhileLockedHelper(const CallbackType& callback) |
242 : callback_(new CallbackType(callback)) { | 254 : callback_(new CallbackType(callback)) { |
243 thread_checker_.DetachFromThread(); | 255 thread_checker_.DetachFromThread(); |
244 } | 256 } |
245 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, | 257 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, |
246 P1 p1) { | 258 P1 p1) { |
247 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 259 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
248 ProxyAutoLock lock; | 260 ProxyAutoLock lock; |
| 261 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 262 // |lock| above protects the access to Resource instances. |
| 263 base::ScopedAllowCrossThreadRefCountAccess |
| 264 allow_cross_thread_ref_count_access; |
249 { | 265 { |
250 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 266 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
251 temp_callback->Run(p1); | 267 temp_callback->Run(p1); |
252 } | 268 } |
253 } | 269 } |
254 ~RunWhileLockedHelper() { | 270 ~RunWhileLockedHelper() { |
255 DCHECK(thread_checker_.CalledOnValidThread()); | 271 DCHECK(thread_checker_.CalledOnValidThread()); |
256 if (callback_) { | 272 if (callback_) { |
257 ProxyAutoLock lock; | 273 ProxyAutoLock lock; |
| 274 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 275 // |lock| above protects the access to Resource instances. |
| 276 base::ScopedAllowCrossThreadRefCountAccess |
| 277 allow_cross_thread_ref_count_access; |
258 callback_.reset(); | 278 callback_.reset(); |
259 } | 279 } |
260 } | 280 } |
261 | 281 |
262 private: | 282 private: |
263 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 283 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
264 std::unique_ptr<CallbackType> callback_; | 284 std::unique_ptr<CallbackType> callback_; |
265 base::ThreadChecker thread_checker_; | 285 base::ThreadChecker thread_checker_; |
266 }; | 286 }; |
267 | 287 |
268 template <typename P1, typename P2> | 288 template <typename P1, typename P2> |
269 class RunWhileLockedHelper<void(P1, P2)> { | 289 class RunWhileLockedHelper<void(P1, P2)> { |
270 public: | 290 public: |
271 typedef base::Callback<void(P1, P2)> CallbackType; | 291 typedef base::Callback<void(P1, P2)> CallbackType; |
272 explicit RunWhileLockedHelper(const CallbackType& callback) | 292 explicit RunWhileLockedHelper(const CallbackType& callback) |
273 : callback_(new CallbackType(callback)) { | 293 : callback_(new CallbackType(callback)) { |
274 thread_checker_.DetachFromThread(); | 294 thread_checker_.DetachFromThread(); |
275 } | 295 } |
276 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, | 296 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, |
277 P1 p1, | 297 P1 p1, |
278 P2 p2) { | 298 P2 p2) { |
279 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 299 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
280 ProxyAutoLock lock; | 300 ProxyAutoLock lock; |
| 301 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 302 // |lock| above protects the access to Resource instances. |
| 303 base::ScopedAllowCrossThreadRefCountAccess |
| 304 allow_cross_thread_ref_count_access; |
281 { | 305 { |
282 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 306 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
283 temp_callback->Run(p1, p2); | 307 temp_callback->Run(p1, p2); |
284 } | 308 } |
285 } | 309 } |
286 ~RunWhileLockedHelper() { | 310 ~RunWhileLockedHelper() { |
287 DCHECK(thread_checker_.CalledOnValidThread()); | 311 DCHECK(thread_checker_.CalledOnValidThread()); |
288 if (callback_) { | 312 if (callback_) { |
289 ProxyAutoLock lock; | 313 ProxyAutoLock lock; |
| 314 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 315 // |lock| above protects the access to Resource instances. |
| 316 base::ScopedAllowCrossThreadRefCountAccess |
| 317 allow_cross_thread_ref_count_access; |
290 callback_.reset(); | 318 callback_.reset(); |
291 } | 319 } |
292 } | 320 } |
293 | 321 |
294 private: | 322 private: |
295 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 323 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
296 std::unique_ptr<CallbackType> callback_; | 324 std::unique_ptr<CallbackType> callback_; |
297 base::ThreadChecker thread_checker_; | 325 base::ThreadChecker thread_checker_; |
298 }; | 326 }; |
299 | 327 |
300 template <typename P1, typename P2, typename P3> | 328 template <typename P1, typename P2, typename P3> |
301 class RunWhileLockedHelper<void(P1, P2, P3)> { | 329 class RunWhileLockedHelper<void(P1, P2, P3)> { |
302 public: | 330 public: |
303 typedef base::Callback<void(P1, P2, P3)> CallbackType; | 331 typedef base::Callback<void(P1, P2, P3)> CallbackType; |
304 explicit RunWhileLockedHelper(const CallbackType& callback) | 332 explicit RunWhileLockedHelper(const CallbackType& callback) |
305 : callback_(new CallbackType(callback)) { | 333 : callback_(new CallbackType(callback)) { |
306 thread_checker_.DetachFromThread(); | 334 thread_checker_.DetachFromThread(); |
307 } | 335 } |
308 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, | 336 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, |
309 P1 p1, | 337 P1 p1, |
310 P2 p2, | 338 P2 p2, |
311 P3 p3) { | 339 P3 p3) { |
312 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 340 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
313 ProxyAutoLock lock; | 341 ProxyAutoLock lock; |
| 342 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 343 // |lock| above protects the access to Resource instances. |
| 344 base::ScopedAllowCrossThreadRefCountAccess |
| 345 allow_cross_thread_ref_count_access; |
314 { | 346 { |
315 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 347 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
316 temp_callback->Run(p1, p2, p3); | 348 temp_callback->Run(p1, p2, p3); |
317 } | 349 } |
318 } | 350 } |
319 ~RunWhileLockedHelper() { | 351 ~RunWhileLockedHelper() { |
320 DCHECK(thread_checker_.CalledOnValidThread()); | 352 DCHECK(thread_checker_.CalledOnValidThread()); |
321 if (callback_) { | 353 if (callback_) { |
322 ProxyAutoLock lock; | 354 ProxyAutoLock lock; |
| 355 // Relax the cross-thread access restriction to non-thread-safe RefCount. |
| 356 // |lock| above protects the access to Resource instances. |
| 357 base::ScopedAllowCrossThreadRefCountAccess |
| 358 allow_cross_thread_ref_count_access; |
323 callback_.reset(); | 359 callback_.reset(); |
324 } | 360 } |
325 } | 361 } |
326 | 362 |
327 private: | 363 private: |
328 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 364 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
329 std::unique_ptr<CallbackType> callback_; | 365 std::unique_ptr<CallbackType> callback_; |
330 base::ThreadChecker thread_checker_; | 366 base::ThreadChecker thread_checker_; |
331 }; | 367 }; |
332 | 368 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 std::unique_ptr<internal::RunWhileLockedHelper<FunctionType>> helper( | 417 std::unique_ptr<internal::RunWhileLockedHelper<FunctionType>> helper( |
382 new internal::RunWhileLockedHelper<FunctionType>(callback)); | 418 new internal::RunWhileLockedHelper<FunctionType>(callback)); |
383 return base::Bind( | 419 return base::Bind( |
384 &internal::RunWhileLockedHelper<FunctionType>::CallWhileLocked, | 420 &internal::RunWhileLockedHelper<FunctionType>::CallWhileLocked, |
385 base::Passed(std::move(helper))); | 421 base::Passed(std::move(helper))); |
386 } | 422 } |
387 | 423 |
388 } // namespace ppapi | 424 } // namespace ppapi |
389 | 425 |
390 #endif // PPAPI_SHARED_IMPL_PROXY_LOCK_H_ | 426 #endif // PPAPI_SHARED_IMPL_PROXY_LOCK_H_ |
OLD | NEW |