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); }
void CachedResource::addClient(CachedResourceClient* client) { if (addClientToSet(client)) didAddClient(client); }