reland 121901, PPAPI: Add unlocking for PPP calls and callbacks...
"""
With this patch, ppapi_tests pass locally when building with enable_pepper_threading=1. (They didn't before).
TODO: Test more calls off the main thread, make sync completion callbacks work.
BUG=92909
TEST=
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=121901
"""
[email protected]
Review URL: http://codereview.chromium.org/9361065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122001 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/ppapi/shared_impl/ppp_instance_combined.cc b/ppapi/shared_impl/ppp_instance_combined.cc
index d27c2a0..e5b7998 100644
--- a/ppapi/shared_impl/ppp_instance_combined.cc
+++ b/ppapi/shared_impl/ppp_instance_combined.cc
@@ -1,8 +1,9 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
#include "ppapi/shared_impl/ppp_instance_combined.h"
+#include "ppapi/shared_impl/proxy_lock.h"
namespace ppapi {
@@ -26,31 +27,36 @@
uint32_t argc,
const char* argn[],
const char* argv[]) {
- return instance_1_1_.DidCreate(instance, argc, argn, argv);
+ return CallWhileUnlocked(instance_1_1_.DidCreate, instance, argc, argn, argv);
}
void PPP_Instance_Combined::DidDestroy(PP_Instance instance) {
- return instance_1_1_.DidDestroy(instance);
+ return CallWhileUnlocked(instance_1_1_.DidDestroy, instance);
}
void PPP_Instance_Combined::DidChangeView(PP_Instance instance,
PP_Resource view_changed_resource,
const struct PP_Rect* position,
const struct PP_Rect* clip) {
- if (instance_1_1_.DidChangeView)
- instance_1_1_.DidChangeView(instance, view_changed_resource);
- else
- did_change_view_1_0_(instance, position, clip);
+ if (instance_1_1_.DidChangeView) {
+ CallWhileUnlocked(instance_1_1_.DidChangeView,
+ instance,
+ view_changed_resource);
+ } else {
+ CallWhileUnlocked(did_change_view_1_0_, instance, position, clip);
+ }
}
void PPP_Instance_Combined::DidChangeFocus(PP_Instance instance,
PP_Bool has_focus) {
- instance_1_1_.DidChangeFocus(instance, has_focus);
+ CallWhileUnlocked(instance_1_1_.DidChangeFocus, instance, has_focus);
}
PP_Bool PPP_Instance_Combined::HandleDocumentLoad(PP_Instance instance,
PP_Resource url_loader) {
- return instance_1_1_.HandleDocumentLoad(instance, url_loader);
+ return CallWhileUnlocked(instance_1_1_.HandleDocumentLoad,
+ instance,
+ url_loader);
}
} // namespace ppapi
diff --git a/ppapi/shared_impl/proxy_lock.cc b/ppapi/shared_impl/proxy_lock.cc
index 226c51f..7ef652b 100644
--- a/ppapi/shared_impl/proxy_lock.cc
+++ b/ppapi/shared_impl/proxy_lock.cc
@@ -23,4 +23,9 @@
lock->Release();
}
+void CallWhileLocked(const base::Closure& closure) {
+ ProxyAutoLock lock;
+ closure.Run();
+}
+
} // namespace ppapi
diff --git a/ppapi/shared_impl/proxy_lock.h b/ppapi/shared_impl/proxy_lock.h
index c5571f39..20e907be 100644
--- a/ppapi/shared_impl/proxy_lock.h
+++ b/ppapi/shared_impl/proxy_lock.h
@@ -6,6 +6,8 @@
#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"
@@ -34,6 +36,7 @@
// Relinquish the proxy lock. If the lock has not been set, this does nothing.
static void Release();
+ private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ProxyLock);
};
@@ -68,6 +71,78 @@
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);
+}
+
+// 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
diff --git a/ppapi/shared_impl/tracked_callback.cc b/ppapi/shared_impl/tracked_callback.cc
index a49f4ff9..f97acfd 100644
--- a/ppapi/shared_impl/tracked_callback.cc
+++ b/ppapi/shared_impl/tracked_callback.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -12,6 +12,7 @@
#include "ppapi/c/pp_errors.h"
#include "ppapi/shared_impl/callback_tracker.h"
#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
#include "ppapi/shared_impl/resource.h"
namespace ppapi {
@@ -49,8 +50,8 @@
if (!abort_impl_factory_.HasWeakPtrs()) {
MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&TrackedCallback::Abort,
- abort_impl_factory_.GetWeakPtr()));
+ RunWhileLocked(base::Bind(&TrackedCallback::Abort,
+ abort_impl_factory_.GetWeakPtr())));
}
}
}
@@ -69,7 +70,7 @@
// Do this before running the callback in case of reentrancy (which
// shouldn't happen, but avoid strange failures).
MarkAsCompleted();
- PP_RunCompletionCallback(&callback, result);
+ CallWhileUnlocked(PP_RunCompletionCallback, &callback, result);
}
}