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 <utility> | 9 #include <utility> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/callback.h" | 12 #include "base/callback.h" |
12 #include "base/macros.h" | 13 #include "base/macros.h" |
13 #include "base/memory/scoped_ptr.h" | |
14 #include "base/threading/thread_checker.h" | 14 #include "base/threading/thread_checker.h" |
15 #include "ppapi/shared_impl/ppapi_shared_export.h" | 15 #include "ppapi/shared_impl/ppapi_shared_export.h" |
16 | 16 |
17 namespace base { | 17 namespace base { |
18 class Lock; | 18 class Lock; |
19 } | 19 } |
20 | 20 |
21 namespace content { | 21 namespace content { |
22 class HostGlobals; | 22 class HostGlobals; |
23 } | 23 } |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 template <> | 178 template <> |
179 class RunWhileLockedHelper<void()> { | 179 class RunWhileLockedHelper<void()> { |
180 public: | 180 public: |
181 typedef base::Callback<void()> CallbackType; | 181 typedef base::Callback<void()> CallbackType; |
182 explicit RunWhileLockedHelper(const CallbackType& callback) | 182 explicit RunWhileLockedHelper(const CallbackType& callback) |
183 : callback_(new CallbackType(callback)) { | 183 : callback_(new CallbackType(callback)) { |
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(scoped_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 { | 194 { |
195 // 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 |
196 // 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() |
197 // throws an exception. | 197 // throws an exception. |
198 scoped_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 198 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
199 temp_callback->Run(); | 199 temp_callback->Run(); |
200 } | 200 } |
201 } | 201 } |
202 | 202 |
203 ~RunWhileLockedHelper() { | 203 ~RunWhileLockedHelper() { |
204 // Check that the Callback is destroyed on the same thread as where | 204 // Check that the Callback is destroyed on the same thread as where |
205 // CallWhileLocked happened if CallWhileLocked happened. If we weren't | 205 // CallWhileLocked happened if CallWhileLocked happened. If we weren't |
206 // invoked, thread_checked_ isn't bound to a thread. | 206 // invoked, thread_checked_ isn't bound to a thread. |
207 DCHECK(thread_checker_.CalledOnValidThread()); | 207 DCHECK(thread_checker_.CalledOnValidThread()); |
208 // Here we read callback_ without the lock. This is why the callback must be | 208 // Here we read callback_ without the lock. This is why the callback must be |
(...skipping 12 matching lines...) Expand all Loading... |
221 // - 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 |
222 // call the ResourceTracker and also the Resource's destructor, which | 222 // call the ResourceTracker and also the Resource's destructor, which |
223 // both require the ProxyLock. | 223 // both require the ProxyLock. |
224 ProxyAutoLock lock; | 224 ProxyAutoLock lock; |
225 callback_.reset(); | 225 callback_.reset(); |
226 } | 226 } |
227 } | 227 } |
228 | 228 |
229 private: | 229 private: |
230 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 230 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
231 scoped_ptr<CallbackType> callback_; | 231 std::unique_ptr<CallbackType> callback_; |
232 | 232 |
233 // 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. |
234 base::ThreadChecker thread_checker_; | 234 base::ThreadChecker thread_checker_; |
235 }; | 235 }; |
236 | 236 |
237 template <typename P1> | 237 template <typename P1> |
238 class RunWhileLockedHelper<void(P1)> { | 238 class RunWhileLockedHelper<void(P1)> { |
239 public: | 239 public: |
240 typedef base::Callback<void(P1)> CallbackType; | 240 typedef base::Callback<void(P1)> CallbackType; |
241 explicit RunWhileLockedHelper(const CallbackType& callback) | 241 explicit RunWhileLockedHelper(const CallbackType& callback) |
242 : callback_(new CallbackType(callback)) { | 242 : callback_(new CallbackType(callback)) { |
243 thread_checker_.DetachFromThread(); | 243 thread_checker_.DetachFromThread(); |
244 } | 244 } |
245 static void CallWhileLocked(scoped_ptr<RunWhileLockedHelper> ptr, P1 p1) { | 245 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, |
| 246 P1 p1) { |
246 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 247 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
247 ProxyAutoLock lock; | 248 ProxyAutoLock lock; |
248 { | 249 { |
249 scoped_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 250 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
250 temp_callback->Run(p1); | 251 temp_callback->Run(p1); |
251 } | 252 } |
252 } | 253 } |
253 ~RunWhileLockedHelper() { | 254 ~RunWhileLockedHelper() { |
254 DCHECK(thread_checker_.CalledOnValidThread()); | 255 DCHECK(thread_checker_.CalledOnValidThread()); |
255 if (callback_) { | 256 if (callback_) { |
256 ProxyAutoLock lock; | 257 ProxyAutoLock lock; |
257 callback_.reset(); | 258 callback_.reset(); |
258 } | 259 } |
259 } | 260 } |
260 | 261 |
261 private: | 262 private: |
262 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 263 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
263 scoped_ptr<CallbackType> callback_; | 264 std::unique_ptr<CallbackType> callback_; |
264 base::ThreadChecker thread_checker_; | 265 base::ThreadChecker thread_checker_; |
265 }; | 266 }; |
266 | 267 |
267 template <typename P1, typename P2> | 268 template <typename P1, typename P2> |
268 class RunWhileLockedHelper<void(P1, P2)> { | 269 class RunWhileLockedHelper<void(P1, P2)> { |
269 public: | 270 public: |
270 typedef base::Callback<void(P1, P2)> CallbackType; | 271 typedef base::Callback<void(P1, P2)> CallbackType; |
271 explicit RunWhileLockedHelper(const CallbackType& callback) | 272 explicit RunWhileLockedHelper(const CallbackType& callback) |
272 : callback_(new CallbackType(callback)) { | 273 : callback_(new CallbackType(callback)) { |
273 thread_checker_.DetachFromThread(); | 274 thread_checker_.DetachFromThread(); |
274 } | 275 } |
275 static void CallWhileLocked( | 276 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, |
276 scoped_ptr<RunWhileLockedHelper> ptr, P1 p1, P2 p2) { | 277 P1 p1, |
| 278 P2 p2) { |
277 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 279 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
278 ProxyAutoLock lock; | 280 ProxyAutoLock lock; |
279 { | 281 { |
280 scoped_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 282 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
281 temp_callback->Run(p1, p2); | 283 temp_callback->Run(p1, p2); |
282 } | 284 } |
283 } | 285 } |
284 ~RunWhileLockedHelper() { | 286 ~RunWhileLockedHelper() { |
285 DCHECK(thread_checker_.CalledOnValidThread()); | 287 DCHECK(thread_checker_.CalledOnValidThread()); |
286 if (callback_) { | 288 if (callback_) { |
287 ProxyAutoLock lock; | 289 ProxyAutoLock lock; |
288 callback_.reset(); | 290 callback_.reset(); |
289 } | 291 } |
290 } | 292 } |
291 | 293 |
292 private: | 294 private: |
293 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 295 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
294 scoped_ptr<CallbackType> callback_; | 296 std::unique_ptr<CallbackType> callback_; |
295 base::ThreadChecker thread_checker_; | 297 base::ThreadChecker thread_checker_; |
296 }; | 298 }; |
297 | 299 |
298 template <typename P1, typename P2, typename P3> | 300 template <typename P1, typename P2, typename P3> |
299 class RunWhileLockedHelper<void(P1, P2, P3)> { | 301 class RunWhileLockedHelper<void(P1, P2, P3)> { |
300 public: | 302 public: |
301 typedef base::Callback<void(P1, P2, P3)> CallbackType; | 303 typedef base::Callback<void(P1, P2, P3)> CallbackType; |
302 explicit RunWhileLockedHelper(const CallbackType& callback) | 304 explicit RunWhileLockedHelper(const CallbackType& callback) |
303 : callback_(new CallbackType(callback)) { | 305 : callback_(new CallbackType(callback)) { |
304 thread_checker_.DetachFromThread(); | 306 thread_checker_.DetachFromThread(); |
305 } | 307 } |
306 static void CallWhileLocked( | 308 static void CallWhileLocked(std::unique_ptr<RunWhileLockedHelper> ptr, |
307 scoped_ptr<RunWhileLockedHelper> ptr, P1 p1, P2 p2, P3 p3) { | 309 P1 p1, |
| 310 P2 p2, |
| 311 P3 p3) { |
308 DCHECK(ptr->thread_checker_.CalledOnValidThread()); | 312 DCHECK(ptr->thread_checker_.CalledOnValidThread()); |
309 ProxyAutoLock lock; | 313 ProxyAutoLock lock; |
310 { | 314 { |
311 scoped_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); | 315 std::unique_ptr<CallbackType> temp_callback(std::move(ptr->callback_)); |
312 temp_callback->Run(p1, p2, p3); | 316 temp_callback->Run(p1, p2, p3); |
313 } | 317 } |
314 } | 318 } |
315 ~RunWhileLockedHelper() { | 319 ~RunWhileLockedHelper() { |
316 DCHECK(thread_checker_.CalledOnValidThread()); | 320 DCHECK(thread_checker_.CalledOnValidThread()); |
317 if (callback_) { | 321 if (callback_) { |
318 ProxyAutoLock lock; | 322 ProxyAutoLock lock; |
319 callback_.reset(); | 323 callback_.reset(); |
320 } | 324 } |
321 } | 325 } |
322 | 326 |
323 private: | 327 private: |
324 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); | 328 DISALLOW_COPY_AND_ASSIGN(RunWhileLockedHelper); |
325 scoped_ptr<CallbackType> callback_; | 329 std::unique_ptr<CallbackType> callback_; |
326 base::ThreadChecker thread_checker_; | 330 base::ThreadChecker thread_checker_; |
327 }; | 331 }; |
328 | 332 |
329 } // namespace internal | 333 } // namespace internal |
330 | 334 |
331 // RunWhileLocked wraps the given Callback in a new Callback that, when invoked: | 335 // RunWhileLocked wraps the given Callback in a new Callback that, when invoked: |
332 // 1) Locks the ProxyLock. | 336 // 1) Locks the ProxyLock. |
333 // 2) Runs the original Callback (forwarding arguments, if any). | 337 // 2) Runs the original Callback (forwarding arguments, if any). |
334 // 3) Clears the original Callback (while the lock is held). | 338 // 3) Clears the original Callback (while the lock is held). |
335 // 4) Unlocks the ProxyLock. | 339 // 4) Unlocks the ProxyLock. |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 // some_task_runner.PostTask(FROM_HERE, RunWhileLocked(local_callback)); | 371 // some_task_runner.PostTask(FROM_HERE, RunWhileLocked(local_callback)); |
368 // } | 372 // } |
369 // In this case, since we don't have a lock synchronizing us, it's possible | 373 // In this case, since we don't have a lock synchronizing us, it's possible |
370 // for the callback to run on the other thread before we return and destroy | 374 // for the callback to run on the other thread before we return and destroy |
371 // |local_callback|. The important thing here is that even though the other | 375 // |local_callback|. The important thing here is that even though the other |
372 // thread gets a copy of the callback, the internal "BindState" of the | 376 // thread gets a copy of the callback, the internal "BindState" of the |
373 // callback is refcounted and shared between all copies of the callback. So | 377 // callback is refcounted and shared between all copies of the callback. So |
374 // in that case, if we used base::Owned, we might delete RunWhileLockedHelper | 378 // in that case, if we used base::Owned, we might delete RunWhileLockedHelper |
375 // on this thread, which will violate the RunWhileLockedHelper's assumption | 379 // on this thread, which will violate the RunWhileLockedHelper's assumption |
376 // that it is destroyed on the same thread where it is run. | 380 // that it is destroyed on the same thread where it is run. |
377 scoped_ptr<internal::RunWhileLockedHelper<FunctionType>> helper( | 381 std::unique_ptr<internal::RunWhileLockedHelper<FunctionType>> helper( |
378 new internal::RunWhileLockedHelper<FunctionType>(callback)); | 382 new internal::RunWhileLockedHelper<FunctionType>(callback)); |
379 return base::Bind( | 383 return base::Bind( |
380 &internal::RunWhileLockedHelper<FunctionType>::CallWhileLocked, | 384 &internal::RunWhileLockedHelper<FunctionType>::CallWhileLocked, |
381 base::Passed(std::move(helper))); | 385 base::Passed(std::move(helper))); |
382 } | 386 } |
383 | 387 |
384 } // namespace ppapi | 388 } // namespace ppapi |
385 | 389 |
386 #endif // PPAPI_SHARED_IMPL_PROXY_LOCK_H_ | 390 #endif // PPAPI_SHARED_IMPL_PROXY_LOCK_H_ |
OLD | NEW |