void Resource::addClient(ResourceClient* client)
{
    ASSERT(!isPurgeable());

    if (m_preloadResult == PreloadNotReferenced) {
        if (isLoaded())
            m_preloadResult = PreloadReferencedWhileComplete;
        else if (m_requestedFromNetworkingLayer)
            m_preloadResult = PreloadReferencedWhileLoading;
        else
            m_preloadResult = PreloadReferenced;
    }
    if (!hasClients())
        memoryCache()->makeLive(this);

    if (!m_revalidatingRequest.isNull()) {
        m_clients.add(client);
        return;
    }

    // If we have existing data to send to the new client and the resource type supprts it, send it asynchronously.
    if (!m_response.isNull() && !shouldSendCachedDataSynchronouslyForType(type()) && !m_needsSynchronousCacheHit) {
        m_clientsAwaitingCallback.add(client);
        ResourceCallback::callbackHandler()->schedule(this);
        return;
    }

    m_clients.add(client);
    didAddClient(client);
    return;
}
void Resource::finishPendingClients()
{
    // We're going to notify clients one by one. It is simple if the client does nothing.
    // However there are a couple other things that can happen.
    //
    // 1. Clients can be added during the loop. Make sure they are not processed.
    // 2. Clients can be removed during the loop. Make sure they are always available to be
    //    removed. Also don't call removed clients or add them back.

    // Handle case (1) by saving a list of clients to notify. A separate list also ensure
    // a client is either in m_clients or m_clientsAwaitingCallback.
    Vector<ResourceClient*> clientsToNotify;
    copyToVector(m_clientsAwaitingCallback, clientsToNotify);

    for (const auto& client : clientsToNotify) {
        // Handle case (2) to skip removed clients.
        if (!m_clientsAwaitingCallback.remove(client))
            continue;
        m_clients.add(client);
        didAddClient(client);
    }

    // It is still possible for the above loop to finish a new client synchronously.
    // If there's no client waiting we should deschedule.
    bool scheduled = ResourceCallback::callbackHandler()->isScheduled(this);
    if (scheduled && m_clientsAwaitingCallback.isEmpty())
        ResourceCallback::callbackHandler()->cancel(this);

    // Prevent the case when there are clients waiting but no callback scheduled.
    ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled);
}
示例#3
0
void CachedResource::addClient(CachedResourceClient* client)
{
    if (addClientToSet(client))
        didAddClient(client);
}