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
;
32 * 2. if checker returns TRUE -> those whose timestamp is older than required
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
;
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())) {
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
;
98 // do not ask under lock
100 final Boolean shouldUpdateOld
= onlyAbsolute ?
false : myShouldUpdateOldChecker
.compute();
102 synchronized (myLock
) {
104 while (! myQueue
.isEmpty()) {
106 final Pair
<Long
, T
> pair
= myQueue
.get(0);
107 if (pair
.getFirst() == null) {
108 dirty
.add(myQueue
.removeFirst().getSecond());
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());
125 myInProgress
.addAll(dirty
);
128 LOG
.debug("found something to update: " + (! dirty
.isEmpty()));
131 myUpdater
.consume(t
);
132 synchronized (myLock
) {
133 if (myInProgress
.remove(t
)) {
134 myQueue
.addLast(new Pair
<Long
,T
>(System
.currentTimeMillis(), t
));