1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef PPAPI_SHARED_IMPL_PROXY_LOCK_H_
#define PPAPI_SHARED_IMPL_PROXY_LOCK_H_
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/callback.h"
#include "ppapi/shared_impl/ppapi_shared_export.h"
namespace base {
class Lock;
}
namespace ppapi {
// This is the one lock to rule them all for the ppapi proxy. All PPB interface
// functions that need to be synchronized should lock this lock on entry. This
// is normally accomplished by using an appropriate Enter RAII object at the
// beginning of each thunk function.
//
// TODO(dmichael): If this turns out to be too slow and contentious, we'll want
// to use multiple locks. E.g., one for the var tracker, one for the resource
// tracker, etc.
class PPAPI_SHARED_EXPORT ProxyLock {
public:
// Acquire the proxy lock. If it is currently held by another thread, block
// until it is available. If the lock has not been set using the 'Set' method,
// this operation does nothing. That is the normal case for the host side;
// see PluginResourceTracker for where the lock gets set for the out-of-
// process plugin case.
static void Acquire();
// Relinquish the proxy lock. If the lock has not been set, this does nothing.
static void Release();
// Assert that the lock is owned by the current thread (in the plugin
// process). Does nothing when running in-process (or in the host process).
static void AssertAcquired();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProxyLock);
};
// A simple RAII class for locking the PPAPI proxy lock on entry and releasing
// on exit. This is for simple interfaces that don't use the 'thunk' system,
// such as PPB_Var and PPB_Core.
class ProxyAutoLock {
public:
ProxyAutoLock() {
ProxyLock::Acquire();
}
~ProxyAutoLock() {
ProxyLock::Release();
}
private:
DISALLOW_COPY_AND_ASSIGN(ProxyAutoLock);
};
// The inverse of the above; unlock on construction, lock on destruction. This
// is useful for calling out to the plugin, when we need to unlock but ensure
// that we re-acquire the lock when the plugin is returns or raises an
// exception.
class ProxyAutoUnlock {
public:
ProxyAutoUnlock() {
ProxyLock::Release();
}
~ProxyAutoUnlock() {
ProxyLock::Acquire();
}
private:
DISALLOW_COPY_AND_ASSIGN(ProxyAutoUnlock);
};
// A set of function template overloads for invoking a function pointer while
// the ProxyLock is unlocked. This assumes that the luck is held.
// CallWhileUnlocked unlocks the ProxyLock just before invoking the given
// function. The lock is immediately re-acquired when the invoked function
// function returns. CallWhileUnlocked returns whatever the given function
// returned.
//
// Example usage:
// *result = CallWhileUnlocked(ppp_input_event_impl_->HandleInputEvent,
// instance,
// resource->pp_resource());
template <class ReturnType>
ReturnType CallWhileUnlocked(ReturnType (*function)()) {
ProxyAutoUnlock unlock;
return function();
}
template <class ReturnType, class P1>
ReturnType CallWhileUnlocked(ReturnType (*function)(P1), const P1& p1) {
ProxyAutoUnlock unlock;
return function(p1);
}
template <class ReturnType, class P1, class P2>
ReturnType CallWhileUnlocked(ReturnType (*function)(P1, P2),
const P1& p1,
const P2& p2) {
ProxyAutoUnlock unlock;
return function(p1, p2);
}
template <class ReturnType, class P1, class P2, class P3>
ReturnType CallWhileUnlocked(ReturnType (*function)(P1, P2, P3),
const P1& p1,
const P2& p2,
const P3& p3) {
ProxyAutoUnlock unlock;
return function(p1, p2, p3);
}
template <class ReturnType, class P1, class P2, class P3, class P4>
ReturnType CallWhileUnlocked(ReturnType (*function)(P1, P2, P3, P4),
const P1& p1,
const P2& p2,
const P3& p3,
const P4& p4) {
ProxyAutoUnlock unlock;
return function(p1, p2, p3, p4);
}
template <class ReturnType, class P1, class P2, class P3, class P4, class P5>
ReturnType CallWhileUnlocked(ReturnType (*function)(P1, P2, P3, P4, P5),
const P1& p1,
const P2& p2,
const P3& p3,
const P4& p4,
const P5& p5) {
ProxyAutoUnlock unlock;
return function(p1, p2, p3, p4, p5);
}
void PPAPI_SHARED_EXPORT CallWhileUnlocked(const base::Closure& closure);
// CallWhileLocked locks the ProxyLock and runs the given closure immediately.
// The lock is released when CallWhileLocked returns. This function assumes the
// lock is not held. This is mostly for use in RunWhileLocked; see below.
void PPAPI_SHARED_EXPORT CallWhileLocked(const base::Closure& closure);
// RunWhileLocked binds the given closure with CallWhileLocked and returns the
// new Closure. This is for cases where you want to run a task, but you want to
// ensure that the ProxyLock is acquired for the duration of the task.
// Example usage:
// GetMainThreadMessageLoop()->PostDelayedTask(
// FROM_HERE,
// RunWhileLocked(base::Bind(&CallbackWrapper, callback, result)),
// delay_in_ms);
inline base::Closure RunWhileLocked(const base::Closure& closure) {
return base::Bind(CallWhileLocked, closure);
}
} // namespace ppapi
#endif // PPAPI_SHARED_IMPL_PROXY_LOCK_H_
|