IDEA-27603 (Indicate which branch is being worked on)
[fedora-idea.git] / platform / vcs-impl / src / com / intellij / openapi / vcs / changes / LazyRefreshingSelfQueue.java
blob7a8736af176544bb47ed0aeb2bdd7d75a543351b
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.vcs.changes;
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.progress.ProgressIndicator;
20 import com.intellij.openapi.progress.SomeQueue;
21 import com.intellij.openapi.util.Computable;
22 import com.intellij.openapi.util.Getter;
23 import com.intellij.openapi.util.Pair;
24 import com.intellij.util.Consumer;
25 import org.jetbrains.annotations.NotNull;
27 import java.util.*;
29 /**
30 * need to update:
31 * 1. if TS is null
32 * 2. if checker returns TRUE -> those whose timestamp is older than required
35 @SomeQueue
36 public class LazyRefreshingSelfQueue<T> {
37 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LazyRefreshingSelfQueue");
39 private final Getter<Long> myUpdateInterval;
40 // head is old. tail is new
41 private final LinkedList<Pair<Long, T>> myQueue;
42 private final Set<T> myInProgress;
43 private final Computable<Boolean> myShouldUpdateOldChecker;
44 private final Consumer<T> myUpdater;
45 private final Object myLock;
47 public LazyRefreshingSelfQueue(final Getter<Long> updateInterval, final Computable<Boolean> shouldUpdateOldChecker, final Consumer<T> updater) {
48 myUpdateInterval = updateInterval;
49 myShouldUpdateOldChecker = shouldUpdateOldChecker;
50 myUpdater = updater;
51 myQueue = new LinkedList<Pair<Long, T>>();
52 myInProgress = new HashSet<T>();
53 myLock = new Object();
56 public void addRequest(@NotNull final T t) {
57 synchronized (myLock) {
58 myQueue.addFirst(new Pair<Long,T>(null, t));
62 public void addRequests(final Collection<T> values) {
63 synchronized (myLock) {
64 for (T value : values) {
65 myQueue.addFirst(new Pair<Long,T>(null, value));
70 public void forceRemove(@NotNull final T t) {
71 synchronized (myLock) {
72 for (Iterator<Pair<Long, T>> iterator = myQueue.iterator(); iterator.hasNext();) {
73 final Pair<Long, T> pair = iterator.next();
74 if (t.equals(pair.getSecond())) {
75 iterator.remove();
78 myInProgress.remove(t);
82 // called by outside timer or something
83 public void updateStep(@NotNull final ProgressIndicator pi) {
84 final List<T> dirty = new LinkedList<T>();
86 final long startTime = System.currentTimeMillis() - myUpdateInterval.get();
87 boolean onlyAbsolute = true;
88 // check if we have some old items at all - if not, we would not check if repository latest revision had changed and will save time
89 synchronized (myLock) {
90 for (Pair<Long, T> pair : myQueue) {
91 if (pair.getFirst() != null) {
92 onlyAbsolute = pair.getFirst() > startTime;
93 break;
98 // do not ask under lock
99 pi.checkCanceled();
100 final Boolean shouldUpdateOld = onlyAbsolute ? false : myShouldUpdateOldChecker.compute();
102 synchronized (myLock) {
103 // get absolute
104 while (! myQueue.isEmpty()) {
105 pi.checkCanceled();
106 final Pair<Long, T> pair = myQueue.get(0);
107 if (pair.getFirst() == null) {
108 dirty.add(myQueue.removeFirst().getSecond());
109 } else {
110 break;
113 if (Boolean.TRUE.equals(shouldUpdateOld) && (! myQueue.isEmpty())) {
114 while (! myQueue.isEmpty()) {
115 final Pair<Long, T> pair = myQueue.get(0);
116 if (pair.getFirst() < startTime) {
117 myQueue.removeFirst();
118 dirty.add(pair.getSecond());
119 } else {
120 break;
125 myInProgress.addAll(dirty);
128 LOG.debug("found something to update: " + (! dirty.isEmpty()));
129 for (T t : dirty) {
130 pi.checkCanceled();
131 myUpdater.consume(t);
132 synchronized (myLock) {
133 if (myInProgress.remove(t)) {
134 myQueue.addLast(new Pair<Long,T>(System.currentTimeMillis(), t));