Make ContentDecryptionModuleResult cross-thread destructible.
So as to handle cross-thread uses of the corresponding
WebContentDecryptionModuleResult (WCDMResult), have WCDMResult
keep a cross-thread persistent (CrossThreadPersistent<>) by
way of its WebPrivatePtr<> reference.
CrossThreadPersistent<> can be destructed on a thread other than
the Oilpan thread creating it; the thread does not have to be
attached to Oilpan.
To control if WebPrivatePtr<> should use a cross-thread persistent
or not, it is now parameterized over an enum controlling which.
The default is to use same-thread persistents. If
WebPrivatePtr<T, AllowCrossThreadDestruction>
is for a ref-counted T, T must derive from ThreadSafeRefCounted<T>.
R=jrummell,xhwang,haraken,tkent
BUG=509588
Review URL: https://codereview.chromium.org/1249913002
git-svn-id: svn://svn.chromium.org/blink/trunk@199421 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h b/third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h
index f06bbec..9d16de99 100644
--- a/third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h
+++ b/third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h
@@ -66,7 +66,7 @@
BLINK_PLATFORM_EXPORT void reset();
BLINK_PLATFORM_EXPORT void assign(const WebContentDecryptionModuleResult&);
- WebPrivatePtr<ContentDecryptionModuleResult> m_impl;
+ WebPrivatePtr<ContentDecryptionModuleResult, WebPrivatePtrDestructionCrossThread> m_impl;
};
} // namespace blink
diff --git a/third_party/WebKit/public/platform/WebPrivatePtr.h b/third_party/WebKit/public/platform/WebPrivatePtr.h
index f62961f..b4b9a28 100644
--- a/third_party/WebKit/public/platform/WebPrivatePtr.h
+++ b/third_party/WebKit/public/platform/WebPrivatePtr.h
@@ -39,8 +39,20 @@
#include "wtf/TypeTraits.h"
#endif
+namespace WTF {
+template<class T> class ThreadSafeRefCounted;
+}
+
namespace blink {
+// By default, the destruction of a WebPrivatePtr<> must happen on the same
+// thread that created it, but can optionally be allowed to happen on
+// another thread.
+enum WebPrivatePtrDestruction {
+ WebPrivatePtrDestructionSameThread,
+ WebPrivatePtrDestructionCrossThread,
+};
+
#if INSIDE_BLINK
enum LifetimeManagementType {
RefCountedLifetime,
@@ -58,16 +70,17 @@
isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime;
};
-template<typename T, LifetimeManagementType lifetime>
+template<typename T, WebPrivatePtrDestruction crossThreadDestruction, LifetimeManagementType lifetime>
class PtrStorageImpl;
-template<typename T>
-class PtrStorageImpl<T, RefCountedLifetime> {
+template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
+class PtrStorageImpl<T, crossThreadDestruction, RefCountedLifetime> {
public:
typedef PassRefPtr<T> BlinkPtrType;
void assign(const BlinkPtrType& val)
{
+ static_assert(crossThreadDestruction == WebPrivatePtrDestructionSameThread || WTF::IsSubclassOfTemplate<T, WTF::ThreadSafeRefCounted>::value, "Cross thread destructible class must derive from ThreadSafeRefCounted<>");
release();
m_ptr = val.leakRef();
}
@@ -99,8 +112,20 @@
T* m_ptr;
};
-template<typename T>
-class PtrStorageImpl<T, GarbageCollectedLifetime> {
+template <typename T, WebPrivatePtrDestruction>
+struct WebPrivatePtrPersistentStorageType {
+public:
+ using Type = Persistent<T>;
+};
+
+template <typename T>
+struct WebPrivatePtrPersistentStorageType<T, WebPrivatePtrDestructionCrossThread> {
+public:
+ using Type = CrossThreadPersistent<T>;
+};
+
+template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
+class PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime> {
public:
void assign(const RawPtr<T>& val)
{
@@ -110,7 +135,7 @@
}
if (!m_handle)
- m_handle = new Persistent<T>();
+ m_handle = new (typename WebPrivatePtrPersistentStorageType<T, crossThreadDestruction>::Type)();
(*m_handle) = val;
}
@@ -136,19 +161,19 @@
}
private:
- Persistent<T>* m_handle;
+ typename WebPrivatePtrPersistentStorageType<T, crossThreadDestruction>::Type* m_handle;
};
-template<typename T>
-class PtrStorageImpl<T, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, GarbageCollectedLifetime> {
+template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
+class PtrStorageImpl<T, crossThreadDestruction, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime> {
public:
- void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); }
+ void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime>::assign(val.get()); }
- void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(other.get()); }
+ void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, crossThreadDestruction, GarbageCollectedLifetime>::assign(other.get()); }
};
-template<typename T>
-class PtrStorage : public PtrStorageImpl<T, LifetimeOf<T>::value> {
+template<typename T, WebPrivatePtrDestruction crossThreadDestruction>
+class PtrStorage : public PtrStorageImpl<T, crossThreadDestruction, LifetimeOf<T>::value> {
public:
static PtrStorage& fromSlot(void** slot)
{
@@ -169,7 +194,6 @@
};
#endif
-
// This class is an implementation detail of the Blink API. It exists to help
// simplify the implementation of Blink interfaces that merely wrap a reference
// counted WebCore class.
@@ -206,7 +230,7 @@
// WebFoo::~WebFoo() { m_private.reset(); }
// void WebFoo::assign(const WebFoo& other) { ... }
//
-template <typename T>
+template <typename T, WebPrivatePtrDestruction crossThreadDestruction = WebPrivatePtrDestructionSameThread>
class WebPrivatePtr {
public:
WebPrivatePtr() : m_storage(0) { }
@@ -231,20 +255,20 @@
void reset() { storage().release(); }
- WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other)
+ WebPrivatePtr& operator=(const WebPrivatePtr& other)
{
storage().assign(other.storage());
return *this;
}
- void moveFrom(WebPrivatePtr<T>& other)
+ void moveFrom(WebPrivatePtr& other)
{
storage().moveFrom(other.storage());
return;
}
template<typename U>
- WebPrivatePtr<T>& operator=(const U& ptr)
+ WebPrivatePtr& operator=(const U& ptr)
{
storage().assign(ptr);
return *this;
@@ -267,8 +291,8 @@
private:
#if INSIDE_BLINK
- PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_storage); }
- const PtrStorage<T>& storage() const { return PtrStorage<T>::fromSlot(&m_storage); }
+ PtrStorage<T, crossThreadDestruction>& storage() { return PtrStorage<T, crossThreadDestruction>::fromSlot(&m_storage); }
+ const PtrStorage<T, crossThreadDestruction>& storage() const { return PtrStorage<T, crossThreadDestruction>::fromSlot(&m_storage); }
#endif
#if !INSIDE_BLINK
@@ -276,11 +300,11 @@
// INSIDE_BLINK is set, but we need to make sure that it is not
// used outside there; the compiler-provided version won't handle reference
// counting properly.
- WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other);
+ WebPrivatePtr& operator=(const WebPrivatePtr& other);
#endif
// Disable the copy constructor; classes that contain a WebPrivatePtr
// should implement their copy constructor using assign().
- WebPrivatePtr(const WebPrivatePtr<T>&);
+ WebPrivatePtr(const WebPrivatePtr&);
void* m_storage;
};