blob: deaa51226affadac2c6dfea16e0c3d6352773fff [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library operation.queue;
import 'dart:collection';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analyzer/src/generated/source.dart';
/**
* A queue of operations in an [AnalysisServer].
*/
class ServerOperationQueue {
final List<Queue<ServerOperation>> _queues = <Queue<ServerOperation>>[];
ServerOperationQueue() {
for (int i = 0; i < ServerOperationPriority.COUNT; i++) {
var queue = new DoubleLinkedQueue<ServerOperation>();
_queues.add(queue);
}
}
/**
* Returns `true` if there are no queued [ServerOperation]s.
*/
bool get isEmpty {
return _queues.every((queue) => queue.isEmpty);
}
/**
* Adds the given operation to this queue. The exact position in the queue
* depends on the priority of the given operation relative to the priorities
* of the other operations in the queue.
*/
void add(ServerOperation operation) {
int queueIndex = operation.priority.ordinal;
Queue<ServerOperation> queue = _queues[queueIndex];
queue.addLast(operation);
}
/**
* Removes all elements in the queue.
*/
void clear() {
for (Queue<ServerOperation> queue in _queues) {
queue.clear();
}
}
/**
* Return the next operation to perform, or `null` if the queue is empty.
* This method does not change the queue.
*/
ServerOperation peek() {
for (Queue<ServerOperation> queue in _queues) {
if (!queue.isEmpty) {
return queue.first;
}
}
return null;
}
/**
* Reschedules queued operations according their current priorities.
*/
void reschedule() {
// prepare all operations
List<ServerOperation> operations = <ServerOperation>[];
for (Queue<ServerOperation> queue in _queues) {
operations.addAll(queue);
queue.clear();
}
// add all operations
operations.forEach(add);
}
/**
* The given [source] if about to changed.
*/
void sourceAboutToChange(Source source) {
for (Queue<ServerOperation> queue in _queues) {
queue.removeWhere((operation) {
if (operation is SourceSensitiveOperation) {
return operation.shouldBeDiscardedOnSourceChange(source);
}
return false;
});
}
}
/**
* Returns the next operation to perform or `null` if empty.
*/
ServerOperation take() {
for (Queue<ServerOperation> queue in _queues) {
if (!queue.isEmpty) {
return queue.removeFirst();
}
}
return null;
}
/**
* Returns an operation that satisfies the given [test] or `null`.
*/
ServerOperation takeIf(bool test(ServerOperation operation)) {
for (Queue<ServerOperation> queue in _queues) {
for (var operation in queue) {
if (test(operation)) {
queue.remove(operation);
return operation;
}
}
}
return null;
}
}