Changeset 268423 in webkit


Ignore:
Timestamp:
Oct 13, 2020 2:53:22 PM (4 years ago)
Author:
Chris Dumez
Message:

WebAudio tests are crashing in debug when enabling the GPU process
https://bugs.webkit.org/show_bug.cgi?id=217663

Reviewed by Geoff Garen.

Source/WebCore:

No new tests, unskipped existing tests.

  • WebCore.xcodeproj/project.pbxproj:
  • platform/audio/PushPullFIFO.h:

Export PushPullFIFO so that it can be used at WebKit layer.

Source/WebKit:

WebAudio tests were crashing in debug when enabling the GPU process because it did audio
processing on the WebContent process's main thread. To address the issue, I made
RemoteAudioDestinationProxy a ThreadMessageReceiver so that it receives IPC on an audio
thread instead of the main thread. IPC messages are processed directly on the AudioWorklet
thread when active or on an audio thread constructed by RemoteAudioDestinationProxy
otherwise.

  • GPUProcess/media/RemoteAudioDestinationManager.cpp:

(WebKit::RemoteAudioDestination::RemoteAudioDestination):
Use a PushPullFIFO structure in render() to avoid hanging the audio rendering thread
on a semaphore. Hanging the rendering thread was terrible for performance and was also
a source of deadlock since the underlying framework is holding a lock while render() is
called. We could process a RemoteAudioDestination::CreateAudioDestination sync IPC on the
main thread and deadlock on that lock.

  • GPUProcess/webrtc/LibWebRTCCodecsProxy.h:
  • GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h:
  • GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h:
  • NetworkProcess/IndexedDB/WebIDBServer.h:
  • NetworkProcess/webrtc/NetworkRTCProvider.h:
  • WebProcess/Network/webrtc/LibWebRTCNetwork.h:
  • WebProcess/cocoa/RemoteCaptureSampleManager.h:

Use ThreadMessageReceiverRefCounted instead of ThreadMessageReceiver since those classes
do not provide their own RefCounting.

  • Platform/IPC/Connection.cpp:

(IPC::Connection::addWorkQueueMessageReceiver):
(IPC::Connection::removeWorkQueueMessageReceiver):
(IPC::Connection::addThreadMessageReceiver):
(IPC::Connection::removeThreadMessageReceiver):
(IPC::Connection::processIncomingMessage):
(IPC::Connection::dispatchMessageToWorkQueueReceiver):
(IPC::Connection::dispatchMessageToThreadReceiver):

  • Platform/IPC/Connection.h:

(IPC::Connection::ThreadMessageReceiver::ref):
(IPC::Connection::ThreadMessageReceiver::deref):

  • Add support for passing a destinationID when registering a WorkQueueMessageReceiver or a ThreadMessageReceiver, similarly to regular MessageReceivers. This was needed here since The GPUProcess sends IPC messages to the RemoteAudioDestinationProxy with a given destinationID and since RemoteAudioDestinationProxy is now a ThreadMessageReceiver.
  • Stop having ThreadMessageReceiver subclass ThreadSafeRefCounted since RemoteAudioDestinationProxy already subclasses ThreadSafeRefCounted indirectly. A new ThreadMessageReceiverRefCounted class was added for convenience for existing code that relied on its refcounting.
  • WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp:

(WebKit::RemoteAudioDestinationProxy::RemoteAudioDestinationProxy):
(WebKit::RemoteAudioDestinationProxy::~RemoteAudioDestinationProxy):
(WebKit::RemoteAudioDestinationProxy::start):
(WebKit::RemoteAudioDestinationProxy::stop):
(WebKit::RemoteAudioDestinationProxy::renderBuffer):
(WebKit::RemoteAudioDestinationProxy::didChangeIsPlaying):
(WebKit::RemoteAudioDestinationProxy::dispatchToThread):

  • WebProcess/GPU/media/RemoteAudioDestinationProxy.h:

Use a PushPullFIFO container in render() to avoid handing the audio rendering thread on
a semaphore while the Render IPC is getting processed by the WebProcess.

Source/WTF:

  • wtf/CrossThreadQueue.h:

(WTF::CrossThreadQueue<DataType>::waitForMessage):
If CrossThreadQueue::kill() gets called while another thread is waiting on a
CrossThreadQueue::waitForMessage() call, make it so that waitForMessage()
returns a default-constructed DataType instead of crashing trying to
dequeue (since the queue is empty).

LayoutTests:

Unskip webaudio tests when the GPU process is enabled.

  • gpu-process/TestExpectations:
