callOnMainThread() should not copy captured lambda variables
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 28 May 2016 05:51:42 +0000 (05:51 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 28 May 2016 05:51:42 +0000 (05:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=158166

Reviewed by Brady Eidson.

Source/WebCore:

callOnMainThread() should not copy captured lambda variables. This
function is usually called cross-thread with a lambda and copying
the lambda (and its captured variables) can lead to thread-safety
issues.

This patch updates callOnMainThread() to take a NoncopyableFunction&&
in parameter instead of a std::function. The call sites of
callOnMainThread() have also been updated to use C++14's lambda
capture with initializer.

* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::putOrAddOnServer):
* Modules/mediastream/MediaDevicesRequest.cpp:
(WebCore::MediaDevicesRequest::didCompletePermissionCheck):
(WebCore::MediaDevicesRequest::didCompleteTrackSourceInfoRequest):
* Modules/mediastream/MediaEndpointPeerConnection.cpp:
(WebCore::MediaEndpointPeerConnection::runTask):
* Modules/mediastream/MediaEndpointPeerConnection.h:
* Modules/mediastream/UserMediaRequest.cpp:
(WebCore::UserMediaRequest::constraintsValidated):
(WebCore::UserMediaRequest::userMediaAccessGranted):
* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::scheduleNodeDeletion):
(WebCore::AudioContext::isPlayingAudioDidChange):
* dom/Document.cpp:
(WebCore::Document::postTask):
(WebCore::Document::pendingTasksTimerFired): Deleted.
* dom/ScriptElement.cpp:
(WebCore::ScriptElement::requestScript):
* fileapi/AsyncFileStream.cpp:
(WebCore::callOnFileThread):
(WebCore::AsyncFileStream::~AsyncFileStream):
(WebCore::AsyncFileStream::perform):
* fileapi/AsyncFileStream.h:
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::registerFileBlobURL):
(WebCore::ThreadableBlobRegistry::registerBlobURL):
(WebCore::ThreadableBlobRegistry::registerBlobURLForSlice):
(WebCore::ThreadableBlobRegistry::blobSize):
(WebCore::ThreadableBlobRegistry::unregisterBlobURL):
(WebCore::ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked): Deleted.
* loader/icon/IconDatabase.cpp:
(WebCore::IconDatabase::dispatchDidImportIconURLForPageURLOnMainThread):
(WebCore::IconDatabase::dispatchDidImportIconDataForPageURLOnMainThread):
* page/ResourceUsageThread.cpp:
(WebCore::ResourceUsageThread::notifyObservers):
(WebCore::ResourceUsageThread::threadBody):
* page/ResourceUsageThread.h:
* page/scrolling/ScrollingThread.cpp:
(WebCore::ScrollingThread::dispatch):
(WebCore::ScrollingThread::dispatchBarrier):
(WebCore::ScrollingThread::dispatchFunctionsFromScrollingThread):
* page/scrolling/ScrollingThread.h:
* page/scrolling/ios/ScrollingTreeIOS.cpp:
(WebCore::ScrollingTreeIOS::invalidate):
(WebCore::ScrollingTreeIOS::scrollingTreeNodeDidScroll):
(WebCore::ScrollingTreeIOS::currentSnapPointIndicesDidChange):
(WebCore::ScrollingTreeIOS::createScrollingTreeNode): Deleted.
* page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
(WebCore::ScrollingTreeFrameScrollingNodeMac::releaseReferencesToScrollerImpsOnTheMainThread):
* platform/MemoryPressureHandler.cpp:
(WebCore::MemoryPressureHandler::releaseMemory):
* platform/audio/ios/MediaSessionManagerIOS.mm:
(-[WebMediaSessionHelper dealloc]):
(-[WebMediaSessionHelper startMonitoringAirPlayRoutes]):
(-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]):
* platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
(WebCore::AudioSourceProviderAVFObjC::prepare):
* platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
(WebCore::MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification):
(WebCore::MediaPlayerPrivateAVFoundation::dispatchNotification):
* platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm:
(-[WebCDMSessionAVFoundationObjCListener observeValueForKeyPath:ofObject:change:context:]):
* platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm:
(-[WebAVOutputDeviceMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
(WebCore::MediaPlayerPrivateAVFoundationObjC::createVideoLayer):
(-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
(-[WebCoreAVFMovieObserver outputSequenceWasFlushed:]):
(-[WebCoreAVFLoaderDelegate resourceLoader:shouldWaitForLoadingOfRequestedResource:]):
(-[WebCoreAVFLoaderDelegate resourceLoader:shouldWaitForResponseToAuthenticationChallenge:]):
(-[WebCoreAVFLoaderDelegate resourceLoader:didCancelLoadingRequest:]):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
(WebCore::CMTimebaseEffectiveRateChangedCallback):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::play):
(WebCore::MediaPlayerPrivateMediaSourceAVFObjC::pause):
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
* platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
(WebCore::MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask):
* platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
(-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]):
(-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]):
(-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]):
(-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]):
(-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]):
(-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]):
(-[WebAVSampleBufferErrorListener observeValueForKeyPath:ofObject:change:context:]):
(-[WebAVSampleBufferErrorListener layerFailedToDecode:]):
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::patternReleaseCallback):
* platform/graphics/cg/PatternCG.cpp:
(WebCore::patternReleaseCallback):
* platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp:
(WebCore::MediaPlayerPrivateMediaFoundation::endCreatedMediaSource):
(WebCore::MediaPlayerPrivateMediaFoundation::endGetEvent):
(WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::processInputNotify):
* platform/mediastream/MediaStreamPrivate.cpp:
(WebCore::MediaStreamPrivate::scheduleDeferredTask):
* platform/mediastream/MediaStreamPrivate.h:
* platform/mediastream/mac/AVMediaCaptureSource.h:
* platform/mediastream/mac/AVMediaCaptureSource.mm:
(WebCore::AVMediaCaptureSource::scheduleDeferredTask):
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::getMediaStreamTrackSources):
* platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
(WebCore::WebAudioSourceProviderAVFObjC::prepare):
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::getMediaStreamTrackSources):
* platform/network/BlobResourceHandle.cpp:
(WebCore::BlobResourceHandle::start):
(WebCore::BlobResourceHandle::notifyFinish):
* platform/network/DataURLDecoder.cpp:
(WebCore::DataURLDecoder::decode):
* platform/network/DataURLDecoder.h:
* platform/network/cocoa/WebCoreNSURLSession.mm:
(-[WebCoreNSURLSession dealloc]):
(-[WebCoreNSURLSessionDataTask cancel]):
(-[WebCoreNSURLSessionDataTask suspend]):
(-[WebCoreNSURLSessionDataTask resume]):
* platform/network/curl/CurlDownload.cpp:
(WebCore::CurlDownload::didReceiveHeader):
(WebCore::CurlDownload::didReceiveData): Deleted.

Source/WebKit:

callOnMainThread() should not copy captured lambda variables. This
function is usually called cross-thread with a lambda and copying
the lambda (and its captured variables) can lead to thread-safety
issues.

This patch updates callOnMainThread() to take a NoncopyableFunction&&
in parameter instead of a std::function. The call sites of
callOnMainThread() have also been updated to use C++14's lambda
capture with initializer.

* Storage/StorageAreaSync.cpp:
(WebCore::StorageAreaSync::deleteEmptyDatabase):
* Storage/StorageSyncManager.cpp:
(WebCore::StorageSyncManager::dispatch):
* Storage/StorageSyncManager.h:
* Storage/StorageThread.cpp:
(WebCore::StorageThread::dispatch):
(WebCore::StorageThread::terminate):
(WebCore::StorageThread::releaseFastMallocFreeMemoryInAllThreads):
* Storage/StorageThread.h:
* Storage/StorageTracker.cpp:
(WebCore::StorageTracker::syncFileSystemAndTrackerDatabase):
(WebCore::StorageTracker::setOriginDetails):

Source/WebKit/mac:

callOnMainThread() should not copy captured lambda variables. This
function is usually called cross-thread with a lambda and copying
the lambda (and its captured variables) can lead to thread-safety
issues.

This patch updates callOnMainThread() to take a NoncopyableFunction&&
in parameter instead of a std::function. The call sites of
callOnMainThread() have also been updated to use C++14's lambda
capture with initializer.

* Storage/WebDatabaseManagerClient.mm:
(DidModifyOriginData::dispatchToMainThread):
(DidModifyOriginData::DidModifyOriginData): Deleted.
* Storage/WebStorageTrackerClient.mm:
(WebStorageTrackerClient::dispatchDidModifyOrigin):

Source/WTF:

callOnMainThread() should not copy captured lambda variables. This
function is usually called cross-thread with a lambda and copying
the lambda (and its captured variables) can lead to thread-safety
issues.

This patch updates callOnMainThread() to take a NoncopyableFunction&&
in parameter instead of a std::function. The call sites of
callOnMainThread() have also been updated to use C++14's lambda
capture with initializer.

* WTF.xcodeproj/project.pbxproj:

* wtf/FunctionDispatcher.h:
* wtf/NoncopyableFunction.h:
- Moved NoncopyableFunction from FunctionDispatcher.h to
  NoncopyableFunction.h.
- Add a new operator=(nullptr_t) operator to NoncopyableFunction to
  match std::function, as one of the call sites needed it.

* wtf/MainThread.cpp:
(WTF::functionQueue):
(WTF::dispatchFunctionsFromMainThread):
(WTF::callOnMainThread):
* wtf/MainThread.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@201482 268f45cc-cd09-0410-ab3c-d52691b4dbfc

61 files changed:
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/FunctionDispatcher.h
Source/WTF/wtf/MainThread.cpp
Source/WTF/wtf/MainThread.h
Source/WTF/wtf/NoncopyableFunction.h [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBTransaction.cpp
Source/WebCore/Modules/mediastream/MediaDevicesRequest.cpp
Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.cpp
Source/WebCore/Modules/mediastream/MediaEndpointPeerConnection.h
Source/WebCore/Modules/mediastream/UserMediaRequest.cpp
Source/WebCore/Modules/webaudio/AudioContext.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/ScriptElement.cpp
Source/WebCore/fileapi/AsyncFileStream.cpp
Source/WebCore/fileapi/AsyncFileStream.h
Source/WebCore/fileapi/ThreadableBlobRegistry.cpp
Source/WebCore/loader/icon/IconDatabase.cpp
Source/WebCore/page/ResourceUsageThread.cpp
Source/WebCore/page/ResourceUsageThread.h
Source/WebCore/page/scrolling/ScrollingThread.cpp
Source/WebCore/page/scrolling/ScrollingThread.h
Source/WebCore/page/scrolling/ios/ScrollingTreeIOS.cpp
Source/WebCore/page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm
Source/WebCore/platform/MemoryPressureHandler.cpp
Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm
Source/WebCore/platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm
Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp
Source/WebCore/platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h
Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm
Source/WebCore/platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm
Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
Source/WebCore/platform/graphics/cg/PatternCG.cpp
Source/WebCore/platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp
Source/WebCore/platform/mediastream/MediaStreamPrivate.cpp
Source/WebCore/platform/mediastream/MediaStreamPrivate.h
Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h
Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm
Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp
Source/WebCore/platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm
Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp
Source/WebCore/platform/network/BlobResourceHandle.cpp
Source/WebCore/platform/network/DataURLDecoder.cpp
Source/WebCore/platform/network/DataURLDecoder.h
Source/WebCore/platform/network/cocoa/WebCoreNSURLSession.mm
Source/WebCore/platform/network/curl/CurlDownload.cpp
Source/WebKit/ChangeLog
Source/WebKit/Storage/StorageAreaSync.cpp
Source/WebKit/Storage/StorageSyncManager.cpp
Source/WebKit/Storage/StorageSyncManager.h
Source/WebKit/Storage/StorageThread.cpp
Source/WebKit/Storage/StorageThread.h
Source/WebKit/Storage/StorageTracker.cpp
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/Storage/WebDatabaseManagerClient.mm
Source/WebKit/mac/Storage/WebStorageTrackerClient.mm

index ca715e4..509a3ea 100644 (file)
@@ -1,3 +1,35 @@
+2016-05-27  Chris Dumez  <cdumez@apple.com>
+
+        callOnMainThread() should not copy captured lambda variables
+        https://bugs.webkit.org/show_bug.cgi?id=158166
+
+        Reviewed by Brady Eidson.
+
+        callOnMainThread() should not copy captured lambda variables. This
+        function is usually called cross-thread with a lambda and copying
+        the lambda (and its captured variables) can lead to thread-safety
+        issues.
+
+        This patch updates callOnMainThread() to take a NoncopyableFunction&&
+        in parameter instead of a std::function. The call sites of
+        callOnMainThread() have also been updated to use C++14's lambda
+        capture with initializer.
+
+        * WTF.xcodeproj/project.pbxproj:
+
+        * wtf/FunctionDispatcher.h:
+        * wtf/NoncopyableFunction.h:
+        - Moved NoncopyableFunction from FunctionDispatcher.h to
+          NoncopyableFunction.h.
+        - Add a new operator=(nullptr_t) operator to NoncopyableFunction to
+          match std::function, as one of the call sites needed it.
+
+        * wtf/MainThread.cpp:
+        (WTF::functionQueue):
+        (WTF::dispatchFunctionsFromMainThread):
+        (WTF::callOnMainThread):
+        * wtf/MainThread.h:
+
 2016-05-27  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         Unreviewed, build fix for JSCOnly port.
index 8ddbda3..b1fba17 100644 (file)
                7E29C33E15FFD79B00516D61 /* ObjcRuntimeExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E29C33D15FFD79B00516D61 /* ObjcRuntimeExtras.h */; };
                8134013815B092FD001FF0B8 /* Base64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8134013615B092FD001FF0B8 /* Base64.cpp */; };
                8134013915B092FD001FF0B8 /* Base64.h in Headers */ = {isa = PBXBuildFile; fileRef = 8134013715B092FD001FF0B8 /* Base64.h */; };
