Index: pkg/analyzer/lib/src/context/cache.dart |
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart |
index 4443dfaad38d423c09730c98fc92551fe97e4f19..a6094216f7205e4d34128077c4502b53c45a28c6 100644 |
--- a/pkg/analyzer/lib/src/context/cache.dart |
+++ b/pkg/analyzer/lib/src/context/cache.dart |
@@ -41,20 +41,35 @@ class AnalysisCache { |
final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated = |
new ReentrantSynchronousStream<InvalidatedResult>(); |
+ final List< |
+ ReentrantSynchronousStreamSubscription> onResultInvalidatedPartitionSubscriptions = < |
+ ReentrantSynchronousStreamSubscription>[]; |
+ |
/** |
- * Initialize a newly created cache to have the given [partitions]. The |
+ * Initialize a newly created cache to have the given [_partitions]. The |
* partitions will be searched in the order in which they appear in the array, |
* so the most specific partition (usually an [SdkCachePartition]) should be |
* first and the most general (usually a [UniversalCachePartition]) last. |
*/ |
AnalysisCache(this._partitions) { |
for (CachePartition partition in _partitions) { |
- partition.onResultInvalidated.listen((InvalidatedResult event) { |
+ ReentrantSynchronousStreamSubscription<InvalidatedResult> subscription = |
+ partition.onResultInvalidated.listen((InvalidatedResult event) { |
onResultInvalidated.add(event); |
}); |
+ onResultInvalidatedPartitionSubscriptions.add(subscription); |
} |
} |
+ /** |
+ * Return an iterator returning all of the [Source] targets. |
+ */ |
+ Iterable<Source> get sources { |
+ return _partitions |
+ .map((CachePartition partition) => partition._sources) |
+ .expand((Iterable<Source> sources) => sources); |
+ } |
+ |
// TODO(brianwilkerson) Implement or delete this. |
// /** |
// * Return information about each of the partitions in this cache. |
@@ -73,12 +88,13 @@ class AnalysisCache { |
// } |
/** |
- * Return an iterator returning all of the [Source] targets. |
+ * Free any allocated resources and references. |
*/ |
- Iterable<Source> get sources { |
- return _partitions |
- .map((CachePartition partition) => partition._sources) |
- .expand((Iterable<Source> sources) => sources); |
+ void dispose() { |
+ for (ReentrantSynchronousStreamSubscription subscription |
+ in onResultInvalidatedPartitionSubscriptions) { |
+ subscription.cancel(); |
+ } |
} |
/** |
@@ -1042,7 +1058,7 @@ class Delta { |
} |
/** |
- * The possible results of validating analysis results againt a [Delta]. |
+ * The possible results of validating analysis results against a [Delta]. |
*/ |
enum DeltaResult { |
/** |
@@ -1118,8 +1134,27 @@ class ReentrantSynchronousStream<T> { |
* Note that if the [listener] fires a new event, then the [listener] will be |
* invoked again before returning from the [add] invocation. |
*/ |
- void listen(void listener(T event)) { |
+ ReentrantSynchronousStreamSubscription<T> listen(void listener(T event)) { |
listeners.add(listener); |
+ return new ReentrantSynchronousStreamSubscription<T>(this, listener); |
+ } |
+} |
+ |
+/** |
+ * A subscription on events from a [ReentrantSynchronousStream]. |
+ */ |
+class ReentrantSynchronousStreamSubscription<T> { |
+ final ReentrantSynchronousStream<T> _stream; |
+ final Function _listener; |
+ |
+ ReentrantSynchronousStreamSubscription(this._stream, this._listener); |
+ |
+ /** |
+ * Cancels this subscription. |
+ * It will no longer receive events. |
+ */ |
+ void cancel() { |
+ _stream.listeners.remove(_listener); |
} |
} |