void AudioContext::deleteMarkedNodes() { ASSERT(isGraphOwner() || isAudioThreadFinished()); // Note: deleting an AudioNode can cause m_nodesToDelete to grow. size_t nodesDeleted = 0; while (size_t n = m_nodesToDelete.size()) { AudioNode* node = m_nodesToDelete[n - 1]; m_nodesToDelete.removeLast(); // Before deleting the node, clear out any AudioNodeInputs from m_dirtyAudioNodeInputs. unsigned numberOfInputs = node->numberOfInputs(); for (unsigned i = 0; i < numberOfInputs; ++i) m_dirtyAudioNodeInputs.remove(node->input(i)); // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs. unsigned numberOfOutputs = node->numberOfOutputs(); for (unsigned i = 0; i < numberOfOutputs; ++i) m_dirtyAudioNodeOutputs.remove(node->output(i)); // Finally, delete it. delete node; // Don't delete too many nodes per render quantum since we don't want to do too much work in the realtime audio thread. if (++nodesDeleted > MaxNodesToDeletePerQuantum) break; } }
bool AudioContext::tryLock(bool& mustReleaseLock) { ThreadIdentifier thisThread = currentThread(); bool isAudioThread = thisThread == audioThread(); // Try to catch cases of using try lock on main thread - it should use regular lock. ASSERT(isAudioThread || isAudioThreadFinished()); if (!isAudioThread) { // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do. lock(mustReleaseLock); return true; } bool hasLock; if (thisThread == m_graphOwnerThread) { // Thread already has the lock. hasLock = true; mustReleaseLock = false; } else { // Don't already have the lock - try to acquire it. hasLock = m_contextGraphMutex.tryLock(); if (hasLock) m_graphOwnerThread = thisThread; mustReleaseLock = hasLock; } return hasLock; }
void AudioContext::derefUnfinishedSourceNodes() { ASSERT(isMainThread() && isAudioThreadFinished()); for (unsigned i = 0; i < m_referencedNodes.size(); ++i) m_referencedNodes[i]->deref(AudioNode::RefTypeConnection); m_referencedNodes.clear(); }
void AudioContext::derefUnfinishedSourceNodes() { ASSERT(isMainThread() && isAudioThreadFinished()); for (auto& node : m_referencedNodes) node->deref(AudioNode::RefTypeConnection); m_referencedNodes.clear(); }
void AudioContext::derefFinishedSourceNodes() { ASSERT(isGraphOwner()); ASSERT(isAudioThread() || isAudioThreadFinished()); for (unsigned i = 0; i < m_finishedNodes.size(); i++) derefNode(m_finishedNodes[i]); m_finishedNodes.clear(); }
void AudioContext::derefFinishedSourceNodes() { ASSERT(isGraphOwner()); ASSERT(isAudioThread() || isAudioThreadFinished()); for (auto& node : m_finishedNodes) derefNode(node); m_finishedNodes.clear(); }
void AudioContext::markForDeletion(AudioNode* node) { ASSERT(isGraphOwner()); if (isAudioThreadFinished()) m_nodesToDelete.append(node); else m_nodesMarkedForDeletion.append(node); // This is probably the best time for us to remove the node from automatic pull list, // since all connections are gone and we hold the graph lock. Then when handlePostRenderTasks() // gets a chance to schedule the deletion work, updateAutomaticPullNodes() also gets a chance to // modify m_renderingAutomaticPullNodes. removeAutomaticPullNode(node); }
void AudioContext::deleteMarkedNodes() { ASSERT(isGraphOwner() || isAudioThreadFinished()); // Note: deleting an AudioNode can cause m_nodesToDelete to grow. size_t nodesDeleted = 0; while (size_t n = m_nodesToDelete.size()) { AudioNode* node = m_nodesToDelete[n - 1]; m_nodesToDelete.removeLast(); delete node; // Don't delete too many nodes per render quantum since we don't want to do too much work in the realtime audio thread. if (++nodesDeleted > MaxNodesToDeletePerQuantum) break; } }