+               83F2BADF1CF9524E003E99C3 /* NoncopyableFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F2BADE1CF9524E003E99C3 /* NoncopyableFunction.h */; };
                83FBA93219DF459700F30ADB /* TypeCasts.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FBA93119DF459700F30ADB /* TypeCasts.h */; };
                86F46F611A2840EE00CCBF22 /* RefCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F46F5F1A2840EE00CCBF22 /* RefCounter.h */; };
                93934BD318A1E8C300D0D6A1 /* StringViewObjC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 93934BD218A1E8C300D0D6A1 /* StringViewObjC.mm */; };
                7E29C33D15FFD79B00516D61 /* ObjcRuntimeExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjcRuntimeExtras.h; sourceTree = "<group>"; };
                8134013615B092FD001FF0B8 /* Base64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base64.cpp; sourceTree = "<group>"; };
                8134013715B092FD001FF0B8 /* Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64.h; sourceTree = "<group>"; };
+               83F2BADE1CF9524E003E99C3 /* NoncopyableFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoncopyableFunction.h; sourceTree = "<group>"; };
                83FBA93119DF459700F30ADB /* TypeCasts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeCasts.h; sourceTree = "<group>"; };
                86F46F5F1A2840EE00CCBF22 /* RefCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCounter.h; sourceTree = "<group>"; };
                93934BD218A1E8C300D0D6A1 /* StringViewObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = StringViewObjC.mm; path = mac/StringViewObjC.mm; sourceTree = "<group>"; };
                                1A3F6BE6174ADA2100B2EEA7 /* NeverDestroyed.h */,
                                0F0D85B317234CB100338210 /* NoLock.h */,
                                A8A472D0151A825B004123FF /* Noncopyable.h */,
+                               83F2BADE1CF9524E003E99C3 /* NoncopyableFunction.h */,
                                A8A472D5151A825B004123FF /* NumberOfCores.cpp */,
                                A8A472D6151A825B004123FF /* NumberOfCores.h */,
                                7E29C33D15FFD79B00516D61 /* ObjcRuntimeExtras.h */,
                                A8A473D9151A825B004123FF /* HashTable.h in Headers */,
                                A8A473DA151A825B004123FF /* HashTraits.h in Headers */,
                                A8A473DB151A825B004123FF /* HexNumber.h in Headers */,
+                               83F2BADF1CF9524E003E99C3 /* NoncopyableFunction.h in Headers */,
                                2684D4361C000D400081D663 /* IndexSparseSet.h in Headers */,
                                A8A473DC151A825B004123FF /* InlineASM.h in Headers */,
                                A70DA0841799F04D00529A9B /* Insertion.h in Headers */,
index ac0e01f..c3a60f0 100644 (file)
 #define FunctionDispatcher_h
 
 #include <functional>
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WTF {
 
-// FIXME: Move this to its own header (e.g. Functional.h).
-// FIXME: We could make this templated to support other lambdas than void() and make this more reusable.
-class NoncopyableFunction {
-public:
-    NoncopyableFunction() = default;
-
-    template<typename CallableType, class = typename std::enable_if<std::is_rvalue_reference<CallableType&&>::value>::type>
-    NoncopyableFunction(CallableType&& callable)
-        : m_callableWrapper(std::make_unique<CallableWrapper<CallableType>>(WTFMove(callable)))
-    {
-    }
-
-    void operator()() const
-    {
-        if (m_callableWrapper)
-            m_callableWrapper->call();
-    }
-
-    explicit operator bool() const { return !!m_callableWrapper; }
-
-    template<typename CallableType, class = typename std::enable_if<std::is_rvalue_reference<CallableType&&>::value>::type>
-    NoncopyableFunction& operator=(CallableType&& callable)
-    {
-        m_callableWrapper = std::make_unique<CallableWrapper<CallableType>>(WTFMove(callable));
-        return *this;
-    }
-
-private:
-    class CallableWrapperBase {
-        WTF_MAKE_FAST_ALLOCATED;
-    public:
-        virtual ~CallableWrapperBase() { }
-
-        virtual void call() = 0;
-    };
-
-    template<typename CallableType>
-    class CallableWrapper final : public CallableWrapperBase {
-    public:
-        explicit CallableWrapper(CallableType&& callable)
-            : m_callable(WTFMove(callable))
-        {
-        }
-
-        CallableWrapper(const CallableWrapper&) = delete;
-        CallableWrapper& operator=(const CallableWrapper&) = delete;
-
-        void call() final { m_callable(); }
-
-    private:
-        CallableType m_callable;
-    };
-
-    std::unique_ptr<CallableWrapperBase> m_callableWrapper;
-};
-
 // FunctionDispatcher is an abstract representation of something that functions can be
 // dispatched to. This can for example be a run loop or a work queue.
 
@@ -103,6 +48,5 @@ protected:
 } // namespace WTF
 
 using WTF::FunctionDispatcher;
-using WTF::NoncopyableFunction;
 
 #endif // FunctionDispatcher_h
index 46555d5..d3f025e 100644 (file)
@@ -47,9 +47,9 @@ static ThreadIdentifier mainThreadIdentifier;
 
 static StaticLock mainThreadFunctionQueueMutex;
 
-static Deque<std::function<void ()>>& functionQueue()
+static Deque<NoncopyableFunction>& functionQueue()
 {
-    static NeverDestroyed<Deque<std::function<void ()>>> functionQueue;
+    static NeverDestroyed<Deque<NoncopyableFunction>> functionQueue;
     return functionQueue;
 }
 
@@ -120,7 +120,7 @@ void dispatchFunctionsFromMainThread()
 
     auto startTime = std::chrono::steady_clock::now();
 
-    std::function<void ()> function;
+    NoncopyableFunction function;
 
     while (true) {
         {
@@ -144,7 +144,7 @@ void dispatchFunctionsFromMainThread()
     }
 }
 
-void callOnMainThread(std::function<void ()> function)
+void callOnMainThread(NoncopyableFunction&& function)
 {
     ASSERT(function);
 
index 20cf1cb..9f5856d 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <functional>
 #include <stdint.h>
+#include <wtf/NoncopyableFunction.h>
 
 namespace WTF {
 
@@ -40,7 +41,7 @@ typedef uint32_t ThreadIdentifier;
 // Must be called from the main thread.
 WTF_EXPORT_PRIVATE void initializeMainThread();
 
-WTF_EXPORT_PRIVATE void callOnMainThread(std::function<void ()>);
+WTF_EXPORT_PRIVATE void callOnMainThread(NoncopyableFunction&&);
 
 #if PLATFORM(COCOA)
 WTF_EXPORT_PRIVATE void callOnWebThreadOrDispatchAsyncOnMainThread(void (^block)());
diff --git a/Source/WTF/wtf/NoncopyableFunction.h b/Source/WTF/wtf/NoncopyableFunction.h
new file mode 100644 (file)
index 0000000..f91860f
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace WTF {
+
+// FIXME: We could make this templated to support other lambdas than void() and make this more reusable.
+class NoncopyableFunction {
+public:
+    NoncopyableFunction() = default;
+
+    template<typename CallableType, class = typename std::enable_if<std::is_rvalue_reference<CallableType&&>::value>::type>
+    NoncopyableFunction(CallableType&& callable)
+        : m_callableWrapper(std::make_unique<CallableWrapper<CallableType>>(WTFMove(callable)))
+    {
+    }
+
+    void operator()() const
+    {
+        if (m_callableWrapper)
+            m_callableWrapper->call();
+    }
+
+    explicit operator bool() const { return !!m_callableWrapper; }
+
+    template<typename CallableType, class = typename std::enable_if<std::is_rvalue_reference<CallableType&&>::value>::type>
+    NoncopyableFunction& operator=(CallableType&& callable)
+    {
+        m_callableWrapper = std::make_unique<CallableWrapper<CallableType>>(WTFMove(callable));
+        return *this;
+    }
+
+    NoncopyableFunction& operator=(std::nullptr_t)
+    {
+        m_callableWrapper = nullptr;
+        return *this;
+    }
+
+private:
+    class CallableWrapperBase {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        virtual ~CallableWrapperBase() { }
+
+        virtual void call() = 0;
+    };
+
+    template<typename CallableType>
+    class CallableWrapper final : public CallableWrapperBase {
+    public:
+        explicit CallableWrapper(CallableType&& callable)
+            : m_callable(WTFMove(callable))
+        {
+        }
+
+        CallableWrapper(const CallableWrapper&) = delete;
+        CallableWrapper& operator=(const CallableWrapper&) = delete;
+
+        void call() final { m_callable(); }
+
+    private:
+        CallableType m_callable;
+    };
+
+    std::unique_ptr<CallableWrapperBase> m_callableWrapper;
+};
+
+} // namespace WTF
+
+using WTF::NoncopyableFunction;
index 413792f..6cbb121 100644 (file)
@@ -1,3 +1,143 @@
+2016-05-27  Chris Dumez  <cdumez@apple.com>
+
+        callOnMainThread() should not copy captured lambda variables
+        https://bugs.webkit.org/show_bug.cgi?id=158166
+
+        Reviewed by Brady Eidson.
+
+        callOnMainThread() should not copy captured lambda variables. This 
+        function is usually called cross-thread with a lambda and copying
+        the lambda (and its captured variables) can lead to thread-safety
+        issues.
+
+        This patch updates callOnMainThread() to take a NoncopyableFunction&&
+        in parameter instead of a std::function. The call sites of
+        callOnMainThread() have also been updated to use C++14's lambda
+        capture with initializer.
+
+        * Modules/indexeddb/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::putOrAddOnServer):
+        * Modules/mediastream/MediaDevicesRequest.cpp:
+        (WebCore::MediaDevicesRequest::didCompletePermissionCheck):
+        (WebCore::MediaDevicesRequest::didCompleteTrackSourceInfoRequest):
+        * Modules/mediastream/MediaEndpointPeerConnection.cpp:
+        (WebCore::MediaEndpointPeerConnection::runTask):
+        * Modules/mediastream/MediaEndpointPeerConnection.h:
+        * Modules/mediastream/UserMediaRequest.cpp:
+        (WebCore::UserMediaRequest::constraintsValidated):
+        (WebCore::UserMediaRequest::userMediaAccessGranted):
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::scheduleNodeDeletion):
+        (WebCore::AudioContext::isPlayingAudioDidChange):
+        * dom/Document.cpp:
+        (WebCore::Document::postTask):
+        (WebCore::Document::pendingTasksTimerFired): Deleted.
+        * dom/ScriptElement.cpp:
+        (WebCore::ScriptElement::requestScript):
+        * fileapi/AsyncFileStream.cpp:
+        (WebCore::callOnFileThread):
+        (WebCore::AsyncFileStream::~AsyncFileStream):
+        (WebCore::AsyncFileStream::perform):
+        * fileapi/AsyncFileStream.h:
+        * fileapi/ThreadableBlobRegistry.cpp:
+        (WebCore::ThreadableBlobRegistry::registerFileBlobURL):
+        (WebCore::ThreadableBlobRegistry::registerBlobURL):
+        (WebCore::ThreadableBlobRegistry::registerBlobURLForSlice):
+        (WebCore::ThreadableBlobRegistry::blobSize):
+        (WebCore::ThreadableBlobRegistry::unregisterBlobURL):
+        (WebCore::ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked): Deleted.
+        * loader/icon/IconDatabase.cpp:
+        (WebCore::IconDatabase::dispatchDidImportIconURLForPageURLOnMainThread):
+        (WebCore::IconDatabase::dispatchDidImportIconDataForPageURLOnMainThread):
+        * page/ResourceUsageThread.cpp:
+        (WebCore::ResourceUsageThread::notifyObservers):
+        (WebCore::ResourceUsageThread::threadBody):
+        * page/ResourceUsageThread.h:
+        * page/scrolling/ScrollingThread.cpp:
+        (WebCore::ScrollingThread::dispatch):
+        (WebCore::ScrollingThread::dispatchBarrier):
+        (WebCore::ScrollingThread::dispatchFunctionsFromScrollingThread):
+        * page/scrolling/ScrollingThread.h:
+        * page/scrolling/ios/ScrollingTreeIOS.cpp:
+        (WebCore::ScrollingTreeIOS::invalidate):
+        (WebCore::ScrollingTreeIOS::scrollingTreeNodeDidScroll):
+        (WebCore::ScrollingTreeIOS::currentSnapPointIndicesDidChange):
+        (WebCore::ScrollingTreeIOS::createScrollingTreeNode): Deleted.
+        * page/scrolling/mac/ScrollingTreeFrameScrollingNodeMac.mm:
+        (WebCore::ScrollingTreeFrameScrollingNodeMac::releaseReferencesToScrollerImpsOnTheMainThread):
+        * platform/MemoryPressureHandler.cpp:
+        (WebCore::MemoryPressureHandler::releaseMemory):
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (-[WebMediaSessionHelper dealloc]):
+        (-[WebMediaSessionHelper startMonitoringAirPlayRoutes]):
+        (-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]):
+        * platform/graphics/avfoundation/AudioSourceProviderAVFObjC.mm:
+        (WebCore::AudioSourceProviderAVFObjC::prepare):
+        * platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp:
+        (WebCore::MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification):
+        (WebCore::MediaPlayerPrivateAVFoundation::dispatchNotification):
+        * platform/graphics/avfoundation/objc/CDMSessionAVFoundationObjC.mm:
+        (-[WebCDMSessionAVFoundationObjCListener observeValueForKeyPath:ofObject:change:context:]):
+        * platform/graphics/avfoundation/objc/MediaPlaybackTargetPickerMac.mm:
+        (-[WebAVOutputDeviceMenuControllerHelper observeValueForKeyPath:ofObject:change:context:]):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm:
+        (WebCore::MediaPlayerPrivateAVFoundationObjC::createVideoLayer):
+        (-[WebCoreAVFMovieObserver legibleOutput:didOutputAttributedStrings:nativeSampleBuffers:forItemTime:]):
+        (-[WebCoreAVFMovieObserver outputSequenceWasFlushed:]):
+        (-[WebCoreAVFLoaderDelegate resourceLoader:shouldWaitForLoadingOfRequestedResource:]):
+        (-[WebCoreAVFLoaderDelegate resourceLoader:shouldWaitForResponseToAuthenticationChallenge:]):
+        (-[WebCoreAVFLoaderDelegate resourceLoader:didCancelLoadingRequest:]):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaSourceAVFObjC.mm:
+        (WebCore::CMTimebaseEffectiveRateChangedCallback):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::play):
+        (WebCore::MediaPlayerPrivateMediaSourceAVFObjC::pause):
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.h:
+        * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+        (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask):
+        * platform/graphics/avfoundation/objc/SourceBufferPrivateAVFObjC.mm:
+        (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:]):
+        (-[WebAVStreamDataParserListener streamDataParser:didParseStreamDataAsAsset:withDiscontinuity:]):
+        (-[WebAVStreamDataParserListener streamDataParser:didFailToParseStreamDataWithError:]):
+        (-[WebAVStreamDataParserListener streamDataParser:didProvideMediaData:forTrackID:mediaType:flags:]):
+        (-[WebAVStreamDataParserListener streamDataParser:didReachEndOfTrackWithTrackID:mediaType:]):
+        (-[WebAVStreamDataParserListener streamDataParser:didProvideContentKeyRequestInitializationData:forTrackID:]):
+        (-[WebAVSampleBufferErrorListener observeValueForKeyPath:ofObject:change:context:]):
+        (-[WebAVSampleBufferErrorListener layerFailedToDecode:]):
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::patternReleaseCallback):
+        * platform/graphics/cg/PatternCG.cpp:
+        (WebCore::patternReleaseCallback):
+        * platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp:
+        (WebCore::MediaPlayerPrivateMediaFoundation::endCreatedMediaSource):
+        (WebCore::MediaPlayerPrivateMediaFoundation::endGetEvent):
+        (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::processInputNotify):
+        * platform/mediastream/MediaStreamPrivate.cpp:
+        (WebCore::MediaStreamPrivate::scheduleDeferredTask):
+        * platform/mediastream/MediaStreamPrivate.h:
+        * platform/mediastream/mac/AVMediaCaptureSource.h:
+        * platform/mediastream/mac/AVMediaCaptureSource.mm:
+        (WebCore::AVMediaCaptureSource::scheduleDeferredTask):
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::getMediaStreamTrackSources):
+        * platform/mediastream/mac/WebAudioSourceProviderAVFObjC.mm:
+        (WebCore::WebAudioSourceProviderAVFObjC::prepare):
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::getMediaStreamTrackSources):
+        * platform/network/BlobResourceHandle.cpp:
+        (WebCore::BlobResourceHandle::start):
+        (WebCore::BlobResourceHandle::notifyFinish):
+        * platform/network/DataURLDecoder.cpp:
+        (WebCore::DataURLDecoder::decode):
+        * platform/network/DataURLDecoder.h:
+        * platform/network/cocoa/WebCoreNSURLSession.mm:
+        (-[WebCoreNSURLSession dealloc]):
+        (-[WebCoreNSURLSessionDataTask cancel]):
+        (-[WebCoreNSURLSessionDataTask suspend]):
+        (-[WebCoreNSURLSessionDataTask resume]):
+        * platform/network/curl/CurlDownload.cpp:
+        (WebCore::CurlDownload::didReceiveHeader):
+        (WebCore::CurlDownload::didReceiveData): Deleted.
+
 2016-05-27  Tim Horton  <timothy_horton@apple.com>
 
         REGRESSION (r190574): Swipe snapshots are always black on iPhone 5
