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
;
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
;
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())) {
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
;
79 // do not ask under lock
80 final Boolean shouldUpdateOld
= onlyAbsolute ?
false : myShouldUpdateOldChecker
.compute();
82 synchronized (myLock
) {
84 while (! myQueue
.isEmpty()) {
85 final Pair
<Long
, T
> pair
= myQueue
.get(0);
86 if (pair
.getFirst() == null) {
87 dirty
.add(myQueue
.removeFirst().getSecond());
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());
104 myInProgress
.addAll(dirty
);
107 LOG
.debug("found something to update: " + (! dirty
.isEmpty()));
109 myUpdater
.consume(t
);
110 synchronized (myLock
) {
111 if (myInProgress
.remove(t
)) {
112 myQueue
.addLast(new Pair
<Long
,T
>(System
.currentTimeMillis(), t
));