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