Location:
trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r268422 r268423  
     12020-10-13  Chris Dumez  <cdumez@apple.com>
     2
     3        WebAudio tests are crashing in debug when enabling the GPU process
     4        https://bugs.webkit.org/show_bug.cgi?id=217663
     5
     6        Reviewed by Geoff Garen.
     7
     8        Unskip webaudio tests when the GPU process is enabled.
     9
     10        * gpu-process/TestExpectations:
     11
    1122020-10-13  Karl Rackler  <rackler@apple.com>
    213
  • trunk/LayoutTests/gpu-process/TestExpectations

    r268299 r268423  
    307307imported/w3c/web-platform-tests/service-workers/service-worker/fetch-audio-tainting.https.html [ Skip ]
    308308
    309 imported/w3c/web-platform-tests/webaudio [ Skip ]
    310309imported/w3c/web-platform-tests/webrtc [ Skip ]
    311310
    312 webaudio [ Skip ]
    313311webrtc [ Skip ]
    314312
  • trunk/Source/WTF/ChangeLog

    r268420 r268423  
     12020-10-13  Chris Dumez  <cdumez@apple.com>
     2
     3        WebAudio tests are crashing in debug when enabling the GPU process
     4        https://bugs.webkit.org/show_bug.cgi?id=217663
     5
     6        Reviewed by Geoff Garen.
     7
     8        * wtf/CrossThreadQueue.h:
     9        (WTF::CrossThreadQueue<DataType>::waitForMessage):
     10        If CrossThreadQueue::kill() gets called while another thread is waiting on a
     11        CrossThreadQueue::waitForMessage() call, make it so that waitForMessage()
     12        returns a default-constructed DataType instead of crashing trying to
     13        dequeue (since the queue is empty).
     14
    1152020-10-13  Keith Rollin  <krollin@apple.com>
    216
  • trunk/Source/WTF/wtf/CrossThreadQueue.h

    r248546 r268423  
    8181        m_condition.wait(m_lock);
    8282    }
     83    if (m_killed)
     84        return { };
    8385
    8486    return m_queue.takeFirst();
  • trunk/Source/WebCore/ChangeLog

    r268420 r268423  
     12020-10-13  Chris Dumez  <cdumez@apple.com>
     2
     3        WebAudio tests are crashing in debug when enabling the GPU process
     4        https://bugs.webkit.org/show_bug.cgi?id=217663
     5
     6        Reviewed by Geoff Garen.
     7
     8        No new tests, unskipped existing tests.
     9
     10        * WebCore.xcodeproj/project.pbxproj:
     11        * platform/audio/PushPullFIFO.h:
     12        Export PushPullFIFO so that it can be used at WebKit layer.
     13
    1142020-10-13  Keith Rollin  <krollin@apple.com>
    215
  • trunk/Source/WebCore/Headers.cmake

    r268372 r268423  
    10691069    platform/audio/AudioSourceProvider.h
    10701070    platform/audio/AudioStreamDescription.h
     1071    platform/audio/AudioUtilities.h
    10711072    platform/audio/NowPlayingInfo.h
    10721073    platform/audio/PlatformAudioData.h
    10731074    platform/audio/PlatformMediaSession.h
    10741075    platform/audio/PlatformMediaSessionManager.h
     1076    platform/audio/PushPullFIFO.h
    10751077
    10761078    platform/encryptedmedia/CDMEncryptionScheme.h
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r268386 r268423  
    25432543                83D35AEC1C7187FA00F70D5A /* XMLHttpRequestEventTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D35AEA1C7187ED00F70D5A /* XMLHttpRequestEventTarget.h */; };
    25442544                83D35AF21C718D9000F70D5A /* JSXMLHttpRequestEventTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */; };
    2545                 83D511F6250C1CBF002EDC51 /* PushPullFIFO.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D511F5250C1CA8002EDC51 /* PushPullFIFO.h */; };
     2545                83D511F6250C1CBF002EDC51 /* PushPullFIFO.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D511F5250C1CA8002EDC51 /* PushPullFIFO.h */; settings = {ATTRIBUTES = (Private, ); }; };
    25462546                83D6AAE62524EE1C00428B4B /* WorkerOrWorkletGlobalScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D6AAE42524EE1300428B4B /* WorkerOrWorkletGlobalScope.h */; };
    25472547                83DB9E0F24DA19490037B468 /* BiquadFilterType.h in Headers */ = {isa = PBXBuildFile; fileRef = 83DB9E0C24DA18B50037B468 /* BiquadFilterType.h */; };
     
    52865286                FD31608812B026F700C1A359 /* AudioResamplerKernel.h in Headers */ = {isa = PBXBuildFile; fileRef = FD31605212B026F700C1A359 /* AudioResamplerKernel.h */; };
    52875287                FD31608912B026F700C1A359 /* AudioSourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = FD31605312B026F700C1A359 /* AudioSourceProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
    5288                 FD31608B12B026F700C1A359 /* AudioUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = FD31605512B026F700C1A359 /* AudioUtilities.h */; };
     5288                FD31608B12B026F700C1A359 /* AudioUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = FD31605512B026F700C1A359 /* AudioUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
    52895289                FD31608D12B026F700C1A359 /* Biquad.h in Headers */ = {isa = PBXBuildFile; fileRef = FD31605712B026F700C1A359 /* Biquad.h */; };
    52905290                FD31608F12B026F700C1A359 /* Cone.h in Headers */ = {isa = PBXBuildFile; fileRef = FD31605912B026F700C1A359 /* Cone.h */; };
  • trunk/Source/WebCore/platform/audio/PushPullFIFO.h

    r267544 r268423  
    4646
    4747    // |fifoLength| cannot exceed |maxFIFOLength|. Otherwise it crashes.
    48     PushPullFIFO(unsigned numberOfChannels, size_t fifoLength);
    49     ~PushPullFIFO();
     48    WEBCORE_EXPORT PushPullFIFO(unsigned numberOfChannels, size_t fifoLength);
     49    WEBCORE_EXPORT ~PushPullFIFO();
    5050
    5151    // Pushes the rendered frames by WebAudio engine.
     
    5454    //    will be overwritten and |indexRead| will be forcibly moved to
    5555    //    |indexWrite| to avoid reading overwritten frames.
    56     void push(const AudioBus* inputBus);
     56    WEBCORE_EXPORT void push(const AudioBus* inputBus);
    5757
    5858    // Pulls |framesRequested| by the audio device thread and returns the actual
    5959    // number of frames to be rendered by the source. (i.e. WebAudio graph)
    60     size_t pull(AudioBus* outputBus, size_t framesRequested);
     60    WEBCORE_EXPORT size_t pull(AudioBus* outputBus, size_t framesRequested);
    6161
    6262    size_t framesAvailable() const { return m_framesAvailable; }
  • trunk/Source/WebKit/ChangeLog

    r268421 r268423  
     12020-10-13  Chris Dumez  <cdumez@apple.com>
     2
     3        WebAudio tests are crashing in debug when enabling the GPU process
     4        https://bugs.webkit.org/show_bug.cgi?id=217663
     5
     6        Reviewed by Geoff Garen.
     7
     8        WebAudio tests were crashing in debug when enabling the GPU process because it did audio
     9        processing on the WebContent process's main thread. To address the issue, I made
     10        RemoteAudioDestinationProxy a ThreadMessageReceiver so that it receives IPC on an audio
     11        thread instead of the main thread. IPC messages are processed directly on the AudioWorklet
     12        thread when active or on an audio thread constructed by RemoteAudioDestinationProxy
     13        otherwise.
     14
     15        * GPUProcess/media/RemoteAudioDestinationManager.cpp:
     16        (WebKit::RemoteAudioDestination::RemoteAudioDestination):
     17        Use a PushPullFIFO structure in render() to avoid hanging the audio rendering thread
     18        on a semaphore. Hanging the rendering thread was terrible for performance and was also
     19        a source of deadlock since the underlying framework is holding a lock while render() is
     20        called. We could process a RemoteAudioDestination::CreateAudioDestination sync IPC on the
     21        main thread and deadlock on that lock.
     22
     23        * GPUProcess/webrtc/LibWebRTCCodecsProxy.h:
     24        * GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h:
     25        * GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h:
     26        * NetworkProcess/IndexedDB/WebIDBServer.h:
     27        * NetworkProcess/webrtc/NetworkRTCProvider.h:
     28        * WebProcess/Network/webrtc/LibWebRTCNetwork.h:
     29        * WebProcess/cocoa/RemoteCaptureSampleManager.h:
     30        Use ThreadMessageReceiverRefCounted instead of ThreadMessageReceiver since those classes
     31        do not provide their own RefCounting.
     32
     33        * Platform/IPC/Connection.cpp:
     34        (IPC::Connection::addWorkQueueMessageReceiver):
     35        (IPC::Connection::removeWorkQueueMessageReceiver):
     36        (IPC::Connection::addThreadMessageReceiver):
     37        (IPC::Connection::removeThreadMessageReceiver):
     38        (IPC::Connection::processIncomingMessage):
     39        (IPC::Connection::dispatchMessageToWorkQueueReceiver):
     40        (IPC::Connection::dispatchMessageToThreadReceiver):
     41        * Platform/IPC/Connection.h:
     42        (IPC::Connection::ThreadMessageReceiver::ref):
     43        (IPC::Connection::ThreadMessageReceiver::deref):
     44        - Add support for passing a destinationID when registering a WorkQueueMessageReceiver or a
     45          ThreadMessageReceiver, similarly to regular MessageReceivers. This was needed here since
     46          The GPUProcess sends IPC messages to the RemoteAudioDestinationProxy with a given
     47          destinationID and since RemoteAudioDestinationProxy is now a ThreadMessageReceiver.
     48        - Stop having ThreadMessageReceiver subclass ThreadSafeRefCounted since
     49          RemoteAudioDestinationProxy already subclasses ThreadSafeRefCounted indirectly. A new
     50          ThreadMessageReceiverRefCounted class was added for convenience for existing code that
     51          relied on its refcounting.
     52
     53        * WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp:
     54        (WebKit::RemoteAudioDestinationProxy::RemoteAudioDestinationProxy):
     55        (WebKit::RemoteAudioDestinationProxy::~RemoteAudioDestinationProxy):
     56        (WebKit::RemoteAudioDestinationProxy::start):
     57        (WebKit::RemoteAudioDestinationProxy::stop):
     58        (WebKit::RemoteAudioDestinationProxy::renderBuffer):
     59        (WebKit::RemoteAudioDestinationProxy::didChangeIsPlaying):
     60        (WebKit::RemoteAudioDestinationProxy::dispatchToThread):
     61        * WebProcess/GPU/media/RemoteAudioDestinationProxy.h:
     62        Use a PushPullFIFO container in render() to avoid handing the audio rendering thread on
     63        a semaphore while the Render IPC is getting processed by the WebProcess.
     64
    1652020-10-13  Per Arne Vollan  <pvollan@apple.com>
    266
  • trunk/Source/WebKit/GPUProcess/media/RemoteAudioDestinationManager.cpp

    r268118 r268423  
    3636#include <WebCore/AudioDestination.h>
    3737#include <WebCore/AudioIOCallback.h>
     38#include <WebCore/AudioUtilities.h>
     39#include <WebCore/PushPullFIFO.h>
    3840#include <WebCore/SharedBuffer.h>
    3941#include <wtf/ThreadSafeRefCounted.h>
     
    4143
    4244namespace WebKit {
     45
     46// This FIFO size matches to one in AudioDestinationCocoa.cpp and was imported from Blink.
     47constexpr size_t fifoSize = 96 * WebCore::AudioUtilities::renderQuantumSize;
    4348
    4449class RemoteAudioDestination : public ThreadSafeRefCounted<RemoteAudioDestination>, public WebCore::AudioIOCallback {
     
    7782        , m_id(identifier)
    7883        , m_destination(AudioDestination::create(*this, inputDeviceId, numberOfInputChannels, numberOfOutputChannels, sampleRate))
     84        , m_fifo(numberOfOutputChannels, fifoSize)
    7985    {
    8086    }
    8187
    82     void render(AudioBus* sourceBus, AudioBus* destinationBus, size_t framesToProcess, const WebCore::AudioIOPosition& outputPosition) override
     88    void render(AudioBus*, AudioBus* destinationBus, size_t framesToProcess, const WebCore::AudioIOPosition& outputPosition) override
    8389    {
     90        ASSERT(!isMainThread());
     91
    8492        if (m_protectThisDuringGracefulShutdown)
    8593            return;
    8694
    87         auto protectedThis = makeRef(*this);
    88         BinarySemaphore renderSemaphore;
     95        {
     96            auto locker = holdLock(m_fifoLock);
     97            framesToProcess = m_fifo.pull(destinationBus, framesToProcess);
     98        }
     99        if (!framesToProcess)
     100            return;
    89101
    90102        Vector<Ref<SharedMemory>> buffers;
     
    94106        }
    95107
    96         // FIXME: Replace this code with a ring buffer. At least this happens in audio thread.
    97         ASSERT(!isMainThread());
    98         callOnMainThread([this, framesToProcess, outputPosition, &buffers, &renderSemaphore] {
     108        // FIXME: It is unfortunate we have to dispatch to the main thead here. We should be able to IPC straight from the
     109        // render thread but this is not supported by sendWithAsyncReply().
     110        callOnMainThread([this, protectedThis = makeRef(*this), framesToProcess, outputPosition, buffers = WTFMove(buffers)]() mutable {
    99111            RemoteAudioBusData busData { framesToProcess, outputPosition, buffers.map([](auto& memory) { return memory.copyRef(); }) };
    100112            ASSERT(framesToProcess);
    101             m_connection.connection().sendWithAsyncReply(Messages::RemoteAudioDestinationProxy::RenderBuffer(busData), [&]() {
    102                 renderSemaphore.signal();
     113            m_connection.connection().sendWithAsyncReply(Messages::RemoteAudioDestinationProxy::RenderBuffer(busData), [this, protectedThis = WTFMove(protectedThis), buffers = WTFMove(buffers), framesToProcess]() {
     114                auto audioBus = AudioBus::create(buffers.size(), framesToProcess, false);
     115                for (unsigned i = 0; i < buffers.size(); ++i)
     116                    audioBus->setChannelMemory(i, static_cast<float*>(buffers[i]->data()), framesToProcess);
     117                auto locker = holdLock(m_fifoLock);
     118                m_fifo.push(audioBus.get());
    103119            }, m_id.toUInt64());
    104120        });
    105         renderSemaphore.wait();
    106 
    107         auto audioBus = AudioBus::create(buffers.size(), framesToProcess, false);
    108         for (unsigned i = 0; i < buffers.size(); ++i)
    109             audioBus->setChannelMemory(i, (float*)buffers[i]->data(), framesToProcess);
    110         destinationBus->copyFrom(*audioBus);
    111121    }
    112122
     
    128138    RefPtr<AudioDestination> m_destination;
    129139    RefPtr<RemoteAudioDestination> m_protectThisDuringGracefulShutdown;
     140    Lock m_fifoLock;
     141    WebCore::PushPullFIFO m_fifo;
    130142};
    131143
  • trunk/Source/WebKit/GPUProcess/webrtc/LibWebRTCCodecsProxy.h

    r267145 r268423  
    5252class GPUConnectionToWebProcess;
    5353
    54 class LibWebRTCCodecsProxy : public IPC::Connection::ThreadMessageReceiver {
     54class LibWebRTCCodecsProxy : public IPC::Connection::ThreadMessageReceiverRefCounted {
    5555    WTF_MAKE_FAST_ALLOCATED;
    5656public:
  • trunk/Source/WebKit/GPUProcess/webrtc/RemoteAudioMediaStreamTrackRendererManager.h

    r267156 r268423  
    4343class RemoteAudioMediaStreamTrackRenderer;
    4444
    45 class RemoteAudioMediaStreamTrackRendererManager final : public IPC::Connection::ThreadMessageReceiver {
     45class RemoteAudioMediaStreamTrackRendererManager final : public IPC::Connection::ThreadMessageReceiverRefCounted {
    4646    WTF_MAKE_FAST_ALLOCATED;
    4747public:
  • trunk/Source/WebKit/GPUProcess/webrtc/RemoteSampleBufferDisplayLayerManager.h

    r267156 r268423  
    4747class RemoteSampleBufferDisplayLayer;
    4848
    49 class RemoteSampleBufferDisplayLayerManager final : public IPC::Connection::ThreadMessageReceiver {
     49class RemoteSampleBufferDisplayLayerManager final : public IPC::Connection::ThreadMessageReceiverRefCounted {
    5050    WTF_MAKE_FAST_ALLOCATED;
    5151public:
  • trunk/Source/WebKit/NetworkProcess/IndexedDB/WebIDBServer.h

    r266742 r268423  
    4444namespace WebKit {
    4545
    46 class WebIDBServer final : public CrossThreadTaskHandler, public IPC::Connection::ThreadMessageReceiver {
     46class WebIDBServer final : public CrossThreadTaskHandler, public IPC::Connection::ThreadMessageReceiverRefCounted {
    4747public:
    4848    static Ref<WebIDBServer> create(PAL::SessionID, const String& directory, WebCore::IDBServer::IDBServer::StorageQuotaManagerSpaceRequester&&);
  • trunk/Source/WebKit/NetworkProcess/webrtc/NetworkRTCProvider.h

    r264814 r268423  
    6161struct RTCPacketOptions;
    6262
    63 class NetworkRTCProvider : public rtc::MessageHandler, public IPC::Connection::ThreadMessageReceiver {
     63class NetworkRTCProvider : public rtc::MessageHandler, public IPC::Connection::ThreadMessageReceiverRefCounted {
    6464public:
    6565    static Ref<NetworkRTCProvider> create(NetworkConnectionToWebProcess& connection) { return adoptRef(*new NetworkRTCProvider(connection)); }
  • trunk/Source/WebKit/Platform/IPC/Connection.cpp

    r264032 r268423  
    312312}
    313313
    314 void Connection::addWorkQueueMessageReceiver(ReceiverName messageReceiverName, WorkQueue& workQueue, WorkQueueMessageReceiver* workQueueMessageReceiver)
     314void Connection::addWorkQueueMessageReceiver(ReceiverName messageReceiverName, WorkQueue& workQueue, WorkQueueMessageReceiver* workQueueMessageReceiver, uint64_t destinationID)
    315315{
    316316    ASSERT(RunLoop::isMain());
    317317
    318318    auto locker = holdLock(m_workQueueMessageReceiversMutex);
    319     ASSERT(!m_workQueueMessageReceivers.contains(messageReceiverName));
    320 
    321     m_workQueueMessageReceivers.add(messageReceiverName, std::make_pair(&workQueue, workQueueMessageReceiver));
    322 }
    323 
    324 void Connection::removeWorkQueueMessageReceiver(ReceiverName messageReceiverName)
     319    auto key = std::make_pair(static_cast<uint8_t>(messageReceiverName), destinationID);
     320    ASSERT(!m_workQueueMessageReceivers.contains(key));
     321
     322    m_workQueueMessageReceivers.add(key, std::make_pair(&workQueue, workQueueMessageReceiver));
     323}
     324
     325void Connection::removeWorkQueueMessageReceiver(ReceiverName messageReceiverName, uint64_t destinationID)
    325326{
    326327    ASSERT(RunLoop::isMain());
    327328
    328329    auto locker = holdLock(m_workQueueMessageReceiversMutex);
    329     ASSERT(m_workQueueMessageReceivers.contains(messageReceiverName));
    330     m_workQueueMessageReceivers.remove(messageReceiverName);
     330    auto key = std::make_pair(static_cast<uint8_t>(messageReceiverName), destinationID);
     331    ASSERT(m_workQueueMessageReceivers.contains(key));
     332    m_workQueueMessageReceivers.remove(key);
    331333}
    332334
     
    358360}
    359361
    360 void Connection::addThreadMessageReceiver(ReceiverName messageReceiverName, ThreadMessageReceiver* threadMessageReceiver)
     362void Connection::addThreadMessageReceiver(ReceiverName messageReceiverName, ThreadMessageReceiver* threadMessageReceiver, uint64_t destinationID)
    361363{
    362364    ASSERT(RunLoop::isMain());
    363365
    364366    auto locker = holdLock(m_threadMessageReceiversLock);
    365     ASSERT(!m_threadMessageReceivers.contains(messageReceiverName));
    366 
    367     m_threadMessageReceivers.add(messageReceiverName, threadMessageReceiver);
    368 }
    369 
    370 void Connection::removeThreadMessageReceiver(ReceiverName messageReceiverName)
     367    auto key = std::make_pair(static_cast<uint8_t>(messageReceiverName), destinationID);
     368    ASSERT(!m_threadMessageReceivers.contains(key));
     369
     370    m_threadMessageReceivers.add(key, threadMessageReceiver);
     371}
     372
     373void Connection::removeThreadMessageReceiver(ReceiverName messageReceiverName, uint64_t destinationID)
    371374{
    372375    ASSERT(RunLoop::isMain());
    373376
    374377    auto locker = holdLock(m_threadMessageReceiversLock);
    375     ASSERT(m_threadMessageReceivers.contains(messageReceiverName));
    376 
    377     m_threadMessageReceivers.remove(messageReceiverName);
     378    auto key = std::make_pair(static_cast<uint8_t>(messageReceiverName), destinationID);
     379    ASSERT(m_threadMessageReceivers.contains(key));
     380
     381    m_threadMessageReceivers.remove(key);
    378382}
    379383
     
    714718    }
    715719
    716     if (!WorkQueueMessageReceiverMap::isValidKey(message->messageReceiverName()) || !ThreadMessageReceiverMap::isValidKey(message->messageReceiverName())) {
     720    auto threadedReceiverKey = std::make_pair(static_cast<uint8_t>(message->messageReceiverName()), message->destinationID());
     721    if (!WorkQueueMessageReceiverMap::isValidKey(threadedReceiverKey) || !ThreadMessageReceiverMap::isValidKey(threadedReceiverKey)) {
    717722        RunLoop::main().dispatch([protectedThis = makeRef(*this), messageName = message->messageName()]() mutable {
    718723            protectedThis->dispatchDidReceiveInvalidMessage(messageName);
     
    10051010{
    10061011    auto locker = holdLock(m_workQueueMessageReceiversMutex);
    1007     auto it = m_workQueueMessageReceivers.find(message->messageReceiverName());
     1012    auto key = std::make_pair(static_cast<uint8_t>(message->messageReceiverName()), message->destinationID());
     1013    auto it = m_workQueueMessageReceivers.find(key);
    10081014    if (it != m_workQueueMessageReceivers.end()) {
    10091015        it->value.first->dispatch([protectedThis = makeRef(*this), workQueueMessageReceiver = it->value.second, decoder = WTFMove(message)]() mutable {
     
    10201026    {
    10211027        auto locker = holdLock(m_threadMessageReceiversLock);
    1022         protectedThreadMessageReceiver = m_threadMessageReceivers.get(message->messageReceiverName());
     1028        auto key = std::make_pair(static_cast<uint8_t>(message->messageReceiverName()), message->destinationID());
     1029        protectedThreadMessageReceiver = m_threadMessageReceivers.get(key);
    10231030    }
    10241031
  • trunk/Source/WebKit/Platform/IPC/Connection.h

    r264740 r268423  
    118118    };
    119119
    120     class ThreadMessageReceiver : public MessageReceiver, public ThreadSafeRefCounted<ThreadMessageReceiver> {
     120    class ThreadMessageReceiver : public MessageReceiver {
    121121    public:
    122         virtual void dispatchToThread(WTF::Function<void()>&&) { };
     122        virtual void dispatchToThread(WTF::Function<void()>&&) = 0;
     123
     124        void ref() { refMessageReceiver(); }
     125        void deref() { derefMessageReceiver(); }
     126
     127    protected:
     128        virtual void refMessageReceiver() = 0;
     129        virtual void derefMessageReceiver() = 0;
     130    };
     131
     132    class ThreadMessageReceiverRefCounted : public ThreadMessageReceiver, public ThreadSafeRefCounted<ThreadMessageReceiverRefCounted> {
     133    public:
     134        using ThreadSafeRefCounted::ref;
     135        using ThreadSafeRefCounted::deref;
     136
     137    private:
     138        void refMessageReceiver() final { ThreadSafeRefCounted::ref(); }
     139        void derefMessageReceiver() final { ThreadSafeRefCounted::deref(); }
    123140    };
    124141
     
    191208    void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback);
    192209
    193     void addWorkQueueMessageReceiver(ReceiverName, WorkQueue&, WorkQueueMessageReceiver*);
    194     void removeWorkQueueMessageReceiver(ReceiverName);
    195 
    196     void addThreadMessageReceiver(ReceiverName, ThreadMessageReceiver*);
    197     void removeThreadMessageReceiver(ReceiverName);
     210    void addWorkQueueMessageReceiver(ReceiverName, WorkQueue&, WorkQueueMessageReceiver*, uint64_t destinationID = 0);
     211    void removeWorkQueueMessageReceiver(ReceiverName, uint64_t destinationID = 0);
     212
     213    void addThreadMessageReceiver(ReceiverName, ThreadMessageReceiver*, uint64_t destinationID = 0);
     214    void removeThreadMessageReceiver(ReceiverName, uint64_t destinationID = 0);
    198215
    199216    bool open();
     
    350367
    351368    Lock m_workQueueMessageReceiversMutex;
    352     using WorkQueueMessageReceiverMap = HashMap<ReceiverName, std::pair<RefPtr<WorkQueue>, RefPtr<WorkQueueMessageReceiver>>, WTF::IntHash<ReceiverName>, WTF::StrongEnumHashTraits<ReceiverName>>;
     369    using WorkQueueMessageReceiverMap = HashMap<std::pair<uint8_t, uint64_t>, std::pair<RefPtr<WorkQueue>, RefPtr<WorkQueueMessageReceiver>>>;
    353370    WorkQueueMessageReceiverMap m_workQueueMessageReceivers;
    354371
    355372    Lock m_threadMessageReceiversLock;
    356     using ThreadMessageReceiverMap = HashMap<ReceiverName, RefPtr<ThreadMessageReceiver>, WTF::IntHash<ReceiverName>, WTF::StrongEnumHashTraits<ReceiverName>>;
     373    using ThreadMessageReceiverMap = HashMap<std::pair<uint8_t, uint64_t>, RefPtr<ThreadMessageReceiver>>;
    357374    ThreadMessageReceiverMap m_threadMessageReceivers;
    358375
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.cpp

    r267859 r268423  
    6161        Messages::RemoteAudioDestinationManager::CreateAudioDestination(inputDeviceId, numberOfInputChannels, numberOfOutputChannels, sampleRate),
    6262        Messages::RemoteAudioDestinationManager::CreateAudioDestination::Reply(destinationID, framesPerBuffer), 0);
    63     connection.messageReceiverMap().addMessageReceiver(Messages::RemoteAudioDestinationProxy::messageReceiverName(), destinationID.toUInt64(), *this);
     63
     64    auto offThreadRendering = [this, protectedThis = makeRef(*this)]() mutable {
     65        while (!m_threadTaskQueue.isKilled()) {
     66            if (auto task = m_threadTaskQueue.waitForMessage())
     67                task();
     68        }
     69    };
     70    m_renderThread = Thread::create("RemoteAudioDestinationProxy render thread", WTFMove(offThreadRendering), ThreadType::Audio);
     71
     72    connection.connection().addThreadMessageReceiver(Messages::RemoteAudioDestinationProxy::messageReceiverName(), this, destinationID.toUInt64());
    6473
    6574    m_destinationID = destinationID;
     
    7079{
    7180    auto& connection =  WebProcess::singleton().ensureGPUProcessConnection();
    72     connection.messageReceiverMap().removeMessageReceiver(Messages::RemoteAudioDestinationProxy::messageReceiverName(), m_destinationID.toUInt64());
     81    connection.connection().removeThreadMessageReceiver(Messages::RemoteAudioDestinationProxy::messageReceiverName(), m_destinationID.toUInt64());
    7382
    7483    connection.connection().sendWithAsyncReply(
     
    7685        // Can't remove this from proxyMap() here because the object would have been already deleted.
    7786    });
     87
     88    m_threadTaskQueue.kill();
     89    m_renderThread->waitForCompletion();
    7890}
    7991
     
    96108void RemoteAudioDestinationProxy::renderBuffer(const WebKit::RemoteAudioBusData& audioBusData, CompletionHandler<void()>&& completionHandler)
    97109{
    98     // FIXME: This does rendering on the main thread when AudioWorklet is not active, which is likely not a good idea.
    99     ASSERT(isMainThread());
     110    ASSERT(!isMainThread());
    100111    ASSERT(audioBusData.framesToProcess);
    101112    ASSERT(audioBusData.channelBuffers.size());
     
    104115        audioBus->setChannelMemory(i, (float*)audioBusData.channelBuffers[i]->data(), audioBusData.framesToProcess);
    105116
    106     auto doRender = [this, protectedThis = makeRef(*this), audioBus = WTFMove(audioBus), framesToProcess = audioBusData.framesToProcess, outputPosition = audioBusData.outputPosition] {
    107         m_callback.render(0, audioBus.get(), framesToProcess, outputPosition);
    108     };
    109     if (m_dispatchToRenderThread) {
    110         m_dispatchToRenderThread([doRender = WTFMove(doRender), completionHandler = WTFMove(completionHandler)]() mutable {
    111             doRender();
    112             callOnMainThread(WTFMove(completionHandler));
    113         });
    114     } else {
    115         doRender();
    116         completionHandler();
    117     }
     117    m_callback.render(0, audioBus.get(), audioBusData.framesToProcess, audioBusData.outputPosition);
     118    completionHandler();
    118119}
    119120
    120121void RemoteAudioDestinationProxy::didChangeIsPlaying(bool isPlaying)
    121122{
     123    ASSERT(!isMainThread());
     124}
     125
     126// IPC::Connection::ThreadMessageReceiver
     127void RemoteAudioDestinationProxy::dispatchToThread(Function<void()>&& task)
     128{
     129    if (m_dispatchToRenderThread) {
     130        m_dispatchToRenderThread(WTFMove(task));
     131        return;
     132    }
     133    m_threadTaskQueue.append(WTFMove(task));
    122134}
    123135
  • trunk/Source/WebKit/WebProcess/GPU/media/RemoteAudioDestinationProxy.h

    r267859 r268423  
    3434#include <WebCore/AudioDestination.h>
    3535#include <WebCore/AudioIOCallback.h>
     36#include <wtf/CrossThreadQueue.h>
     37#include <wtf/Threading.h>
    3638
    3739#if PLATFORM(COCOA)
     
    4143namespace WebKit {
    4244
    43 class RemoteAudioDestinationProxy : public WebCore::AudioDestination, private IPC::MessageReceiver {
    44     WTF_MAKE_FAST_ALLOCATED;
     45class RemoteAudioDestinationProxy : public WebCore::AudioDestination, public IPC::Connection::ThreadMessageReceiver {
    4546    WTF_MAKE_NONCOPYABLE(RemoteAudioDestinationProxy);
    4647public:
    4748    using AudioBus = WebCore::AudioBus;
    4849    using AudioIOCallback = WebCore::AudioIOCallback;
     50    using WebCore::AudioDestination::ref;
     51    using WebCore::AudioDestination::deref;
    4952
    5053    static Ref<AudioDestination> create(AudioIOCallback&, const String& inputDeviceId, unsigned numberOfInputChannels, unsigned numberOfOutputChannels, float sampleRate);
     
    6972    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
    7073
     74    // IPC::Connection::ThreadMessageReceiver
     75    void dispatchToThread(Function<void()>&&) final;
     76    void refMessageReceiver() final { WebCore::AudioDestination::ref(); }
     77    void derefMessageReceiver() final { WebCore::AudioDestination::deref(); }
     78
    7179    AudioIOCallback& m_callback;
    7280    float m_sampleRate { 0. };
     
    7583    bool m_isPlaying { false };
    7684    Function<void(Function<void()>&&)> m_dispatchToRenderThread;
     85    RefPtr<Thread> m_renderThread;
     86    CrossThreadQueue<Function<void()>> m_threadTaskQueue;
    7787};
    7888
  • trunk/Source/WebKit/WebProcess/Network/webrtc/LibWebRTCNetwork.h

    r264665 r268423  
    3636namespace WebKit {
    3737
    38 class LibWebRTCNetwork : public IPC::Connection::ThreadMessageReceiver {
     38class LibWebRTCNetwork : public IPC::Connection::ThreadMessageReceiverRefCounted {
    3939    WTF_MAKE_FAST_ALLOCATED;
    4040public:
  • trunk/Source/WebKit/WebProcess/cocoa/RemoteCaptureSampleManager.h

    r265725 r268423  
    4040namespace WebKit {
    4141
    42 class RemoteCaptureSampleManager : public IPC::Connection::ThreadMessageReceiver {
     42class RemoteCaptureSampleManager : public IPC::Connection::ThreadMessageReceiverRefCounted {
    4343    WTF_MAKE_FAST_ALLOCATED;
    4444public:
Note: See TracChangeset for help on using the changeset viewer.