index 48527b9..cd4d372 100644 (file)
@@ -979,7 +979,7 @@ void IDBTransaction::putOrAddOnServer(IDBClient::TransactionOperation& operation
         // If the IDBValue doesn't have any data, then something went wrong writing the blobs to disk.
         // In that case, we cannot successfully store this record, so we callback with an error.
         auto result = IDBResultData::error(protectedOperation->identifier(), { IDBDatabaseException::UnknownError, ASCIILiteral("Error preparing Blob/File data to be stored in object store") });
-        callOnMainThread([protectedThis = WTFMove(protectedThis), this, protectedOperation = WTFMove(protectedOperation), result = WTFMove(result)]() {
+        callOnMainThread([protectedThis = WTFMove(protectedThis), protectedOperation = WTFMove(protectedOperation), result = WTFMove(result)]() {
             protectedOperation->completed(result);
         });
     });
index 1802cc5..228570b 100644 (file)
@@ -92,7 +92,7 @@ void MediaDevicesRequest::didCompletePermissionCheck(const String& salt, bool ca
     m_idHashSalt = salt;
     m_havePersistentPermission = canAccess;
 
-    callOnMainThread([this, permissionCheckProtector] {
+    callOnMainThread([this, permissionCheckProtector = WTFMove(permissionCheckProtector)] {
         RealtimeMediaSourceCenter::singleton().getMediaStreamTrackSources(this);
     });
 }
@@ -160,8 +160,7 @@ void MediaDevicesRequest::didCompleteTrackSourceInfoRequest(const TrackSourceInf
         devices.append(MediaDeviceInfo::create(scriptExecutionContext(), label, id, groupId, deviceType));
     }
 
-    RefPtr<MediaDevicesRequest> protectedThis(this);
-    callOnMainThread([protectedThis, devices] {
+    callOnMainThread([protectedThis = Ref<MediaDevicesRequest>(*this), devices = WTFMove(devices)]() mutable {
         protectedThis->m_promise.resolve(devices);
     });
     m_protector = nullptr;
index 5955260..385c14f 100644 (file)
@@ -95,14 +95,14 @@ MediaEndpointPeerConnection::MediaEndpointPeerConnection(PeerConnectionBackendCl
     m_mediaEndpoint->generateDtlsInfo();
 }
 
-void MediaEndpointPeerConnection::runTask(std::function<void()> task)
+void MediaEndpointPeerConnection::runTask(NoncopyableFunction&& task)
 {
     if (m_dtlsFingerprint.isNull()) {
         // Only one task needs to be deferred since it will hold off any others until completed.
         ASSERT(!m_initialDeferredTask);
-        m_initialDeferredTask = task;
+        m_initialDeferredTask = WTFMove(task);
     } else
-        callOnMainThread(task);
+        callOnMainThread(WTFMove(task));
 }
 
 void MediaEndpointPeerConnection::startRunningTasks()
index dd3ec1a..86b2477 100644 (file)
@@ -37,6 +37,7 @@
 #include "NotImplemented.h"
 #include "PeerConnectionBackend.h"
 #include "RTCSessionDescription.h"
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -77,7 +78,7 @@ public:
     void clearNegotiationNeededState() override { notImplemented(); };
 
 private:
-    void runTask(std::function<void()>);
+    void runTask(NoncopyableFunction&&);
     void startRunningTasks();
 
     void createOfferTask(RTCOfferOptions&, PeerConnection::SessionDescriptionPromise&);
@@ -91,7 +92,7 @@ private:
     PeerConnectionBackendClient* m_client;
     std::unique_ptr<MediaEndpoint> m_mediaEndpoint;
 
-    std::function<void()> m_initialDeferredTask;
+    NoncopyableFunction m_initialDeferredTask;
 
     std::unique_ptr<SDPProcessor> m_sdpProcessor;
 
index 004e4fb..9e5a9c2 100644 (file)
@@ -135,11 +135,10 @@ void UserMediaRequest::constraintsValidated(const Vector<RefPtr<RealtimeMediaSou
     for (auto& videoTrack : videoTracks)
         m_videoDeviceUIDs.append(videoTrack->persistentID());
 
-    RefPtr<UserMediaRequest> protectedThis(this);
-    callOnMainThread([protectedThis] {
+    callOnMainThread([protectedThis = Ref<UserMediaRequest>(*this)]() mutable {
         // 2 - The constraints are valid, ask the user for access to media.
         if (UserMediaController* controller = protectedThis->m_controller)
-            controller->requestUserMediaAccess(*protectedThis.get());
+            controller->requestUserMediaAccess(protectedThis.get());
     });
 }
 
@@ -148,10 +147,9 @@ void UserMediaRequest::userMediaAccessGranted(const String& audioDeviceUID, cons
     m_allowedVideoDeviceUID = videoDeviceUID;
     m_audioDeviceUIDAllowed = audioDeviceUID;
 
-    RefPtr<UserMediaRequest> protectedThis(this);
-    callOnMainThread([protectedThis, audioDeviceUID, videoDeviceUID] {
+    callOnMainThread([protectedThis = Ref<UserMediaRequest>(*this), audioDeviceUID, videoDeviceUID]() mutable {
         // 3 - the user granted access, ask platform to create the media stream descriptors.
-        RealtimeMediaSourceCenter::singleton().createMediaStream(protectedThis.get(), audioDeviceUID, videoDeviceUID);
+        RealtimeMediaSourceCenter::singleton().createMediaStream(protectedThis.ptr(), audioDeviceUID, videoDeviceUID);
     });
 }
 
index 9dcee19..8818085 100644 (file)
@@ -797,8 +797,7 @@ void AudioContext::scheduleNodeDeletion()
 
         m_isDeletionScheduled = true;
 
-        RefPtr<AudioContext> protectedThis(this);
-        callOnMainThread([protectedThis] {
+        callOnMainThread([protectedThis = Ref<AudioContext>(*this)]() mutable {
             protectedThis->deleteMarkedNodes();
         });
     }
@@ -1002,8 +1001,7 @@ void AudioContext::isPlayingAudioDidChange()
 {
     // Make sure to call Document::updateIsPlayingMedia() on the main thread, since
     // we could be on the audio I/O thread here and the call into WebCore could block.
-    RefPtr<AudioContext> protectedThis(this);
-    callOnMainThread([protectedThis] {
+    callOnMainThread([protectedThis = Ref<AudioContext>(*this)] {
         if (protectedThis->document())
             protectedThis->document()->updateIsPlayingMedia();
     });
index ebf6ec3..6c6b31c 100644 (file)
@@ -5386,12 +5386,8 @@ SecurityOrigin* Document::topOrigin() const
 
 void Document::postTask(Task task)
 {
-    Task* taskPtr = std::make_unique<Task>(WTFMove(task)).release();
-    WeakPtr<Document> documentReference(m_weakFactory.createWeakPtr());
-
-    callOnMainThread([=] {
+    callOnMainThread([documentReference = m_weakFactory.createWeakPtr(), task = WTFMove(task)]() mutable {
         ASSERT(isMainThread());
-        std::unique_ptr<Task> task(taskPtr);
 
         Document* document = documentReference.get();
         if (!document)
@@ -5399,9 +5395,9 @@ void Document::postTask(Task task)
 
         Page* page = document->page();
         if ((page && page->defersLoading() && document->activeDOMObjectsAreSuspended()) || !document->m_pendingTasks.isEmpty())
-            document->m_pendingTasks.append(WTFMove(*task.release()));
+            document->m_pendingTasks.append(WTFMove(task));
         else
-            task->performTask(*document);
+            task.performTask(*document);
     });
 }
 
index 2713392..6cb25d9 100644 (file)
@@ -280,8 +280,7 @@ bool ScriptElement::requestScript(const String& sourceUrl)
     if (m_cachedScript)
         return true;
 
-    RefPtr<Element> element = &m_element;
-    callOnMainThread([this, element] {
+    callOnMainThread([this, element = Ref<Element>(m_element)] {
         dispatchErrorEvent();
     });
     return false;
index 0fb9124..f4b70cf 100644 (file)
@@ -39,6 +39,7 @@
 #include <wtf/MainThread.h>
 #include <wtf/MessageQueue.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/NoncopyableFunction.h>
 
 namespace WebCore {
 
@@ -63,12 +64,12 @@ inline AsyncFileStream::Internals::Internals(FileStreamClient& client)
 #endif
 }
 
-static void callOnFileThread(std::function<void()>&& function)
+static void callOnFileThread(NoncopyableFunction&& function)
 {
     ASSERT(isMainThread());
     ASSERT(function);
 
-    static NeverDestroyed<MessageQueue<std::function<void()>>> queue;
+    static NeverDestroyed<MessageQueue<NoncopyableFunction>> queue;
 
     static std::once_flag createFileThreadOnce;
     std::call_once(createFileThreadOnce, [] {
@@ -89,7 +90,7 @@ static void callOnFileThread(std::function<void()>&& function)
         });
     });
 
-    queue.get().append(std::make_unique<std::function<void()>>(WTFMove(function)));
+    queue.get().append(std::make_unique<NoncopyableFunction>(WTFMove(function)));
 }
 
 AsyncFileStream::AsyncFileStream(FileStreamClient& client)
@@ -102,33 +103,28 @@ AsyncFileStream::~AsyncFileStream()
 {
     ASSERT(isMainThread());
 
-    // Release so that we can control the timing of deletion below.
-    auto& internals = *m_internals.release();
-
     // Set flag to prevent client callbacks and also prevent queued operations from starting.
-    internals.destroyed = true;
+    m_internals->destroyed = true;
 
     // Call through file thread and back to main thread to make sure deletion happens
     // after all file thread functions and all main thread functions called from them.
-    callOnFileThread([&internals] {
-        callOnMainThread([&internals] {
-            delete &internals;
+    callOnFileThread([internals = WTFMove(m_internals)]() mutable {
+        callOnMainThread([internals = WTFMove(internals)] {
         });
     });
 }
 
-void AsyncFileStream::perform(std::function<std::function<void(FileStreamClient&)>(FileStream&)> operation)
+void AsyncFileStream::perform(std::function<std::function<void(FileStreamClient&)>(FileStream&)>&& operation)
 {
     auto& internals = *m_internals;
-    callOnFileThread([&internals, operation] {
+    callOnFileThread([&internals, operation = WTFMove(operation)] {
         // Don't do the operation if stop was already called on the main thread. Note that there is
         // a race here, but since skipping the operation is an optimization it's OK that we can't
         // guarantee exactly which operations are skipped. Note that this is also the only reason
         // we use an atomic_bool rather than just a bool for destroyed.
         if (internals.destroyed)
             return;
-        auto mainThreadWork = operation(internals.stream);
-        callOnMainThread([&internals, mainThreadWork] {
+        callOnMainThread([&internals, mainThreadWork = operation(internals.stream)] {
             if (internals.destroyed)
                 return;
             mainThreadWork(internals.client);
index 428f730..ff481a4 100644 (file)
@@ -56,7 +56,7 @@ public:
 
 private:
     void start();
-    void perform(std::function<std::function<void(FileStreamClient&)>(FileStream&)>);
+    void perform(std::function<std::function<void(FileStreamClient&)>(FileStream&)>&&);
 
     struct Internals;
     std::unique_ptr<Internals> m_internals;
index 1000135..c598ac3 100644 (file)
@@ -117,10 +117,8 @@ void ThreadableBlobRegistry::registerFileBlobURL(const URL& url, const String& p
         blobRegistry().registerFileBlobURL(url, BlobDataFileReference::create(path), contentType);
     else {
         // BlobRegistryContext performs an isolated copy of data.
-        BlobRegistryContext* context = new BlobRegistryContext(url, path, contentType);
-        callOnMainThread([context] {
-            std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
-            blobRegistry().registerFileBlobURL(blobRegistryContext->url, BlobDataFileReference::create(blobRegistryContext->path), blobRegistryContext->contentType);
+        callOnMainThread([context = std::make_unique<BlobRegistryContext>(url, path, contentType)] {
+            blobRegistry().registerFileBlobURL(context->url, BlobDataFileReference::create(context->path), context->contentType);
         });
     }
 }
@@ -131,10 +129,8 @@ void ThreadableBlobRegistry::registerBlobURL(const URL& url, Vector<BlobPart> bl
         blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
     else {
         // BlobRegistryContext performs an isolated copy of data.
-        BlobRegistryContext* context = new BlobRegistryContext(url, WTFMove(blobParts), contentType);
-        callOnMainThread([context] {
-            std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
-            blobRegistry().registerBlobURL(blobRegistryContext->url, WTFMove(blobRegistryContext->blobParts), blobRegistryContext->contentType);
+        callOnMainThread([context = std::make_unique<BlobRegistryContext>(url, WTFMove(blobParts), contentType)] {
+            blobRegistry().registerBlobURL(context->url, WTFMove(context->blobParts), context->contentType);
         });
     }
 }
@@ -149,10 +145,8 @@ void ThreadableBlobRegistry::registerBlobURL(SecurityOrigin* origin, const URL&
         blobRegistry().registerBlobURL(url, srcURL);
     else {
         // BlobRegistryContext performs an isolated copy of data.
-        BlobRegistryContext* context = new BlobRegistryContext(url, srcURL);
-        callOnMainThread([context] {
-            std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
-            blobRegistry().registerBlobURL(blobRegistryContext->url, blobRegistryContext->srcURL);
+        callOnMainThread([context = std::make_unique<BlobRegistryContext>(url, srcURL)] {
+            blobRegistry().registerBlobURL(context->url, context->srcURL);
         });
     }
 }
@@ -178,10 +172,8 @@ void ThreadableBlobRegistry::registerBlobURLForSlice(const URL& newURL, const UR
         blobRegistry().registerBlobURLForSlice(newURL, srcURL, start, end);
     else {
         // BlobRegistryContext performs an isolated copy of data.
-        BlobRegistryContext* context = new BlobRegistryContext(newURL, srcURL);
-        callOnMainThread([context, start, end] {
-            std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
-            blobRegistry().registerBlobURLForSlice(blobRegistryContext->url, blobRegistryContext->srcURL, start, end);
+        callOnMainThread([context = std::make_unique<BlobRegistryContext>(newURL, srcURL), start, end] {
+            blobRegistry().registerBlobURLForSlice(context->url, context->srcURL, start, end);
         });
     }
 }
@@ -193,11 +185,9 @@ unsigned long long ThreadableBlobRegistry::blobSize(const URL& url)
         resultSize = blobRegistry().blobSize(url);
     else {
         // BlobRegistryContext performs an isolated copy of data.
-        BlobRegistryContext* context = new BlobRegistryContext(url);
         BinarySemaphore semaphore;
-        callOnMainThread([context, &semaphore, &resultSize] {
-            std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
-            resultSize = blobRegistry().blobSize(blobRegistryContext->url);
+        callOnMainThread([context = std::make_unique<BlobRegistryContext>(url), &semaphore, &resultSize] {
+            resultSize = blobRegistry().blobSize(context->url);
             semaphore.signal();
         });
         semaphore.wait(std::numeric_limits<double>::max());
@@ -214,10 +204,8 @@ void ThreadableBlobRegistry::unregisterBlobURL(const URL& url)
         blobRegistry().unregisterBlobURL(url);
     else {
         // BlobRegistryContext performs an isolated copy of data.
-        BlobRegistryContext* context = new BlobRegistryContext(url);
-        callOnMainThread([context] {
-            std::unique_ptr<BlobRegistryContext> blobRegistryContext(context);
-            blobRegistry().unregisterBlobURL(blobRegistryContext->url);
+        callOnMainThread([context = std::make_unique<BlobRegistryContext>(url)] {
+            blobRegistry().unregisterBlobURL(context->url);
         });
     }
 }
index 6da244e..e1eda5c 100644 (file)
@@ -2090,10 +2090,9 @@ void IconDatabase::dispatchDidImportIconURLForPageURLOnMainThread(const String&
     ASSERT_ICON_SYNC_THREAD();
     ++m_mainThreadCallbackCount;
 
-    String pageURLCopy = pageURL.isolatedCopy();
-    callOnMainThread([this, pageURLCopy] {
+    callOnMainThread([this, pageURL = pageURL.isolatedCopy()] {
         if (m_client)
-            m_client->didImportIconURLForPageURL(pageURLCopy);
+            m_client->didImportIconURLForPageURL(pageURL);
         checkClosedAfterMainThreadCallback();
     });
 }
@@ -2103,10 +2102,9 @@ void IconDatabase::dispatchDidImportIconDataForPageURLOnMainThread(const String&
     ASSERT_ICON_SYNC_THREAD();
     ++m_mainThreadCallbackCount;
 
-    String pageURLCopy = pageURL.isolatedCopy();
-    callOnMainThread([this, pageURLCopy] {
+    callOnMainThread([this, pageURL = pageURL.isolatedCopy()] {
         if (m_client)
-            m_client->didImportIconDataForPageURL(pageURLCopy);
+            m_client->didImportIconDataForPageURL(pageURL);
         checkClosedAfterMainThreadCallback();
     });
 }
index 23500be..ef2a525 100644 (file)
@@ -77,9 +77,9 @@ void ResourceUsageThread::waitUntilObservers()
         m_condition.wait(m_lock);
 }
 
-void ResourceUsageThread::notifyObservers(ResourceUsageData& data)
+void ResourceUsageThread::notifyObservers(ResourceUsageData&& data)
 {
-    callOnMainThread([data]() mutable {
+    callOnMainThread([data = WTFMove(data)]() mutable {
         Vector<std::function<void (const ResourceUsageData&)>> functions;
         
         {
@@ -117,7 +117,7 @@ NO_RETURN void ResourceUsageThread::threadBody()
 
         ResourceUsageData data;
         platformThreadBody(m_vm, data);
-        notifyObservers(data);
+        notifyObservers(WTFMove(data));
 
         auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start);
         auto difference = std::chrono::milliseconds(500) - duration;
index fd2581a..25e4c3d 100644 (file)
@@ -56,7 +56,7 @@ private:
     static ResourceUsageThread& singleton();
 
     void waitUntilObservers();
-    void notifyObservers(ResourceUsageData&);
+    void notifyObservers(ResourceUsageData&&);
 
     void createThreadIfNeeded();
     static void threadCallback(void* scrollingThread);
index 4669a19..35a17b8 100644 (file)
@@ -45,22 +45,22 @@ bool ScrollingThread::isCurrentThread()
     return threadIdentifier && currentThread() == threadIdentifier;
 }
 
-void ScrollingThread::dispatch(std::function<void ()> function)
+void ScrollingThread::dispatch(NoncopyableFunction&& function)
 {
     auto& scrollingThread = ScrollingThread::singleton();
     scrollingThread.createThreadIfNeeded();
 
     {
         std::lock_guard<Lock> lock(scrollingThread.m_functionsMutex);
-        scrollingThread.m_functions.append(function);
+        scrollingThread.m_functions.append(WTFMove(function));
     }
 
     scrollingThread.wakeUpRunLoop();
 }
 
-void ScrollingThread::dispatchBarrier(std::function<void ()> function)
+void ScrollingThread::dispatchBarrier(NoncopyableFunction&& function)
 {
-    dispatch([function]() mutable {
+    dispatch([function = WTFMove(function)]() mutable {
         callOnMainThread(WTFMove(function));
     });
 }
@@ -104,7 +104,7 @@ void ScrollingThread::dispatchFunctionsFromScrollingThread()
 {
     ASSERT(isCurrentThread());
 
-    Vector<std::function<void ()>> functions;
+    Vector<NoncopyableFunction> functions;
     
     {
         std::lock_guard<Lock> lock(m_functionsMutex);
index a709ccd..aaf577b 100644 (file)
@@ -33,6 +33,7 @@
 #include <wtf/Forward.h>
 #include <wtf/Lock.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/Threading.h>
 #include <wtf/Vector.h>
 
@@ -47,11 +48,11 @@ class ScrollingThread {
 
 public:
     static bool isCurrentThread();
-    WEBCORE_EXPORT static void dispatch(std::function<void ()>);
+    WEBCORE_EXPORT static void dispatch(NoncopyableFunction&&);
 
     // Will dispatch the given function on the main thread once all pending functions
     // on the scrolling thread have finished executing. Used for synchronization purposes.
-    WEBCORE_EXPORT static void dispatchBarrier(std::function<void ()>);
+    WEBCORE_EXPORT static void dispatchBarrier(NoncopyableFunction&&);
 
 private:
     friend NeverDestroyed<ScrollingThread>;
@@ -79,7 +80,7 @@ private:
     Lock m_initializeRunLoopMutex;
 
     Lock m_functionsMutex;
-    Vector<std::function<void ()>> m_functions;
+    Vector<NoncopyableFunction> m_functions;
 
 #if PLATFORM(COCOA)
     // FIXME: We should use WebCore::RunLoop here.
index 082bd73..6626ecc 100644 (file)
@@ -67,9 +67,7 @@ void ScrollingTreeIOS::invalidate()
     // Since this can potentially be the last reference to the scrolling coordinator,
     // we need to release it on the main thread since it has member variables (such as timers)
     // that expect to be destroyed from the main thread.
-    ScrollingCoordinator* scrollingCoordinator = m_scrollingCoordinator.release().leakRef();
-    callOnMainThread([scrollingCoordinator] {
-        scrollingCoordinator->deref();
+    callOnMainThread([scrollingCoordinator = WTFMove(m_scrollingCoordinator)] {
     });
 }
 
@@ -86,10 +84,7 @@ void ScrollingTreeIOS::scrollingTreeNodeDidScroll(ScrollingNodeID nodeID, const
     if (nodeID == rootNode()->scrollingNodeID())
         setMainFrameScrollPosition(scrollPosition);
 
-    RefPtr<AsyncScrollingCoordinator> scrollingCoordinator = m_scrollingCoordinator;
-    bool localIsHandlingProgrammaticScroll = isHandlingProgrammaticScroll();
-
-    callOnMainThread([scrollingCoordinator, nodeID, scrollPosition, localIsHandlingProgrammaticScroll, scrollingLayerPositionAction] {
+    callOnMainThread([scrollingCoordinator = m_scrollingCoordinator, nodeID, scrollPosition, localIsHandlingProgrammaticScroll = isHandlingProgrammaticScroll(), scrollingLayerPositionAction] {
         scrollingCoordinator->scheduleUpdateScrollPositionAfterAsyncScroll(nodeID, scrollPosition, localIsHandlingProgrammaticScroll, scrollingLayerPositionAction);
     });
 }
@@ -123,8 +118,7 @@ void ScrollingTreeIOS::currentSnapPointIndicesDidChange(WebCore::ScrollingNodeID
     if (!m_scrollingCoordinator)
         return;
     
-    RefPtr<AsyncScrollingCoordinator> scrollingCoordinator = m_scrollingCoordinator;
-    callOnMainThread([scrollingCoordinator, nodeID, horizontal, vertical] {
+    callOnMainThread([scrollingCoordinator = m_scrollingCoordinator, nodeID, horizontal, vertical] {
         scrollingCoordinator->setActiveScrollSnapIndices(nodeID, horizontal, vertical);
     });
 }
index bd81854..8b3f1cc 100644 (file)
@@ -75,11 +75,7 @@ void ScrollingTreeFrameScrollingNodeMac::releaseReferencesToScrollerImpsOnTheMai
     if (m_verticalScrollerImp || m_horizontalScrollerImp) {
         // FIXME: This is a workaround in place for the time being since NSScrollerImps cannot be deallocated
         // on a non-main thread. rdar://problem/24535055
-        NSScrollerImp *retainedVerticalScrollerImp = m_verticalScrollerImp.leakRef();
-        NSScrollerImp *retainedHorizontalScrollerImp = m_horizontalScrollerImp.leakRef();
-        WTF::callOnMainThread([retainedVerticalScrollerImp, retainedHorizontalScrollerImp] {
-            [retainedVerticalScrollerImp release];
-            [retainedHorizontalScrollerImp release];
+        WTF::callOnMainThread([verticalScrollerImp = WTFMove(m_verticalScrollerImp), horizontalScrollerImp = WTFMove(m_horizontalScrollerImp)] {
         });
     }
 }
index 32eac45..495d8b7 100644 (file)
@@ -172,7 +172,9 @@ void MemoryPressureHandler::releaseMemory(Critical critical, Synchronous synchro
         // FastMalloc has lock-free thread specific caches that can only be cleared from the thread itself.
         WorkerThread::releaseFastMallocFreeMemoryInAllThreads();
 #if ENABLE(ASYNC_SCROLLING) && !PLATFORM(IOS)
-        ScrollingThread::dispatch(WTF::releaseFastMallocFreeMemory);
+        ScrollingThread::dispatch([]() {
+            WTF::releaseFastMallocFreeMemory();
+        });
 #endif
         WTF::releaseFastMallocFreeMemory();
     }
index 12cbcbf..632dc35 100644 (file)
@@ -396,10 +396,7 @@ void MediaSessionManageriOS::applicationWillEnterForeground(bool isSuspendedUnde
     LOG(Media, "-[WebMediaSessionHelper dealloc]");
 
     if (!isMainThread()) {
-        auto volumeView = WTFMove(_volumeView);
-        auto routingController = WTFMove(_airPlayPresenceRoutingController);
-
-        callOnMainThread([volumeView, routingController] () mutable {
+        callOnMainThread([volumeView = WTFMove(_volumeView), routingController = WTFMove(_airPlayPresenceRoutingController)] () mutable {
             LOG(Media, "-[WebMediaSessionHelper dealloc] - dipatched to MainThread");
 
             volumeView.clear();
@@ -435,15 +432,14 @@ void MediaSessionManageriOS::applicationWillEnterForeground(bool isSuspendedUnde
 
     LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes]");
 
-    RetainPtr<WebMediaSessionHelper> strongSelf = self;
-    callOnMainThread([strongSelf] () {
+    callOnMainThread([protectedSelf = RetainPtr<WebMediaSessionHelper>(self)] () {
         LOG(Media, "-[WebMediaSessionHelper startMonitoringAirPlayRoutes] - dipatched to MainThread");
 
-        if (strongSelf->_airPlayPresenceRoutingController)
+        if (protectedSelf->_airPlayPresenceRoutingController)
             return;
 
-        strongSelf->_airPlayPresenceRoutingController = adoptNS([allocMPAVRoutingControllerInstance() initWithName:@"WebCore - HTML media element checking for AirPlay route presence"]);
-        [strongSelf->_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModePresence];
+        protectedSelf->_airPlayPresenceRoutingController = adoptNS([allocMPAVRoutingControllerInstance() initWithName:@"WebCore - HTML media element checking for AirPlay route presence"]);
+        [protectedSelf->_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModePresence];
     });
 }
 
@@ -454,15 +450,14 @@ void MediaSessionManageriOS::applicationWillEnterForeground(bool isSuspendedUnde
 
     LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes]");
 
-    RetainPtr<WebMediaSessionHelper> strongSelf = self;
-    callOnMainThread([strongSelf] () {
+    callOnMainThread([protectedSelf = RetainPtr<WebMediaSessionHelper>(self)] () {
         LOG(Media, "-[WebMediaSessionHelper stopMonitoringAirPlayRoutes] - dipatched to MainThread");
 
-        if (!strongSelf->_airPlayPresenceRoutingController)
+        if (!protectedSelf->_airPlayPresenceRoutingController)
             return;
 
-        [strongSelf->_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
-        strongSelf->_airPlayPresenceRoutingController = nil;
+        [protectedSelf->_airPlayPresenceRoutingController setDiscoveryMode:MPRouteDiscoveryModeDisabled];
+        protectedSelf->_airPlayPresenceRoutingController = nil;
     });
 }
 
index 3d90ded..522aa36 100644 (file)
@@ -323,9 +323,8 @@ void AudioSourceProviderAVFObjC::prepare(CMItemCount maxFrames, const AudioStrea
     memset(m_list.get(), 0, bufferListSize);
     m_list->mNumberBuffers = numberOfChannels;
 
-    RefPtr<AudioSourceProviderAVFObjC> strongThis = this;
-    callOnMainThread([strongThis, numberOfChannels, sampleRate] {
-        strongThis->m_client->setFormat(numberOfChannels, sampleRate);
+    callOnMainThread([protectedThis = Ref<AudioSourceProviderAVFObjC>(*this), numberOfChannels, sampleRate] {
+        protectedThis->m_client->setFormat(numberOfChannels, sampleRate);
     });
 }
 
index 9862117..692871a 100644 (file)
@@ -806,8 +806,7 @@ void MediaPlayerPrivateAVFoundation::scheduleMainThreadNotification(Notification
     if (delayDispatch && !m_mainThreadCallPending) {
         m_mainThreadCallPending = true;
 
-        auto weakThis = createWeakPtr();
-        callOnMainThread([weakThis] {
+        callOnMainThread([weakThis = createWeakPtr()] {
             if (!weakThis)
                 return;
 
@@ -844,8 +843,7 @@ void MediaPlayerPrivateAVFoundation::dispatchNotification()
         }
         
         if (!m_queuedNotifications.isEmpty() && !m_mainThreadCallPending) {
-            auto weakThis = createWeakPtr();
-            callOnMainThread([weakThis] {
+            callOnMainThread([weakThis = createWeakPtr()] {
                 if (!weakThis)
                     return;
 
index a28d929..5ffd521 100644 (file)
@@ -84,10 +84,10 @@ SOFT_LINK_CLASS(AVFoundation, AVAssetResourceLoadingRequest)
     if ([keyPath isEqualTo:@"outputObscuredDueToInsufficientExternalProtection"]) {
         if ([[change valueForKey:NSKeyValueChangeNewKey] intValue] == 1) {
             RetainPtr<NSError> error = [NSError errorWithDomain:@"com.apple.WebKit" code:'HDCP' userInfo:nil];
-            RetainPtr<WebCDMSessionAVFoundationObjCListener> strongSelf = { self };
-            callOnMainThread([strongSelf, error] {
-                if (strongSelf->_parent)
-                    strongSelf->_parent->playerDidReceiveError(error.get());
+            RetainPtr<WebCDMSessionAVFoundationObjCListener> protectedSelf = { self };
+            callOnMainThread([protectedSelf = WTFMove(protectedSelf), error = WTFMove(error)] {
+                if (protectedSelf->_parent)
+                    protectedSelf->_parent->playerDidReceiveError(error.get());
             });
         }
     } else
index 2c70777..22b04a7 100644 (file)
@@ -185,16 +185,16 @@ void MediaPlaybackTargetPickerMac::invalidatePlaybackTargets()
     if (![keyPath isEqualToString:externalOutputDeviceAvailableKeyName] && ![keyPath isEqualToString:externalOutputDevicePickedKeyName])
         return;
 
-    RetainPtr<WebAVOutputDeviceMenuControllerHelper> strongSelf = self;
-    RetainPtr<NSString> strongKeyPath = keyPath;
-    callOnMainThread([strongSelf, strongKeyPath] {
-        MediaPlaybackTargetPickerMac* callback = strongSelf->m_callback;
+    RetainPtr<WebAVOutputDeviceMenuControllerHelper> protectedSelf = self;
+    RetainPtr<NSString> protectedKeyPath = keyPath;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedKeyPath = WTFMove(protectedKeyPath)] {
+        MediaPlaybackTargetPickerMac* callback = protectedSelf->m_callback;
         if (!callback)
             return;
 
-        if ([strongKeyPath isEqualToString:externalOutputDeviceAvailableKeyName])
+        if ([protectedKeyPath isEqualToString:externalOutputDeviceAvailableKeyName])
             callback->availableDevicesDidChange();
-        else if ([strongKeyPath isEqualToString:externalOutputDevicePickedKeyName])
+        else if ([protectedKeyPath isEqualToString:externalOutputDevicePickedKeyName])
             callback->currentDeviceDidChange();
     });
 }
index a891440..7d89c93 100644 (file)
@@ -701,8 +701,7 @@ void MediaPlayerPrivateAVFoundationObjC::createVideoLayer()
     if (!m_avPlayer || m_haveBeenAskedToCreateLayer)
         return;
 
-    auto weakThis = createWeakPtr();
-    callOnMainThread([this, weakThis] {
+    callOnMainThread([this, weakThis = createWeakPtr()] {
         if (!weakThis)
             return;
 
@@ -3441,15 +3440,15 @@ NSArray* playerKVOProperties()
     if (!m_callback)
         return;
 
-    RetainPtr<WebCoreAVFMovieObserver> strongSelf = self;
-    RetainPtr<NSArray> strongStrings = strings;
-    RetainPtr<NSArray> strongSamples = nativeSamples;
-    callOnMainThread([strongSelf, strongStrings, strongSamples, itemTime] {
-        MediaPlayerPrivateAVFoundationObjC* callback = strongSelf->m_callback;
+    RetainPtr<WebCoreAVFMovieObserver> protectedSelf = self;
+    RetainPtr<NSArray> protectedStrings = strings;
+    RetainPtr<NSArray> protectedNativeSamples = nativeSamples;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedStrings = WTFMove(protectedStrings), protectedNativeSamples = WTFMove(protectedNativeSamples), itemTime] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
         if (!callback)
             return;
         MediaTime time = std::max(toMediaTime(itemTime), MediaTime::zeroTime());
-        callback->processCue(strongStrings.get(), strongSamples.get(), time);
+        callback->processCue(protectedStrings.get(), protectedNativeSamples.get(), time);
     });
 }
 
@@ -3460,9 +3459,8 @@ NSArray* playerKVOProperties()
     if (!m_callback)
         return;
     
-    RetainPtr<WebCoreAVFMovieObserver> strongSelf = self;
-    callOnMainThread([strongSelf] {
-        if (MediaPlayerPrivateAVFoundationObjC* callback = strongSelf->m_callback)
+    callOnMainThread([protectedSelf = RetainPtr<WebCoreAVFMovieObserver>(self)] {
+        if (MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback)
             callback->flushCues();
     });
 }
@@ -3488,17 +3486,17 @@ NSArray* playerKVOProperties()
     if (!m_callback)
         return NO;
 
-    RetainPtr<WebCoreAVFLoaderDelegate> strongSelf = self;
-    RetainPtr<AVAssetResourceLoadingRequest> strongRequest = loadingRequest;
-    callOnMainThread([strongSelf, strongRequest] {
-        MediaPlayerPrivateAVFoundationObjC* callback = strongSelf->m_callback;
+    RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
+    RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
         if (!callback) {
-            [strongRequest finishLoadingWithError:nil];
+            [protectedLoadingRequest finishLoadingWithError:nil];
             return;
         }
 
-        if (!callback->shouldWaitForLoadingOfResource(strongRequest.get()))
-            [strongRequest finishLoadingWithError:nil];
+        if (!callback->shouldWaitForLoadingOfResource(protectedLoadingRequest.get()))
+            [protectedLoadingRequest finishLoadingWithError:nil];
     });
 
     return YES;
@@ -3513,17 +3511,17 @@ NSArray* playerKVOProperties()
     if ([[[challenge protectionSpace] authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
         return NO;
 
-    RetainPtr<WebCoreAVFLoaderDelegate> strongSelf = self;
-    RetainPtr<NSURLAuthenticationChallenge> strongChallenge = challenge;
-    callOnMainThread([strongSelf, strongChallenge] {
-        MediaPlayerPrivateAVFoundationObjC* callback = strongSelf->m_callback;
+    RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
+    RetainPtr<NSURLAuthenticationChallenge> protectedChallenge = challenge;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedChallenge = WTFMove(protectedChallenge)] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
         if (!callback) {
-            [[strongChallenge sender] cancelAuthenticationChallenge:strongChallenge.get()];
+            [[protectedChallenge sender] cancelAuthenticationChallenge:protectedChallenge.get()];
             return;
         }
 
-        if (!callback->shouldWaitForResponseToAuthenticationChallenge(strongChallenge.get()))
-            [[strongChallenge sender] cancelAuthenticationChallenge:strongChallenge.get()];
+        if (!callback->shouldWaitForResponseToAuthenticationChallenge(protectedChallenge.get()))
+            [[protectedChallenge sender] cancelAuthenticationChallenge:protectedChallenge.get()];
     });
 
     return YES;
@@ -3535,12 +3533,12 @@ NSArray* playerKVOProperties()
     if (!m_callback)
         return;
 
-    RetainPtr<WebCoreAVFLoaderDelegate> strongSelf = self;
-    RetainPtr<AVAssetResourceLoadingRequest> strongRequest = loadingRequest;
-    callOnMainThread([strongSelf, strongRequest] {
-        MediaPlayerPrivateAVFoundationObjC* callback = strongSelf->m_callback;
+    RetainPtr<WebCoreAVFLoaderDelegate> protectedSelf = self;
+    RetainPtr<AVAssetResourceLoadingRequest> protectedLoadingRequest = loadingRequest;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedLoadingRequest = WTFMove(protectedLoadingRequest)] {
+        MediaPlayerPrivateAVFoundationObjC* callback = protectedSelf->m_callback;
         if (callback)
-            callback->didCancelLoadingRequest(strongRequest.get());
+            callback->didCancelLoadingRequest(protectedLoadingRequest.get());
     });
 }
 
index 2f582db..b35e3de 100644 (file)
@@ -129,8 +129,7 @@ namespace WebCore {
 static void CMTimebaseEffectiveRateChangedCallback(CMNotificationCenterRef, const void *listener, CFStringRef, const void *, CFTypeRef)
 {
     MediaPlayerPrivateMediaSourceAVFObjC* player = (MediaPlayerPrivateMediaSourceAVFObjC*)listener;
-    auto weakThis = player->createWeakPtr();
-    callOnMainThread([weakThis]{
+    callOnMainThread([weakThis = player->createWeakPtr()] {
         if (!weakThis)
             return;
         weakThis.get()->effectiveRateChanged();
@@ -312,8 +311,7 @@ PlatformLayer* MediaPlayerPrivateMediaSourceAVFObjC::platformLayer() const
 
 void MediaPlayerPrivateMediaSourceAVFObjC::play()
 {
-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis]{
+    callOnMainThread([weakThis = createWeakPtr()] {
         if (!weakThis)
             return;
         weakThis.get()->playInternal();
@@ -332,8 +330,7 @@ void MediaPlayerPrivateMediaSourceAVFObjC::playInternal()
 
 void MediaPlayerPrivateMediaSourceAVFObjC::pause()
 {
-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis]{
+    callOnMainThread([weakThis = createWeakPtr()] {
         if (!weakThis)
             return;
         weakThis.get()->pauseInternal();
index 2cf5877..daee2ef 100644 (file)
@@ -31,6 +31,7 @@
 #include "MediaPlayerPrivate.h"
 #include "MediaStreamPrivate.h"
 #include <wtf/MediaTime.h>
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
 
@@ -142,7 +143,7 @@ private:
     void updateTracks();
     void renderingModeChanged();
 
-    void scheduleDeferredTask(std::function<void()>);
+    void scheduleDeferredTask(NoncopyableFunction&&);
 
     enum DisplayMode {
         None,
index 5de44d0..7a79642 100644 (file)
@@ -624,11 +624,10 @@ void MediaPlayerPrivateMediaStreamAVFObjC::setNetworkState(MediaPlayer::NetworkS
     m_player->networkStateChanged();
 }
 
-void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(std::function<void()> function)
+void MediaPlayerPrivateMediaStreamAVFObjC::scheduleDeferredTask(NoncopyableFunction&& function)
 {
     ASSERT(function);
-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis, function] {
+    callOnMainThread([weakThis = createWeakPtr(), function = WTFMove(function)] {
         if (!weakThis)
             return;
 
index c56f21f..2f5d8c9 100644 (file)
@@ -179,12 +179,12 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(streamDataParser);
 #endif
     ASSERT(streamDataParser == _parser);
-    RetainPtr<WebAVStreamDataParserListener> strongSelf = self;
+    RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;
 
-    RetainPtr<AVAsset*> strongAsset = asset;
-    callOnMainThread([strongSelf, strongAsset] {
-        if (strongSelf->_parent)
-            strongSelf->_parent->didParseStreamDataAsAsset(strongAsset.get());
+    RetainPtr<AVAsset*> protectedAsset = asset;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {
+        if (protectedSelf->_parent)
+            protectedSelf->_parent->didParseStreamDataAsAsset(protectedAsset.get());
     });
 }
 
@@ -195,12 +195,12 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(streamDataParser);
 #endif
     ASSERT(streamDataParser == _parser);
-    RetainPtr<WebAVStreamDataParserListener> strongSelf = self;
+    RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;
 
-    RetainPtr<AVAsset*> strongAsset = asset;
-    callOnMainThread([strongSelf, strongAsset] {
-        if (strongSelf->_parent)
-            strongSelf->_parent->didParseStreamDataAsAsset(strongAsset.get());
+    RetainPtr<AVAsset*> protectedAsset = asset;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedAsset = WTFMove(protectedAsset)] {
+        if (protectedSelf->_parent)
+            protectedSelf->_parent->didParseStreamDataAsAsset(protectedAsset.get());
     });
 }
 
@@ -210,12 +210,12 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(streamDataParser);
 #endif
     ASSERT(streamDataParser == _parser);
-    RetainPtr<WebAVStreamDataParserListener> strongSelf = self;
+    RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;
 
-    RetainPtr<NSError> strongError = error;
-    callOnMainThread([strongSelf, strongError] {
-        if (strongSelf->_parent)
-            strongSelf->_parent->didFailToParseStreamDataWithError(strongError.get());
+    RetainPtr<NSError> protectedError = error;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedError = WTFMove(protectedError)] {
+        if (protectedSelf->_parent)
+            protectedSelf->_parent->didFailToParseStreamDataWithError(protectedError.get());
     });
 }
 
@@ -225,13 +225,13 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(streamDataParser);
 #endif
     ASSERT(streamDataParser == _parser);
-    RetainPtr<WebAVStreamDataParserListener> strongSelf = self;
+    RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;
 
-    RetainPtr<CMSampleBufferRef> strongSample = sample;
+    RetainPtr<CMSampleBufferRef> protectedSample = sample;
     String mediaType = nsMediaType;
-    callOnMainThread([strongSelf, strongSample, trackID, mediaType, flags] {
-        if (strongSelf->_parent)
-            strongSelf->_parent->didProvideMediaDataForTrackID(trackID, strongSample.get(), mediaType, flags);
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedSample = WTFMove(protectedSample), trackID, mediaType, flags] {
+        if (protectedSelf->_parent)
+            protectedSelf->_parent->didProvideMediaDataForTrackID(trackID, protectedSample.get(), mediaType, flags);
     });
 }
 
@@ -241,12 +241,12 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(streamDataParser);
 #endif
     ASSERT(streamDataParser == _parser);
-    RetainPtr<WebAVStreamDataParserListener> strongSelf = self;
+    RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;
 
     String mediaType = nsMediaType;
-    callOnMainThread([strongSelf, trackID, mediaType] {
-        if (strongSelf->_parent)
-            strongSelf->_parent->didReachEndOfTrackWithTrackID(trackID, mediaType);
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), trackID, mediaType] {
+        if (protectedSelf->_parent)
+            protectedSelf->_parent->didReachEndOfTrackWithTrackID(trackID, mediaType);
     });
 }
 
@@ -272,13 +272,12 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(streamDataParser);
 #endif
     ASSERT(streamDataParser == _parser);
-    RetainPtr<WebAVStreamDataParserListener> strongSelf = self;
+    RetainPtr<WebAVStreamDataParserListener> protectedSelf = self;
 
-    RetainPtr<NSData> strongData = initData;
     OSObjectPtr<dispatch_semaphore_t> hasSessionSemaphore = adoptOSObject(dispatch_semaphore_create(0));
-    callOnMainThread([strongSelf, strongData, trackID,  hasSessionSemaphore] {
-        if (strongSelf->_parent)
-            strongSelf->_parent->didProvideContentKeyRequestInitializationDataForTrackID(strongData.get(), trackID, hasSessionSemaphore);
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), protectedInitData = RetainPtr<NSData>(initData), trackID, hasSessionSemaphore = WTFMove(hasSessionSemaphore)] {
+        if (protectedSelf->_parent)
+            protectedSelf->_parent->didProvideContentKeyRequestInitializationDataForTrackID(protectedInitData.get(), trackID, hasSessionSemaphore);
     });
     dispatch_semaphore_wait(hasSessionSemaphore.get(), DISPATCH_TIME_FOREVER);
 }
@@ -382,21 +381,21 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     UNUSED_PARAM(keyPath);
     ASSERT(_parent);
 
-    RetainPtr<WebAVSampleBufferErrorListener> strongSelf = self;
+    RetainPtr<WebAVSampleBufferErrorListener> protectedSelf = self;
     if ([object isKindOfClass:getAVSampleBufferDisplayLayerClass()]) {
         RetainPtr<AVSampleBufferDisplayLayer> layer = (AVSampleBufferDisplayLayer *)object;
         ASSERT(_layers.contains(layer.get()));
 
         if ([keyPath isEqualTo:@"error"]) {
             RetainPtr<NSError> error = [change valueForKey:NSKeyValueChangeNewKey];
-            callOnMainThread([strongSelf, layer, error] {
-                strongSelf->_parent->layerDidReceiveError(layer.get(), error.get());
+            callOnMainThread([protectedSelf = WTFMove(protectedSelf), layer = WTFMove(layer), error = WTFMove(error)] {
+                protectedSelf->_parent->layerDidReceiveError(layer.get(), error.get());
             });
         } else if ([keyPath isEqualTo:@"outputObscuredDueToInsufficientExternalProtection"]) {
             if ([[change valueForKey:NSKeyValueChangeNewKey] boolValue]) {
                 RetainPtr<NSError> error = [NSError errorWithDomain:@"com.apple.WebKit" code:'HDCP' userInfo:nil];
-                callOnMainThread([strongSelf, layer, error] {
-                    strongSelf->_parent->layerDidReceiveError(layer.get(), error.get());
+                callOnMainThread([protectedSelf = WTFMove(protectedSelf), layer = WTFMove(layer), error = WTFMove(error)] {
+                    protectedSelf->_parent->layerDidReceiveError(layer.get(), error.get());
                 });
             }
         } else
@@ -409,8 +408,8 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
         ASSERT(_renderers.contains(renderer.get()));
         ASSERT([keyPath isEqualTo:@"error"]);
 
-        callOnMainThread([strongSelf, renderer, error] {
-            strongSelf->_parent->rendererDidReceiveError(renderer.get(), error.get());
+        callOnMainThread([protectedSelf = WTFMove(protectedSelf), renderer = WTFMove(renderer), error = WTFMove(error)] {
+            protectedSelf->_parent->rendererDidReceiveError(renderer.get(), error.get());
         });
     } else
         ASSERT_NOT_REACHED();
@@ -421,11 +420,11 @@ SOFT_LINK_CONSTANT(AVFoundation, AVSampleBufferDisplayLayerFailedToDecodeNotific
     RetainPtr<AVSampleBufferDisplayLayer> layer = (AVSampleBufferDisplayLayer *)[note object];
     RetainPtr<NSError> error = [[note userInfo] valueForKey:AVSampleBufferDisplayLayerFailedToDecodeNotificationErrorKey];
 
-    RetainPtr<WebAVSampleBufferErrorListener> strongSelf = self;
-    callOnMainThread([strongSelf, layer, error] {
-        if (!strongSelf->_parent || !strongSelf->_layers.contains(layer.get()))
+    RetainPtr<WebAVSampleBufferErrorListener> protectedSelf = self;
+    callOnMainThread([protectedSelf = WTFMove(protectedSelf), layer = WTFMove(layer), error = WTFMove(error)] {
+        if (!protectedSelf->_parent || !protectedSelf->_layers.contains(layer.get()))
             return;
-        strongSelf->_parent->layerDidReceiveError(layer.get(), error.get());
+        protectedSelf->_parent->layerDidReceiveError(layer.get(), error.get());
     });
 }
 @end
index 9ecec52..21f5338 100644 (file)
@@ -295,8 +295,7 @@ static void drawPatternCallback(void* info, CGContextRef context)
 
 static void patternReleaseCallback(void* info)
 {
-    auto image = static_cast<CGImageRef>(info);
-    callOnMainThread([image] {
+    callOnMainThread([image = static_cast<CGImageRef>(info)] {
         CGImageRelease(image);
     });
 }
index b3033fe..b428d50 100644 (file)
@@ -56,9 +56,7 @@ static void patternCallback(void* info, CGContextRef context)
 
 static void patternReleaseCallback(void* info)
 {
-    auto image = static_cast<CGImageRef>(info);
-
-    callOnMainThread([image] {
+    callOnMainThread([image = static_cast<CGImageRef>(info)] {
         CGImageRelease(image);
     });
 }
index 8e577ff..ed32d19 100644 (file)
@@ -486,8 +486,7 @@ bool MediaPlayerPrivateMediaFoundation::endCreatedMediaSource(IMFAsyncResult* as
     hr = asyncResult->GetStatus();
     m_loadingProgress = SUCCEEDED(hr);
 
-    auto weakPtr = m_weakPtrFactory.createWeakPtr();
-    callOnMainThread([weakPtr] {
+    callOnMainThread([weakPtr = m_weakPtrFactory.createWeakPtr()] {
         if (!weakPtr)
             return;
         weakPtr->onCreatedMediaSource();
@@ -516,8 +515,7 @@ bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
 
     switch (mediaEventType) {
     case MESessionTopologySet: {
-        auto weakPtr = m_weakPtrFactory.createWeakPtr();
-        callOnMainThread([weakPtr] {
+        callOnMainThread([weakPtr = m_weakPtrFactory.createWeakPtr()] {
             if (!weakPtr)
                 return;
             weakPtr->onTopologySet();
@@ -526,8 +524,7 @@ bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
     }
 
     case MEBufferingStarted: {
-        auto weakPtr = m_weakPtrFactory.createWeakPtr();
-        callOnMainThread([weakPtr] {
+        callOnMainThread([weakPtr = m_weakPtrFactory.createWeakPtr()] {
             if (!weakPtr)
                 return;
             weakPtr->onBufferingStarted();
@@ -536,8 +533,7 @@ bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
     }
 
     case MEBufferingStopped: {
-        auto weakPtr = m_weakPtrFactory.createWeakPtr();
-        callOnMainThread([weakPtr] {
+        callOnMainThread([weakPtr = m_weakPtrFactory.createWeakPtr()] {
             if (!weakPtr)
                 return;
             weakPtr->onBufferingStopped();
@@ -546,8 +542,7 @@ bool MediaPlayerPrivateMediaFoundation::endGetEvent(IMFAsyncResult* asyncResult)
     }
 
     case MESessionEnded: {
-        auto weakPtr = m_weakPtrFactory.createWeakPtr();
-        callOnMainThread([weakPtr] {
+        callOnMainThread([weakPtr = m_weakPtrFactory.createWeakPtr()] {
             if (!weakPtr)
                 return;
             weakPtr->onSessionEnded();
@@ -1675,8 +1670,7 @@ HRESULT MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::processInputNot
     
     // Invalidate the video area
     if (m_mediaPlayer) {
-        auto weakPtr = m_mediaPlayer->m_weakPtrFactory.createWeakPtr();
-        callOnMainThread([weakPtr] {
+        callOnMainThread([weakPtr = m_mediaPlayer->m_weakPtrFactory.createWeakPtr()] {
             if (weakPtr)
                 weakPtr->invalidateFrameView();
         });
index df66070..42d2466 100644 (file)
@@ -299,11 +299,10 @@ void MediaStreamPrivate::trackEnded(MediaStreamTrackPrivate&)
     });
 }
 
-void MediaStreamPrivate::scheduleDeferredTask(std::function<void()> function)
+void MediaStreamPrivate::scheduleDeferredTask(NoncopyableFunction&& function)
 {
     ASSERT(function);
-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis, function] {
+    callOnMainThread([weakThis = createWeakPtr(), function = WTFMove(function)] {
         if (!weakThis)
             return;
 
index 6bae73c..8cf604c 100644 (file)
@@ -41,6 +41,7 @@
 #include "MediaStreamTrackPrivate.h"
 #include <wtf/HashMap.h>
 #include <wtf/MediaTime.h>
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
@@ -111,7 +112,7 @@ private:
     void characteristicsChanged();
     void updateActiveVideoTrack();
 
-    void scheduleDeferredTask(std::function<void()>);
+    void scheduleDeferredTask(NoncopyableFunction&&);
 
     WeakPtrFactory<MediaStreamPrivate> m_weakPtrFactory;
     Vector<Observer*> m_observers;
index fba5283..21acaf0 100644 (file)
@@ -31,6 +31,7 @@
 #include "GenericTaskQueue.h"
 #include "RealtimeMediaSource.h"
 #include "Timer.h"
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/RetainPtr.h>
 #include <wtf/WeakPtr.h>
 
@@ -85,7 +86,7 @@ protected:
     void setVideoSampleBufferDelegate(AVCaptureVideoDataOutput*);
     void setAudioSampleBufferDelegate(AVCaptureAudioDataOutput*);
 
-    void scheduleDeferredTask(std::function<void ()>);
+    void scheduleDeferredTask(NoncopyableFunction&&);
 
 private:
     void setupSession();
index c0612c5..7915a84 100644 (file)
@@ -240,12 +240,10 @@ void AVMediaCaptureSource::setAudioSampleBufferDelegate(AVCaptureAudioDataOutput
     [audioOutput setSampleBufferDelegate:m_objcObserver.get() queue:globaAudioCaptureSerialQueue()];
 }
 
-void AVMediaCaptureSource::scheduleDeferredTask(std::function<void ()> function)
+void AVMediaCaptureSource::scheduleDeferredTask(NoncopyableFunction&& function)
 {
     ASSERT(function);
-
-    auto weakThis = createWeakPtr();
-    callOnMainThread([weakThis, function] {
+    callOnMainThread([weakThis = createWeakPtr(), function = WTFMove(function)] {
         if (!weakThis)
             return;
 
index 2499cf3..dea7a7c 100644 (file)
@@ -163,10 +163,9 @@ void RealtimeMediaSourceCenterMac::createMediaStream(MediaStreamCreationClient*
 bool RealtimeMediaSourceCenterMac::getMediaStreamTrackSources(PassRefPtr<MediaStreamTrackSourcesRequestClient> prpClient)
 {
     RefPtr<MediaStreamTrackSourcesRequestClient> requestClient = prpClient;
-
     TrackSourceInfoVector sources = AVCaptureDeviceManager::singleton().getSourcesInfo(requestClient->requestOrigin());
 
-    callOnMainThread([this, requestClient, sources] {
+    callOnMainThread([this, requestClient = WTFMove(requestClient), sources = WTFMove(sources)] {
         requestClient->didCompleteTrackSourceInfoRequest(sources);
     });
 
index 7b8d61c..ed917e8 100644 (file)
@@ -214,10 +214,10 @@ void WebAudioSourceProviderAVFObjC::prepare(const AudioStreamBasicDescription* f
     memset(m_list.get(), 0, m_listBufferSize);
     m_list->mNumberBuffers = numberOfChannels;
 
-    RefPtr<WebAudioSourceProviderAVFObjC> strongThis = this;
-    callOnMainThread([strongThis, numberOfChannels, sampleRate] {
-        if (strongThis->m_client)
-            strongThis->m_client->setFormat(numberOfChannels, sampleRate);
+    RefPtr<WebAudioSourceProviderAVFObjC> protectedThis = this;
+    callOnMainThread([protectedThis = WTFMove(protectedThis), numberOfChannels, sampleRate] {
+        if (protectedThis->m_client)
+            protectedThis->m_client->setFormat(numberOfChannels, sampleRate);
     });
 }
 
index 9093579..aae8083 100644 (file)
@@ -159,7 +159,7 @@ bool MockRealtimeMediaSourceCenter::getMediaStreamTrackSources(PassRefPtr<MediaS
     sources.append(MockRealtimeMediaSource::trackSourceWithUID(MockRealtimeMediaSource::mockAudioSourcePersistentID(), nullptr));
     sources.append(MockRealtimeMediaSource::trackSourceWithUID(MockRealtimeMediaSource::mockVideoSourcePersistentID(), nullptr));
 
-    callOnMainThread([this, requestClient, sources] {
+    callOnMainThread([this, requestClient = WTFMove(requestClient), sources = WTFMove(sources)] {
         requestClient->didCompleteTrackSourceInfoRequest(sources);
     });
 
index 53eb25a..484e921 100644 (file)
@@ -187,10 +187,8 @@ void BlobResourceHandle::start()
         return;
     }
 
-    RefPtr<BlobResourceHandle> protectedThis(this);
-
     // Finish this async call quickly and return.
-    callOnMainThread([protectedThis] {
+    callOnMainThread([protectedThis = Ref<BlobResourceHandle>(*this)]() mutable {
         protectedThis->doStart();
     });
 }
@@ -665,9 +663,8 @@ void BlobResourceHandle::notifyFinish()
 
     // Schedule to notify the client from a standalone function because the client might dispose the handle immediately from the callback function
     // while we still have BlobResourceHandle calls in the stack.
-    RefPtr<BlobResourceHandle> protectedThis(this);
-    callOnMainThread([protectedThis] {
-        doNotifyFinish(*protectedThis);
+    callOnMainThread([protectedThis = Ref<BlobResourceHandle>(*this)]() mutable {
+        doNotifyFinish(protectedThis);
     });
 
 }
index e40ed3f..7798f91 100644 (file)
@@ -168,25 +168,21 @@ static void decodeEscaped(DecodeTask& task)
     task.result.data = SharedBuffer::adoptVector(buffer);
 }
 
-void decode(const URL& url, const ScheduleContext& scheduleContext, DecodeCompletionHandler completionHandler)
+void decode(const URL& url, const ScheduleContext& scheduleContext, DecodeCompletionHandler&& completionHandler)
 {
     ASSERT(url.protocolIsData());
 
     auto decodeTask = createDecodeTask(url, scheduleContext, WTFMove(completionHandler));
-    auto* decodeTaskPtr = decodeTask.release();
-    decodeQueue().dispatch([decodeTaskPtr] {
-        auto& decodeTask = *decodeTaskPtr;
-
-        if (decodeTask.isBase64)
-            decodeBase64(decodeTask);
+    decodeQueue().dispatch([decodeTask = WTFMove(decodeTask)]() mutable {
+        if (decodeTask->isBase64)
+            decodeBase64(*decodeTask);
         else
-            decodeEscaped(decodeTask);
+            decodeEscaped(*decodeTask);
 
 #if HAVE(RUNLOOP_TIMER)
-        DecodingResultDispatcher::dispatch(std::unique_ptr<DecodeTask>(decodeTaskPtr));
+        DecodingResultDispatcher::dispatch(WTFMove(decodeTask));
 #else
-        callOnMainThread([decodeTaskPtr] {
-            std::unique_ptr<DecodeTask> decodeTask(decodeTaskPtr);
+        callOnMainThread([decodeTask = WTFMove(decodeTask)] {
             if (!decodeTask->result.data) {
                 decodeTask->completionHandler({ });
                 return;
index 6433376..4c01121 100644 (file)
@@ -55,7 +55,7 @@ struct ScheduleContext {
 #endif
 };
 
-void decode(const URL&, const ScheduleContext&, DecodeCompletionHandler);
+void decode(const URL&, const ScheduleContext&, DecodeCompletionHandler&&);
 
 }
 
index a73675a..61fdfe1 100644 (file)
@@ -92,10 +92,7 @@ NS_ASSUME_NONNULL_END
     for (auto& task : _dataTasks)
         task.get().session = nil;
 
-    // FIXME(C++14): When we can move RefPtrs directly into blocks, replace this with a RefPtr&&:
-    WebCore::PlatformMediaResourceLoader* loader = _loader.leakRef();
-    callOnMainThread([loader] {
-        loader->deref();
+    callOnMainThread([loader = WTFMove(_loader)] {
     });
     [super dealloc];
 }
@@ -466,34 +463,31 @@ void WebCoreNSURLSessionDataTaskClient::loadFinished(PlatformMediaResource& reso
 - (void)cancel
 {
     self.state = NSURLSessionTaskStateCanceling;
-    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
-    callOnMainThread([strongSelf] {
-        [strongSelf _cancel];
-        [strongSelf _finish];
+    callOnMainThread([protectedSelf = RetainPtr<WebCoreNSURLSessionDataTask>(self)] {
+        [protectedSelf _cancel];
+        [protectedSelf _finish];
     });
 }
 
 - (void)suspend
 {
-    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
-    callOnMainThread([strongSelf] {
+    callOnMainThread([protectedSelf = RetainPtr<WebCoreNSURLSessionDataTask>(self)] {
         // NSURLSessionDataTasks must start over after suspending, so while
         // we could defer loading at this point, instead cancel and restart
         // upon resume so as to adhere to NSURLSessionDataTask semantics.
-        [strongSelf _cancel];
-        strongSelf.get().state = NSURLSessionTaskStateSuspended;
+        [protectedSelf _cancel];
+        protectedSelf.get().state = NSURLSessionTaskStateSuspended;
     });
 }
 
 - (void)resume
 {
-    RetainPtr<WebCoreNSURLSessionDataTask> strongSelf { self };
-    callOnMainThread([strongSelf] {
-        if (strongSelf.get().state != NSURLSessionTaskStateSuspended)
+    callOnMainThread([protectedSelf = RetainPtr<WebCoreNSURLSessionDataTask>(self)] {
+        if (protectedSelf.get().state != NSURLSessionTaskStateSuspended)
             return;
 
-        [strongSelf _restart];
-        strongSelf.get().state = NSURLSessionTaskStateRunning;
+        [protectedSelf _restart];
+        protectedSelf.get().state = NSURLSessionTaskStateRunning;
     });
 }
 
index c6c8797..2fef005 100644 (file)
@@ -402,11 +402,9 @@ void CurlDownload::didReceiveHeader(const String& header)
         CURLcode err = curl_easy_getinfo(m_curlHandle, CURLINFO_RESPONSE_CODE, &httpCode);
 
         if (httpCode >= 200 && httpCode < 300) {
-            URLCapture capturedUrl(getCurlEffectiveURL(m_curlHandle));
-            RefPtr<CurlDownload> protectedThis(this);
-
-            callOnMainThread([this, capturedUrl, protectedThis] {
-                m_response.setURL(capturedUrl.url());
+            URL url = getCurlEffectiveURL(m_curlHandle);
+            callOnMainThread([this, url = url.isolatedCopy(), protectedThis = Ref<CurlDownload>(*this)] {
+                m_response.setURL(url);
                 m_response.setMimeType(extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)));
                 m_response.setTextEncodingName(extractCharsetFromMediaType(m_response.httpHeaderField(HTTPHeaderName::ContentType)));
 
@@ -414,14 +412,10 @@ void CurlDownload::didReceiveHeader(const String& header)
             });
         }
     } else {
-        StringCapture capturedHeader(header);
-
-        RefPtr<CurlDownload> protectedThis(this);
-
-        callOnMainThread([this, capturedHeader, protectedThis] {
-            int splitPos = capturedHeader.string().find(":");
+        callOnMainThread([this, header = header.isolatedCopy(), protectedThis = Ref<CurlDownload>(*this)] {
+            int splitPos = header.string().find(":");
             if (splitPos != -1)
-                m_response.setHTTPHeaderField(capturedHeader.string().left(splitPos), capturedHeader.string().substring(splitPos + 1).stripWhiteSpace());
+                m_response.setHTTPHeaderField(header.string().left(splitPos), header.string().substring(splitPos + 1).stripWhiteSpace());
         });
     }
 }
index 4633624..830df7d 100644 (file)
@@ -1,3 +1,34 @@
+2016-05-27  Chris Dumez  <cdumez@apple.com>
+
+        callOnMainThread() should not copy captured lambda variables
+        https://bugs.webkit.org/show_bug.cgi?id=158166
+
+        Reviewed by Brady Eidson.
+
+        callOnMainThread() should not copy captured lambda variables. This 
+        function is usually called cross-thread with a lambda and copying
+        the lambda (and its captured variables) can lead to thread-safety
+        issues.
+
+        This patch updates callOnMainThread() to take a NoncopyableFunction&&
+        in parameter instead of a std::function. The call sites of
+        callOnMainThread() have also been updated to use C++14's lambda
+        capture with initializer.
+
+        * Storage/StorageAreaSync.cpp:
+        (WebCore::StorageAreaSync::deleteEmptyDatabase):
+        * Storage/StorageSyncManager.cpp:
+        (WebCore::StorageSyncManager::dispatch):
+        * Storage/StorageSyncManager.h:
+        * Storage/StorageThread.cpp:
+        (WebCore::StorageThread::dispatch):
+        (WebCore::StorageThread::terminate):
+        (WebCore::StorageThread::releaseFastMallocFreeMemoryInAllThreads):
+        * Storage/StorageThread.h:
+        * Storage/StorageTracker.cpp:
+        (WebCore::StorageTracker::syncFileSystemAndTrackerDatabase):
+        (WebCore::StorageTracker::setOriginDetails):
+
 2016-05-25  Alex Christensen  <achristensen@webkit.org>
 
         Fix CMake build.
index b5ccf5b..524fa26 100644 (file)
@@ -514,10 +514,8 @@ void StorageAreaSync::deleteEmptyDatabase()
         query.finalize();
         m_database.close();
         if (StorageTracker::tracker().isActive()) {
-            StringImpl* databaseIdentifierCopy = &m_databaseIdentifier.impl()->isolatedCopy().leakRef();
-            callOnMainThread([databaseIdentifierCopy] {
-                StorageTracker::tracker().deleteOriginWithIdentifier(databaseIdentifierCopy);
-                databaseIdentifierCopy->deref();
+            callOnMainThread([databaseIdentifier = m_databaseIdentifier.isolatedCopy()] {
+                StorageTracker::tracker().deleteOriginWithIdentifier(databaseIdentifier);
             });
         } else {
             String databaseFilename = m_syncManager->fullDatabaseFilename(m_databaseIdentifier);
index 036d6ba..3e1f1c4 100644 (file)
@@ -63,13 +63,13 @@ String StorageSyncManager::fullDatabaseFilename(const String& databaseIdentifier
     return pathByAppendingComponent(m_path, databaseIdentifier + ".localstorage");
 }
 
-void StorageSyncManager::dispatch(const std::function<void ()>& function)
+void StorageSyncManager::dispatch(NoncopyableFunction&& function)
 {
     ASSERT(isMainThread());
     ASSERT(m_thread);
 
     if (m_thread)
-        m_thread->dispatch(function);
+        m_thread->dispatch(WTFMove(function));
 }
 
 void StorageSyncManager::close()
index 0287721..edd717d 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <functional>
 #include <wtf/Forward.h>
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/WTFString.h>
@@ -42,7 +43,7 @@ public:
     static Ref<StorageSyncManager> create(const String& path);
     ~StorageSyncManager();
 
-    void dispatch(const std::function<void ()>&);
+    void dispatch(NoncopyableFunction&&);
     void close();
 
 private:
index 8ca8bce..62840d2 100644 (file)
@@ -74,11 +74,11 @@ void StorageThread::threadEntryPoint()
     }
 }
 
-void StorageThread::dispatch(const std::function<void ()>& function)
+void StorageThread::dispatch(NoncopyableFunction&& function)
 {
     ASSERT(isMainThread());
     ASSERT(!m_queue.killed() && m_threadID);
-    m_queue.append(std::make_unique<std::function<void ()>>(function));
+    m_queue.append(std::make_unique<NoncopyableFunction>(WTFMove(function)));
 }
 
 void StorageThread::terminate()
@@ -90,7 +90,7 @@ void StorageThread::terminate()
     if (!m_threadID)
         return;
 
-    m_queue.append(std::make_unique<std::function<void ()>>([this] {
+    m_queue.append(std::make_unique<NoncopyableFunction>([this] {
         performTerminate();
     }));
     waitForThreadCompletion(m_threadID);
@@ -108,8 +108,11 @@ void StorageThread::releaseFastMallocFreeMemoryInAllThreads()
 {
     HashSet<StorageThread*>& threads = activeStorageThreads();
 
-    for (HashSet<StorageThread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
-        (*it)->dispatch(WTF::releaseFastMallocFreeMemory);
+    for (HashSet<StorageThread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
+        (*it)->dispatch([]() {
+            WTF::releaseFastMallocFreeMemory();
+        });
+    }
 }
 
 }
index df52ac6..dce5ccf 100644 (file)
@@ -29,7 +29,7 @@
 #include <functional>
 #include <wtf/HashSet.h>
 #include <wtf/MessageQueue.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/NoncopyableFunction.h>
 #include <wtf/Threading.h>
 
 namespace WebCore {
@@ -46,7 +46,7 @@ public:
     bool start();
     void terminate();
 
-    void dispatch(const std::function<void()>&);
+    void dispatch(NoncopyableFunction&&);
 
     static void releaseFastMallocFreeMemoryInAllThreads();
 
@@ -59,7 +59,7 @@ private:
     void performTerminate();
 
     ThreadIdentifier m_threadID;
-    MessageQueue<std::function<void()>> m_queue;
+    MessageQueue<NoncopyableFunction> m_queue;
 };
 
 } // namespace WebCore
index 8d80d4d..9b36a73 100644 (file)
@@ -293,9 +293,8 @@ void StorageTracker::syncFileSystemAndTrackerDatabase()
         if (foundOrigins.contains(originIdentifier))
             continue;
 
-        String originIdentifierCopy = originIdentifier.isolatedCopy();
-        callOnMainThread([this, originIdentifierCopy] {
-            deleteOriginWithIdentifier(originIdentifierCopy);
+        callOnMainThread([this, originIdentifier = originIdentifier.isolatedCopy()] {
+            deleteOriginWithIdentifier(originIdentifier);
         });
     }
 }
@@ -314,19 +313,17 @@ void StorageTracker::setOriginDetails(const String& originIdentifier, const Stri
         m_originSet.add(originIdentifier);
     }
 
-    String originIdentifierCopy = originIdentifier.isolatedCopy();
-    String databaseFileCopy = databaseFile.isolatedCopy();
-    auto function = [this, originIdentifierCopy, databaseFileCopy] {
-        syncSetOriginDetails(originIdentifierCopy, databaseFileCopy);
+    auto function = [this, originIdentifier = originIdentifier.isolatedCopy(), databaseFile = databaseFile.isolatedCopy()] {
+        syncSetOriginDetails(originIdentifier, databaseFile);
     };
 
     if (isMainThread()) {
         ASSERT(m_thread);
-        m_thread->dispatch(function);
+        m_thread->dispatch(WTFMove(function));
     } else {
         // FIXME: This weird ping-ponging was done to fix a deadlock. We should figure out a cleaner way to avoid it instead.
-        callOnMainThread([this, function] {
-            m_thread->dispatch(function);
+        callOnMainThread([this, function = WTFMove(function)]() mutable {
+            m_thread->dispatch(WTFMove(function));
         });
     }
 }
index 65e9475..82b6ec3 100644 (file)
@@ -1,3 +1,26 @@
+2016-05-27  Chris Dumez  <cdumez@apple.com>
+
+        callOnMainThread() should not copy captured lambda variables
+        https://bugs.webkit.org/show_bug.cgi?id=158166
+
+        Reviewed by Brady Eidson.
+
+        callOnMainThread() should not copy captured lambda variables. This 
+        function is usually called cross-thread with a lambda and copying
+        the lambda (and its captured variables) can lead to thread-safety
+        issues.
+
+        This patch updates callOnMainThread() to take a NoncopyableFunction&&
+        in parameter instead of a std::function. The call sites of
+        callOnMainThread() have also been updated to use C++14's lambda
+        capture with initializer.
+
+        * Storage/WebDatabaseManagerClient.mm:
+        (DidModifyOriginData::dispatchToMainThread):
+        (DidModifyOriginData::DidModifyOriginData): Deleted.
+        * Storage/WebStorageTrackerClient.mm:
+        (WebStorageTrackerClient::dispatchDidModifyOrigin):
+
 2016-05-27  Caitlin Potter  <caitp@igalia.com>
 
         [JSC] implement async functions proposal
index deb4e41..a3ec99c 100644 (file)
@@ -103,20 +103,19 @@ class DidModifyOriginData {
 public:
     static void dispatchToMainThread(WebDatabaseManagerClient* client, SecurityOrigin* origin)
     {
-        DidModifyOriginData* context = new DidModifyOriginData(client, origin->isolatedCopy());
-        callOnMainThread([context] {
+        auto context = std::make_unique<DidModifyOriginData>(client, origin->isolatedCopy());
+        callOnMainThread([context = WTFMove(context)] {
             context->client->dispatchDidModifyOrigin(context->origin.get());
-            delete context;
         });
     }
 
-private:
     DidModifyOriginData(WebDatabaseManagerClient* client, PassRefPtr<SecurityOrigin> origin)
         : client(client)
         , origin(origin)
     {
     }
 
+private:
     WebDatabaseManagerClient* client;
     RefPtr<SecurityOrigin> origin;
 };
index 7e5d991..d680bc4 100644 (file)
@@ -58,15 +58,15 @@ void WebStorageTrackerClient::dispatchDidModifyOrigin(PassRefPtr<SecurityOrigin>
 
 void WebStorageTrackerClient::dispatchDidModifyOrigin(const String& originIdentifier)
 {
-    RefPtr<SecurityOrigin> origin = SecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
+    auto origin = SecurityOrigin::createFromDatabaseIdentifier(originIdentifier);
 
     if (isMainThread()) {
-        dispatchDidModifyOrigin(origin);
+        dispatchDidModifyOrigin(WTFMove(origin));
         return;
     }
 
-    callOnMainThread([origin] {
-        WebStorageTrackerClient::sharedWebStorageTrackerClient()->dispatchDidModifyOrigin(origin.get());
+    callOnMainThread([origin = WTFMove(origin)]() mutable {
+        WebStorageTrackerClient::sharedWebStorageTrackerClient()->dispatchDidModifyOrigin(WTFMove(origin));
     });
 }