| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 CrossThreadHolder_h | 5 #ifndef CrossThreadHolder_h |
| 6 #define CrossThreadHolder_h | 6 #define CrossThreadHolder_h |
| 7 | 7 |
| 8 #include "core/dom/ActiveDOMObject.h" | 8 #include "core/dom/ActiveDOMObject.h" |
| 9 #include "core/dom/CrossThreadTask.h" | 9 #include "core/dom/CrossThreadTask.h" |
| 10 #include "core/dom/ExecutionContext.h" | 10 #include "core/dom/ExecutionContext.h" |
| 11 #include "public/platform/WebTraceLocation.h" | 11 #include "public/platform/WebTraceLocation.h" |
| 12 #include "wtf/Locker.h" | 12 #include "wtf/Locker.h" |
| 13 #include "wtf/OwnPtr.h" | |
| 14 #include "wtf/PassOwnPtr.h" | |
| 15 #include "wtf/PassRefPtr.h" | 13 #include "wtf/PassRefPtr.h" |
| 14 #include "wtf/PtrUtil.h" |
| 16 #include "wtf/RefPtr.h" | 15 #include "wtf/RefPtr.h" |
| 17 #include "wtf/ThreadingPrimitives.h" | 16 #include "wtf/ThreadingPrimitives.h" |
| 17 #include <memory> |
| 18 | 18 |
| 19 namespace blink { | 19 namespace blink { |
| 20 | 20 |
| 21 // CrossThreadHolder<T> provides cross-thread access to |obj| of class T | 21 // CrossThreadHolder<T> provides cross-thread access to |obj| of class T |
| 22 // bound to the thread of |executionContext| where |obj| is created. | 22 // bound to the thread of |executionContext| where |obj| is created. |
| 23 // - CrossThreadHolder<T> can be passed across threads. | 23 // - CrossThreadHolder<T> can be passed across threads. |
| 24 // - |obj|'s methods are called on the thread of |executionContext| | 24 // - |obj|'s methods are called on the thread of |executionContext| |
| 25 // via CrossThreadHolder<T>::postTask(). | 25 // via CrossThreadHolder<T>::postTask(). |
| 26 // - |obj| is destructed on the thread of |executionContext| | 26 // - |obj| is destructed on the thread of |executionContext| |
| 27 // when |executionContext| is stopped or | 27 // when |executionContext| is stopped or |
| 28 // CrossThreadHolder is destructed (earlier of them). | 28 // CrossThreadHolder is destructed (earlier of them). |
| 29 // Note: |obj|'s destruction can be slightly after CrossThreadHolder. | 29 // Note: |obj|'s destruction can be slightly after CrossThreadHolder. |
| 30 template<typename T> | 30 template<typename T> |
| 31 class CrossThreadHolder final { | 31 class CrossThreadHolder final { |
| 32 public: | 32 public: |
| 33 // Must be called on the thread where |obj| is created | 33 // Must be called on the thread where |obj| is created |
| 34 // (== the thread of |executionContext|). | 34 // (== the thread of |executionContext|). |
| 35 // The current thread must be attached to Oilpan. | 35 // The current thread must be attached to Oilpan. |
| 36 static PassOwnPtr<CrossThreadHolder<T>> create(ExecutionContext* executionCo
ntext, PassOwnPtr<T> obj) | 36 static std::unique_ptr<CrossThreadHolder<T>> create(ExecutionContext* execut
ionContext, std::unique_ptr<T> obj) |
| 37 { | 37 { |
| 38 ASSERT(executionContext->isContextThread()); | 38 ASSERT(executionContext->isContextThread()); |
| 39 return adoptPtr(new CrossThreadHolder(executionContext, std::move(obj)))
; | 39 return wrapUnique(new CrossThreadHolder(executionContext, std::move(obj)
)); |
| 40 } | 40 } |
| 41 | 41 |
| 42 // Can be called from any thread. | 42 // Can be called from any thread. |
| 43 // Executes |task| with |obj| and |executionContext| on the thread of | 43 // Executes |task| with |obj| and |executionContext| on the thread of |
| 44 // |executionContext|. | 44 // |executionContext|. |
| 45 // NOTE: |task| might be silently ignored (i.e. not executed) and | 45 // NOTE: |task| might be silently ignored (i.e. not executed) and |
| 46 // destructed (possibly on the calling thread or on the thread of | 46 // destructed (possibly on the calling thread or on the thread of |
| 47 // |executionContext|) when |executionContext| is stopped or | 47 // |executionContext|) when |executionContext| is stopped or |
| 48 // CrossThreadHolder is destructed. | 48 // CrossThreadHolder is destructed. |
| 49 void postTask(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF
::CrossThreadAffinity>> task) | 49 void postTask(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF
::CrossThreadAffinity>> task) |
| 50 { | 50 { |
| 51 MutexLocker locker(m_mutex->mutex()); | 51 MutexLocker locker(m_mutex->mutex()); |
| 52 if (!m_bridge) { | 52 if (!m_bridge) { |
| 53 // The bridge has already disappeared. | 53 // The bridge has already disappeared. |
| 54 return; | 54 return; |
| 55 } | 55 } |
| 56 m_bridge->getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossTh
readTask(&Bridge::runTask, wrapCrossThreadPersistent(m_bridge.get()), passed(std
::move(task)))); | 56 m_bridge->getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossTh
readTask(&Bridge::runTask, wrapCrossThreadPersistent(m_bridge.get()), passed(std
::move(task)))); |
| 57 } | 57 } |
| 58 | 58 |
| 59 ~CrossThreadHolder() | 59 ~CrossThreadHolder() |
| 60 { | 60 { |
| 61 MutexLocker locker(m_mutex->mutex()); | 61 MutexLocker locker(m_mutex->mutex()); |
| 62 clearInternal(); | 62 clearInternal(); |
| 63 } | 63 } |
| 64 | 64 |
| 65 private: | 65 private: |
| 66 // Object graph: | 66 // Object graph: |
| 67 // +------+ +-----------------+ | 67 // +------+ +-----------------+ |
| 68 // T <-OwnPtr- |Bridge| ---------*-------------> |CrossThreadHolder| | 68 // T <-std::unique_ptr- |Bridge| ---------*-------------> |CrossThreadHo
lder| |
| 69 // | | <-CrossThreadPersistent- | | | 69 // | | <-CrossThreadPersistent- | | |
| 70 // +------+ +-----------------+ | 70 // +------+ +-----------------+ |
| 71 // | | | 71 // | | |
| 72 // +--RefPtr--> MutexWrapper <--RefPtr--+ | 72 // +--RefPtr--> MutexWrapper <--RefPtr--+ |
| 73 // The CrossThreadPersistent<T>/T* between CrossThreadHolder and Bridge | 73 // The CrossThreadPersistent<T>/T* between CrossThreadHolder and Bridge |
| 74 // are protected by MutexWrapper | 74 // are protected by MutexWrapper |
| 75 // and cleared when CrossThreadHolder::clearInternal() is called, i.e.: | 75 // and cleared when CrossThreadHolder::clearInternal() is called, i.e.: |
| 76 // [1] when |executionContext| is stopped, or | 76 // [1] when |executionContext| is stopped, or |
| 77 // [2] when CrossThreadHolder is destructed. | 77 // [2] when CrossThreadHolder is destructed. |
| 78 // Then Bridge is shortly garbage collected and T is destructed. | 78 // Then Bridge is shortly garbage collected and T is destructed. |
| 79 | 79 |
| 80 class MutexWrapper : public ThreadSafeRefCounted<MutexWrapper> { | 80 class MutexWrapper : public ThreadSafeRefCounted<MutexWrapper> { |
| 81 public: | 81 public: |
| 82 static PassRefPtr<MutexWrapper> create() { return adoptRef(new MutexWrap
per()); } | 82 static PassRefPtr<MutexWrapper> create() { return adoptRef(new MutexWrap
per()); } |
| 83 Mutex& mutex() { return m_mutex; } | 83 Mutex& mutex() { return m_mutex; } |
| 84 private: | 84 private: |
| 85 MutexWrapper() = default; | 85 MutexWrapper() = default; |
| 86 Mutex m_mutex; | 86 Mutex m_mutex; |
| 87 }; | 87 }; |
| 88 | 88 |
| 89 // All methods except for clearInternal() | 89 // All methods except for clearInternal() |
| 90 // must be called on |executionContext|'s thread. | 90 // must be called on |executionContext|'s thread. |
| 91 class Bridge | 91 class Bridge |
| 92 : public GarbageCollectedFinalized<Bridge> | 92 : public GarbageCollectedFinalized<Bridge> |
| 93 , public ActiveDOMObject { | 93 , public ActiveDOMObject { |
| 94 USING_GARBAGE_COLLECTED_MIXIN(Bridge); | 94 USING_GARBAGE_COLLECTED_MIXIN(Bridge); |
| 95 public: | 95 public: |
| 96 Bridge(ExecutionContext* executionContext, PassOwnPtr<T> obj, PassRefPtr
<MutexWrapper> mutex, CrossThreadHolder* holder) | 96 Bridge(ExecutionContext* executionContext, std::unique_ptr<T> obj, PassR
efPtr<MutexWrapper> mutex, CrossThreadHolder* holder) |
| 97 : ActiveDOMObject(executionContext) | 97 : ActiveDOMObject(executionContext) |
| 98 , m_obj(std::move(obj)) | 98 , m_obj(std::move(obj)) |
| 99 , m_mutex(mutex) | 99 , m_mutex(mutex) |
| 100 , m_holder(holder) | 100 , m_holder(holder) |
| 101 { | 101 { |
| 102 suspendIfNeeded(); | 102 suspendIfNeeded(); |
| 103 } | 103 } |
| 104 | 104 |
| 105 DEFINE_INLINE_TRACE() | 105 DEFINE_INLINE_TRACE() |
| 106 { | 106 { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 ASSERT(!m_holder); | 138 ASSERT(!m_holder); |
| 139 } | 139 } |
| 140 | 140 |
| 141 // We have to destruct |*m_obj| here because destructing |*m_obj| | 141 // We have to destruct |*m_obj| here because destructing |*m_obj| |
| 142 // in ~Bridge() might be too late when |executionContext| is | 142 // in ~Bridge() might be too late when |executionContext| is |
| 143 // stopped. | 143 // stopped. |
| 144 m_obj.reset(); | 144 m_obj.reset(); |
| 145 } | 145 } |
| 146 | 146 |
| 147 | 147 |
| 148 OwnPtr<T> m_obj; | 148 std::unique_ptr<T> m_obj; |
| 149 // All accesses to |m_holder| must be protected by |m_mutex|. | 149 // All accesses to |m_holder| must be protected by |m_mutex|. |
| 150 RefPtr<MutexWrapper> m_mutex; | 150 RefPtr<MutexWrapper> m_mutex; |
| 151 CrossThreadHolder* m_holder; | 151 CrossThreadHolder* m_holder; |
| 152 }; | 152 }; |
| 153 | 153 |
| 154 // Must be protected by |m_mutex|. | 154 // Must be protected by |m_mutex|. |
| 155 void clearInternal() | 155 void clearInternal() |
| 156 { | 156 { |
| 157 if (m_bridge) | 157 if (m_bridge) |
| 158 m_bridge->clearInternal(); | 158 m_bridge->clearInternal(); |
| 159 m_bridge.clear(); | 159 m_bridge.clear(); |
| 160 } | 160 } |
| 161 | 161 |
| 162 CrossThreadHolder(ExecutionContext* executionContext, PassOwnPtr<T> obj) | 162 CrossThreadHolder(ExecutionContext* executionContext, std::unique_ptr<T> obj
) |
| 163 : m_mutex(MutexWrapper::create()) | 163 : m_mutex(MutexWrapper::create()) |
| 164 , m_bridge(new Bridge(executionContext, std::move(obj), m_mutex, this)) | 164 , m_bridge(new Bridge(executionContext, std::move(obj), m_mutex, this)) |
| 165 { | 165 { |
| 166 } | 166 } |
| 167 | 167 |
| 168 RefPtr<MutexWrapper> m_mutex; | 168 RefPtr<MutexWrapper> m_mutex; |
| 169 // |m_bridge| is protected by |m_mutex|. | 169 // |m_bridge| is protected by |m_mutex|. |
| 170 // |m_bridge| is cleared before the thread that allocated |*m_bridge| | 170 // |m_bridge| is cleared before the thread that allocated |*m_bridge| |
| 171 // is stopped. | 171 // is stopped. |
| 172 CrossThreadPersistent<Bridge> m_bridge; | 172 CrossThreadPersistent<Bridge> m_bridge; |
| 173 }; | 173 }; |
| 174 | 174 |
| 175 } // namespace blink | 175 } // namespace blink |
| 176 | 176 |
| 177 #endif // CrossThreadHolder_h | 177 #endif // CrossThreadHolder_h |
| OLD | NEW |