VCS: file changed remotely hint
[fedora-idea.git] / vcs-impl / src / com / intellij / openapi / vcs / changes / LazyRefreshingSelfQueue.java
blob31ed0140e76c4d940eb1c0474875597a2b39d125
1 package com.intellij.openapi.vcs.changes;
3 import com.intellij.openapi.diagnostic.Logger;
4 import com.intellij.openapi.util.Computable;
5 import com.intellij.openapi.util.Pair;
6 import com.intellij.util.Consumer;
7 import org.jetbrains.annotations.NotNull;
9 import java.util.*;
11 /**
12 * need to update:
13 * 1. if TS is null
14 * 2. if checker returns TRUE -> those whose timestamp is older than required
17 public class LazyRefreshingSelfQueue<T> {
18 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LazyRefreshingSelfQueue");
20 private final long myUpdateInterval;
21 // head is old. tail is new
22 private final LinkedList<Pair<Long, T>> myQueue;
23 private final Set<T> myInProgress;
24 private final Computable<Boolean> myShouldUpdateOldChecker;
25 private final Consumer<T> myUpdater;
26 private final Object myLock;
28 public LazyRefreshingSelfQueue(final long updateInterval, final Computable<Boolean> shouldUpdateOldChecker, final Consumer<T> updater) {
29 myUpdateInterval = updateInterval;
30 myShouldUpdateOldChecker = shouldUpdateOldChecker;
31 myUpdater = updater;
32 myQueue = new LinkedList<Pair<Long, T>>();
33 myInProgress = new HashSet<T>();
34 myLock = new Object();
37 public void addRequest(@NotNull final T t) {
38 synchronized (myLock) {
39 myQueue.addFirst(new Pair<Long,T>(null, t));
43 public void addRequests(final Collection<T> values) {
44 synchronized (myLock) {
45 for (T value : values) {
46 myQueue.addFirst(new Pair<Long,T>(null, value));
51 public void forceRemove(@NotNull final T t) {
52 synchronized (myLock) {
53 for (Iterator<Pair<Long, T>> iterator = myQueue.iterator(); iterator.hasNext();) {
54 final Pair<Long, T> pair = iterator.next();
55 if (t.equals(pair.getSecond())) {
56 iterator.remove();
59 myInProgress.remove(t);
63 // called by outside timer or something
64 public void updateStep() {
65 final List<T> dirty = new LinkedList<T>();
67 final long startTime = System.currentTimeMillis() - myUpdateInterval;
68 boolean onlyAbsolute = true;
69 // 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
70 synchronized (myLock) {
71 for (Pair<Long, T> pair : myQueue) {
72 if (pair.getFirst() != null) {
73 onlyAbsolute = pair.getFirst() < startTime;
74 break;
79 // do not ask under lock
80 final Boolean shouldUpdateOld = onlyAbsolute ? false : myShouldUpdateOldChecker.compute();
82 synchronized (myLock) {
83 // get absolute
84 while (! myQueue.isEmpty()) {
85 final Pair<Long, T> pair = myQueue.get(0);
86 if (pair.getFirst() == null) {
87 dirty.add(myQueue.removeFirst().getSecond());
88 } else {
89 break;
92 if (Boolean.TRUE.equals(shouldUpdateOld) && (! myQueue.isEmpty())) {
93 while (! myQueue.isEmpty()) {
94 final Pair<Long, T> pair = myQueue.get(0);
95 if (pair.getFirst() < startTime) {
96 myQueue.removeFirst();
97 dirty.add(pair.getSecond());
98 } else {
99 break;
104 myInProgress.addAll(dirty);
107 LOG.debug("found something to update: " + (! dirty.isEmpty()));
108 for (T t : dirty) {
109 myUpdater.consume(t);
110 synchronized (myLock) {
111 if (myInProgress.remove(t)) {
112 myQueue.addLast(new Pair<Long,T>(System.currentTimeMillis(), t));