15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PPAPI_SHARED_IMPL_PROXY_LOCK_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PPAPI_SHARED_IMPL_PROXY_LOCK_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
1158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/threading/thread_checker.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ppapi/shared_impl/ppapi_shared_export.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Lock;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace content {
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)class HostGlobals;
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ppapi {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the one lock to rule them all for the ppapi proxy. All PPB interface
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions that need to be synchronized should lock this lock on entry. This
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is normally accomplished by using an appropriate Enter RAII object at the
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// beginning of each thunk function.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(dmichael): If this turns out to be too slow and contentious, we'll want
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to use multiple locks. E.g., one for the var tracker, one for the resource
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tracker, etc.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PPAPI_SHARED_EXPORT ProxyLock {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Return the global ProxyLock. Normally, you should not access this
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // directly but instead use ProxyAutoLock or ProxyAutoUnlock. But sometimes
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // you need access to the ProxyLock, for example to create a condition
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // variable.
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static base::Lock* Get();
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Acquire the proxy lock. If it is currently held by another thread, block
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until it is available. If the lock has not been set using the 'Set' method,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this operation does nothing. That is the normal case for the host side;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // see PluginResourceTracker for where the lock gets set for the out-of-
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process plugin case.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Acquire();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Relinquish the proxy lock. If the lock has not been set, this does nothing.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Release();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assert that the lock is owned by the current thread (in the plugin
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process). Does nothing when running in-process (or in the host process).
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void AssertAcquired();
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static void AssertAcquiredDebugOnly() {
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifndef NDEBUG
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AssertAcquired();
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We have some unit tests where one thread pretends to be the host and one
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // pretends to be the plugin. This allows the lock to do nothing on only one
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // thread to support these tests. See TwoWayTest for more information.
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static void DisableLockingOnThreadForTest();
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Enables locking on the current thread. Although locking is enabled by
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // default, unit tests that rely on the lock being enabled should *still*
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // call this, since a previous test may have disabled locking.
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static void EnableLockingOnThreadForTest();
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  friend class content::HostGlobals;
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // On the host side, we do not lock. This must be called at most once at
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // startup, before other threads that may access the ProxyLock have had a
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // chance to run.
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  static void DisableLocking();
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(ProxyLock);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A simple RAII class for locking the PPAPI proxy lock on entry and releasing
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on exit. This is for simple interfaces that don't use the 'thunk' system,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// such as PPB_Var and PPB_Core.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyAutoLock {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProxyAutoLock() { ProxyLock::Acquire(); }
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ~ProxyAutoLock() { ProxyLock::Release(); }
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ProxyAutoLock);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The inverse of the above; unlock on construction, lock on destruction. This
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is useful for calling out to the plugin, when we need to unlock but ensure
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that we re-acquire the lock when the plugin is returns or raises an
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// exception.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyAutoUnlock {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ProxyAutoUnlock() { ProxyLock::Release(); }
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ~ProxyAutoUnlock() { ProxyLock::Acquire(); }
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ProxyAutoUnlock);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A set of function template overloads for invoking a function pointer while
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ProxyLock is unlocked. This assumes that the luck is held.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CallWhileUnlocked unlocks the ProxyLock just before invoking the given
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function. The lock is immediately re-acquired when the invoked function
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function returns. CallWhileUnlocked returns whatever the given function
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returned.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Example usage:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   *result = CallWhileUnlocked(ppp_input_event_impl_->HandleInputEvent,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               instance,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                               resource->pp_resource());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class ReturnType>
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ReturnType CallWhileUnlocked(ReturnType (*function)()) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoUnlock unlock;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function();
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Note we use 2 types for the params, even though for the most part we expect
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// A1 to match P1. We let the compiler determine if P1 can convert safely to
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// A1. This allows callers to avoid having to do things like
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// const_cast to add const.
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <class ReturnType, class A1, class P1>
1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciReturnType CallWhileUnlocked(ReturnType (*function)(A1), const P1& p1) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoUnlock unlock;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function(p1);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <class ReturnType, class A1, class A2, class P1, class P2>
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciReturnType CallWhileUnlocked(ReturnType (*function)(A1, A2),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P1& p1,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P2& p2) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoUnlock unlock;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function(p1, p2);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <class ReturnType, class A1, class A2, class A3, class P1, class P2,
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          class P3>
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciReturnType CallWhileUnlocked(ReturnType (*function)(A1, A2, A3),
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P1& p1,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P2& p2,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P3& p3) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoUnlock unlock;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function(p1, p2, p3);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <class ReturnType, class A1, class A2, class A3, class A4, class P1,
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          class P2, class P3, class P4>
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciReturnType CallWhileUnlocked(ReturnType (*function)(A1, A2, A3, A4),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P1& p1,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P2& p2,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P3& p3,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P4& p4) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoUnlock unlock;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function(p1, p2, p3, p4);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <class ReturnType, class A1, class A2, class A3, class A4, class A5,
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          class P1, class P2, class P3, class P4, class P5>
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciReturnType CallWhileUnlocked(ReturnType (*function)(A1, A2, A3, A4, A5),
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P1& p1,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P2& p2,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P3& p3,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P4& p4,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const P5& p5) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyAutoUnlock unlock;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function(p1, p2, p3, p4, p5);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PPAPI_SHARED_EXPORT CallWhileUnlocked(const base::Closure& closure);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochnamespace internal {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochtemplate <typename RunType>
17158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochclass RunWhileLockedHelper;
17258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
17358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochtemplate <>
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class RunWhileLockedHelper<void()> {
17558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch public:
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef base::Callback<void()> CallbackType;
17758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  explicit RunWhileLockedHelper(const CallbackType& callback)
17858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      : callback_(new CallbackType(callback)) {
17958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    // Copying |callback| may adjust reference counts for bound Vars or
18058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    // Resources; we should have the lock already.
18158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyLock::AssertAcquired();
18258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    // CallWhileLocked and destruction might happen on a different thread from
18358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    // creation.
18458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    thread_checker_.DetachFromThread();
18558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
18658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  void CallWhileLocked() {
18758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    // Bind thread_checker_ to this thread so we can check in the destructor.
18858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
18958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyAutoLock lock;
19058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    {
19158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      // Use a scope and local Callback to ensure that the callback is cleared
19258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      // before the lock is released, even in the unlikely event that Run()
19358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      // throws an exception.
19458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      scoped_ptr<CallbackType> temp_callback(callback_.Pass());
19558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      temp_callback->Run();
19658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    }
19758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
19858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ~RunWhileLockedHelper() {
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Check that the Callback is destroyed on the same thread as where
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // CallWhileLocked happened (if CallWhileLocked happened).
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Here we read callback_ without the lock. This is why the callback must be
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // destroyed on the same thread where it runs. There are 2 cases where
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // callback_ will be NULL:
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //   1) This is the original RunWhileLockedHelper that RunWhileLocked
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      created. When it was copied somewhere else (e.g., to a MessageLoop
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      queue), callback_ was passed to the new copy, and the original
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      RunWhileLockedHelper's callback_ was set to NULL (since scoped_ptrs
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      only ever have 1 owner). In this case, we don't want to acquire the
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      lock, because we already have it.
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //   2) callback_ has already been run via CallWhileLocked. In this case,
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      there's no need to acquire the lock, because we don't touch any
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    //      shared data.
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (callback_) {
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // If the callback was not run, we still need to have the lock when we
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // destroy the callback in case it had a Resource bound to it. This
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // ensures that the Resource's destructor is invoked only with the lock
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // held.
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      //
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Also: Resource and Var inherit RefCounted (not ThreadSafeRefCounted),
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // and these callbacks need to be usable on any thread. So we need to lock
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // when releasing the callback to avoid ref counting races.
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ProxyAutoLock lock;
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      callback_.reset();
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch private:
23058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  scoped_ptr<CallbackType> callback_;
23158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
23258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  // Used to ensure that the Callback is run and deleted on the same thread.
23358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  base::ThreadChecker thread_checker_;
23458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch};
23558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
23658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochtemplate <typename P1>
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class RunWhileLockedHelper<void(P1)> {
23858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch public:
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef base::Callback<void(P1)> CallbackType;
24058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  explicit RunWhileLockedHelper(const CallbackType& callback)
24158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      : callback_(new CallbackType(callback)) {
24258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyLock::AssertAcquired();
24358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    thread_checker_.DetachFromThread();
24458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
24558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  void CallWhileLocked(P1 p1) {
24658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
24758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyAutoLock lock;
24858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    {
24958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      scoped_ptr<CallbackType> temp_callback(callback_.Pass());
25058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      temp_callback->Run(p1);
25158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    }
25258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ~RunWhileLockedHelper() {
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (callback_) {
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ProxyAutoLock lock;
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      callback_.reset();
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
26158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch private:
26258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  scoped_ptr<CallbackType> callback_;
26358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  base::ThreadChecker thread_checker_;
26458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch};
26558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
26658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochtemplate <typename P1, typename P2>
267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class RunWhileLockedHelper<void(P1, P2)> {
26858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch public:
269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef base::Callback<void(P1, P2)> CallbackType;
27058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  explicit RunWhileLockedHelper(const CallbackType& callback)
27158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      : callback_(new CallbackType(callback)) {
27258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyLock::AssertAcquired();
27358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    thread_checker_.DetachFromThread();
27458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
27558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  void CallWhileLocked(P1 p1, P2 p2) {
27658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
27758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyAutoLock lock;
27858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    {
27958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      scoped_ptr<CallbackType> temp_callback(callback_.Pass());
28058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      temp_callback->Run(p1, p2);
28158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    }
28258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ~RunWhileLockedHelper() {
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (callback_) {
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ProxyAutoLock lock;
287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      callback_.reset();
288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
29158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch private:
29258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  scoped_ptr<CallbackType> callback_;
29358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  base::ThreadChecker thread_checker_;
29458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch};
29558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
29658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochtemplate <typename P1, typename P2, typename P3>
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class RunWhileLockedHelper<void(P1, P2, P3)> {
29858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch public:
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef base::Callback<void(P1, P2, P3)> CallbackType;
30058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  explicit RunWhileLockedHelper(const CallbackType& callback)
30158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      : callback_(new CallbackType(callback)) {
30258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyLock::AssertAcquired();
30358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    thread_checker_.DetachFromThread();
30458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
30558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  void CallWhileLocked(P1 p1, P2 p2, P3 p3) {
30658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    DCHECK(thread_checker_.CalledOnValidThread());
30758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    ProxyAutoLock lock;
30858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    {
30958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      scoped_ptr<CallbackType> temp_callback(callback_.Pass());
31058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      temp_callback->Run(p1, p2, p3);
31158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    }
31258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  }
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ~RunWhileLockedHelper() {
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (callback_) {
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ProxyAutoLock lock;
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      callback_.reset();
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
32158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch private:
32258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  scoped_ptr<CallbackType> callback_;
32358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  base::ThreadChecker thread_checker_;
32458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch};
32558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
32658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}  // namespace internal
32758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
32858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// RunWhileLocked wraps the given Callback in a new Callback that, when invoked:
32958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch//  1) Locks the ProxyLock.
33058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch//  2) Runs the original Callback (forwarding arguments, if any).
33158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch//  3) Clears the original Callback (while the lock is held).
33258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch//  4) Unlocks the ProxyLock.
33358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// Note that it's important that the callback is cleared in step (3), in case
33458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// clearing the Callback causes a destructor (e.g., for a Resource) to run,
33558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// which should hold the ProxyLock to avoid data races.
33658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch//
33758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// This is for cases where you want to run a task or store a Callback, but you
33858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// want to ensure that the ProxyLock is acquired for the duration of the task
33958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// that the Callback runs.
34058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// EXAMPLE USAGE:
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   GetMainThreadMessageLoop()->PostDelayedTask(
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     FROM_HERE,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     RunWhileLocked(base::Bind(&CallbackWrapper, callback, result)),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     delay_in_ms);
34558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch//
34658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// In normal usage like the above, this all should "just work". However, if you
34758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// do something unusual, you may get a runtime crash due to deadlock. Here are
34858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// the ways that the returned Callback must be used to avoid a deadlock:
34958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// (1) copied to another Callback. After that, the original callback can be
35058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// destroyed with or without the proxy lock acquired, while the newly assigned
35158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// callback has to conform to these same restrictions. Or
35258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// (2) run without proxy lock acquired (e.g., being posted to a MessageLoop
35358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// and run there). The callback must be destroyed on the same thread where it
35458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// was run (but can be destroyed with or without the proxy lock acquired). Or
35558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch// (3) destroyed without the proxy lock acquired.
35658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochtemplate <class FunctionType>
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)inline base::Callback<FunctionType> RunWhileLocked(
358a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const base::Callback<FunctionType>& callback) {
35958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  internal::RunWhileLockedHelper<FunctionType>* helper =
36058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      new internal::RunWhileLockedHelper<FunctionType>(callback);
36158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  return base::Bind(
36258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      &internal::RunWhileLockedHelper<FunctionType>::CallWhileLocked,
36358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch      base::Owned(helper));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ppapi
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // PPAPI_SHARED_IMPL_PROXY_LOCK_H_
369