Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 1123603002: Process suspend() and resume() in call order (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Update according to review Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/modules/webaudio/AudioContext.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010, Google Inc. All rights reserved. 2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 AudioContext::~AudioContext() 144 AudioContext::~AudioContext()
145 { 145 {
146 #if DEBUG_AUDIONODE_REFERENCES 146 #if DEBUG_AUDIONODE_REFERENCES
147 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId ); 147 fprintf(stderr, "%p: AudioContext::~AudioContext(): %u\n", this, m_contextId );
148 #endif 148 #endif
149 deferredTaskHandler().contextWillBeDestroyed(); 149 deferredTaskHandler().contextWillBeDestroyed();
150 // AudioNodes keep a reference to their context, so there should be no way t o be in the destructor if there are still AudioNodes around. 150 // AudioNodes keep a reference to their context, so there should be no way t o be in the destructor if there are still AudioNodes around.
151 ASSERT(!m_isInitialized); 151 ASSERT(!m_isInitialized);
152 ASSERT(!m_activeSourceNodes.size()); 152 ASSERT(!m_activeSourceNodes.size());
153 ASSERT(!m_finishedSourceHandlers.size()); 153 ASSERT(!m_finishedSourceHandlers.size());
154 ASSERT(!m_suspendResolvers.size());
155 ASSERT(!m_isResolvingResumePromises); 154 ASSERT(!m_isResolvingResumePromises);
156 ASSERT(!m_resumeResolvers.size()); 155 ASSERT(!m_resumeResolvers.size());
157 } 156 }
158 157
159 void AudioContext::initialize() 158 void AudioContext::initialize()
160 { 159 {
161 if (isInitialized()) 160 if (isInitialized())
162 return; 161 return;
163 162
164 FFTFrame::initialize(); 163 FFTFrame::initialize();
(...skipping 590 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 return ScriptPromise::rejectWithDOMException( 754 return ScriptPromise::rejectWithDOMException(
756 scriptState, 755 scriptState,
757 DOMException::create( 756 DOMException::create(
758 InvalidAccessError, 757 InvalidAccessError,
759 "cannot suspend an OfflineAudioContext")); 758 "cannot suspend an OfflineAudioContext"));
760 } 759 }
761 760
762 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState); 761 RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver:: create(scriptState);
763 ScriptPromise promise = resolver->promise(); 762 ScriptPromise promise = resolver->promise();
764 763
765 // Save the resolver. If the context is running, it will get resolved at th e end of a rendering 764 if (m_contextState == Closed) {
766 // quantum. Otherwise, resolve it now. 765 resolver->reject(
767 m_suspendResolvers.append(resolver); 766 DOMException::create(InvalidStateError, "Cannot suspend a context th at has been closed"));
767 } else {
768 // Stop rendering now.
769 if (m_destinationNode)
770 stopRendering();
768 771
769 if (m_contextState != Running) { 772 // Since we don't have any way of knowing when the hardware actually sto ps, we'll just
770 // Context is not running so we can't wait for a rendering quantum to re solve the 773 // resolve the promise now.
771 // promise. Just resolve it now (along with any other pending suspend pr omises). 774 resolver->resolve();
772 resolvePromisesForSuspendOnMainThread();
773 } 775 }
774 776
775 return promise; 777 return promise;
776 } 778 }
777 779
778 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState) 780 ScriptPromise AudioContext::resumeContext(ScriptState* scriptState)
779 { 781 {
780 ASSERT(isMainThread()); 782 ASSERT(isMainThread());
781 AutoLocker locker(this); 783 AutoLocker locker(this);
782 784
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 if (tryLock()) { 897 if (tryLock()) {
896 // Take care of AudioNode tasks where the tryLock() failed previously. 898 // Take care of AudioNode tasks where the tryLock() failed previously.
897 deferredTaskHandler().breakConnections(); 899 deferredTaskHandler().breakConnections();
898 900
899 // Dynamically clean up nodes which are no longer needed. 901 // Dynamically clean up nodes which are no longer needed.
900 releaseFinishedSourceNodes(); 902 releaseFinishedSourceNodes();
901 903
902 deferredTaskHandler().handleDeferredTasks(); 904 deferredTaskHandler().handleDeferredTasks();
903 deferredTaskHandler().requestToDeleteHandlersOnMainThread(); 905 deferredTaskHandler().requestToDeleteHandlersOnMainThread();
904 906
905 resolvePromisesForSuspend();
906
907 unlock(); 907 unlock();
908 } 908 }
909 } 909 }
910 910
911 void AudioContext::resolvePromisesForResumeOnMainThread() 911 void AudioContext::resolvePromisesForResumeOnMainThread()
912 { 912 {
913 ASSERT(isMainThread()); 913 ASSERT(isMainThread());
914 AutoLocker locker(this); 914 AutoLocker locker(this);
915 915
916 for (auto& resolver : m_resumeResolvers) { 916 for (auto& resolver : m_resumeResolvers) {
(...skipping 17 matching lines...) Expand all
934 934
935 // Resolve any pending promises created by resume(). Only do this if we have n't already started 935 // Resolve any pending promises created by resume(). Only do this if we have n't already started
936 // resolving these promises. This gets called very often and it takes some t ime to resolve the 936 // resolving these promises. This gets called very often and it takes some t ime to resolve the
937 // promises in the main thread. 937 // promises in the main thread.
938 if (!m_isResolvingResumePromises && m_resumeResolvers.size() > 0) { 938 if (!m_isResolvingResumePromises && m_resumeResolvers.size() > 0) {
939 m_isResolvingResumePromises = true; 939 m_isResolvingResumePromises = true;
940 Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&A udioContext::resolvePromisesForResumeOnMainThread, this)); 940 Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&A udioContext::resolvePromisesForResumeOnMainThread, this));
941 } 941 }
942 } 942 }
943 943
944 void AudioContext::resolvePromisesForSuspendOnMainThread()
945 {
946 ASSERT(isMainThread());
947 AutoLocker locker(this);
948
949 // We can stop rendering now.
950 if (m_destinationNode)
951 stopRendering();
952
953 for (auto& resolver : m_suspendResolvers) {
954 if (m_contextState == Closed) {
955 resolver->reject(
956 DOMException::create(InvalidStateError, "Cannot suspend a contex t that has been closed"));
957 } else {
958 resolver->resolve();
959 }
960 }
961
962 m_suspendResolvers.clear();
963 }
964
965 void AudioContext::resolvePromisesForSuspend()
966 {
967 // This runs inside the AudioContext's lock when handling pre-render tasks.
968 ASSERT(isAudioThread());
969 ASSERT(isGraphOwner());
970
971 // Resolve any pending promises created by suspend()
972 if (m_suspendResolvers.size() > 0)
973 Platform::current()->mainThread()->postTask(FROM_HERE, threadSafeBind(&A udioContext::resolvePromisesForSuspendOnMainThread, this));
974 }
975
976 void AudioContext::rejectPendingResolvers() 944 void AudioContext::rejectPendingResolvers()
977 { 945 {
978 ASSERT(isMainThread()); 946 ASSERT(isMainThread());
979 947
980 // Audio context is closing down so reject any suspend or resume promises th at are still 948 // Audio context is closing down so reject any resume promises that are stil l pending.
981 // pending.
982
983 for (auto& resolver : m_suspendResolvers) {
984 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
985 }
986 m_suspendResolvers.clear();
987 949
988 for (auto& resolver : m_resumeResolvers) { 950 for (auto& resolver : m_resumeResolvers) {
989 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away")); 951 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
990 } 952 }
991 m_resumeResolvers.clear(); 953 m_resumeResolvers.clear();
992 m_isResolvingResumePromises = false; 954 m_isResolvingResumePromises = false;
993 } 955 }
994 956
995 const AtomicString& AudioContext::interfaceName() const 957 const AtomicString& AudioContext::interfaceName() const
996 { 958 {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 visitor->trace(m_listener); 1022 visitor->trace(m_listener);
1061 // trace() can be called in AudioContext constructor, and 1023 // trace() can be called in AudioContext constructor, and
1062 // m_contextGraphMutex might be unavailable. 1024 // m_contextGraphMutex might be unavailable.
1063 if (m_didInitializeContextGraphMutex) { 1025 if (m_didInitializeContextGraphMutex) {
1064 AutoLocker lock(this); 1026 AutoLocker lock(this);
1065 visitor->trace(m_activeSourceNodes); 1027 visitor->trace(m_activeSourceNodes);
1066 } else { 1028 } else {
1067 visitor->trace(m_activeSourceNodes); 1029 visitor->trace(m_activeSourceNodes);
1068 } 1030 }
1069 visitor->trace(m_resumeResolvers); 1031 visitor->trace(m_resumeResolvers);
1070 visitor->trace(m_suspendResolvers);
1071 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis itor); 1032 RefCountedGarbageCollectedEventTargetWithInlineData<AudioContext>::trace(vis itor);
1072 ActiveDOMObject::trace(visitor); 1033 ActiveDOMObject::trace(visitor);
1073 } 1034 }
1074 1035
1075 SecurityOrigin* AudioContext::securityOrigin() const 1036 SecurityOrigin* AudioContext::securityOrigin() const
1076 { 1037 {
1077 if (executionContext()) 1038 if (executionContext())
1078 return executionContext()->securityOrigin(); 1039 return executionContext()->securityOrigin();
1079 1040
1080 return nullptr; 1041 return nullptr;
(...skipping 24 matching lines...) Expand all
1105 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise 1066 // the destination node can GCed if JS has no references. stop() will also r esolve the Promise
1106 // created here. 1067 // created here.
1107 stop(); 1068 stop();
1108 1069
1109 return promise; 1070 return promise;
1110 } 1071 }
1111 1072
1112 } // namespace blink 1073 } // namespace blink
1113 1074
1114 #endif // ENABLE(WEB_AUDIO) 1075 #endif // ENABLE(WEB_AUDIO)
OLDNEW
« no previous file with comments | « Source/modules/webaudio/AudioContext.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698