~ubuntu-branches/debian/sid/eclipse-cdt/sid

« back to all changes in this revision

Viewing changes to results/plugins/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/Query.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2011-10-06 21:15:04 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20111006211504-8dutmljjih0zikfv
Tags: 8.0.1-1
* New upstream release.
* Split the JNI packages into a separate architecture dependent
  package and made eclipse-cdt architecture independent.
* Install JNI libraries into multiarch aware location
* Bumped Standards-Version to 3.9.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*******************************************************************************
2
 
 * Copyright (c) 2006, 2008 Wind River Systems and others.
3
 
 * All rights reserved. This program and the accompanying materials
4
 
 * are made available under the terms of the Eclipse Public License v1.0
5
 
 * which accompanies this distribution, and is available at
6
 
 * http://www.eclipse.org/legal/epl-v10.html
7
 
 * 
8
 
 * Contributors:
9
 
 *     Wind River Systems - initial API and implementation
10
 
 *******************************************************************************/
11
 
package org.eclipse.cdt.dsf.concurrent;
12
 
 
13
 
import java.util.concurrent.CancellationException;
14
 
import java.util.concurrent.ExecutionException;
15
 
import java.util.concurrent.Future;
16
 
import java.util.concurrent.TimeUnit;
17
 
import java.util.concurrent.TimeoutException;
18
 
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
19
 
 
20
 
import org.eclipse.core.runtime.CoreException;
21
 
 
22
 
 
23
 
/**
24
 
 * A convenience class that allows a client to retrieve data from services 
25
 
 * synchronously from a non-dispatch thread.  This class is different from
26
 
 * a Callable<V> in that it allows the implementation code to calculate
27
 
 * the result in several dispatches, rather than requiring it to return the 
28
 
 * data at end of Callable#call method.
29
 
 * <p>
30
 
 * Usage:<br/>
31
 
 * <pre>
32
 
 *     class DataQuery extends Query<Data> {
33
 
 *         protected void execute(DataRequestMonitor<Data> rm) {
34
 
 *             rm.setData(fSlowService.getData());
35
 
 *             rm.done();
36
 
 *         }
37
 
 *     }
38
 
 *     
39
 
 *     DsfExecutor executor = getExecutor();
40
 
 *     DataQuery query = new DataQuery();
41
 
 *     executor.submit(query);
42
 
 *     
43
 
 *     try {
44
 
 *         Data data = query.get();
45
 
 *     }
46
 
 *     
47
 
 * </pre>
48
 
 * <p> 
49
 
 * @see java.util.concurrent.Callable
50
 
 * 
51
 
 * @since 1.0
52
 
 */
53
 
@ThreadSafe
54
 
abstract public class Query<V> extends DsfRunnable 
55
 
    implements Future<V> 
56
 
{
57
 
    /** The synchronization object for this query */
58
 
    private final Sync fSync = new Sync();
59
 
 
60
 
    /** 
61
 
     * The no-argument constructor 
62
 
     */
63
 
    public Query() {}
64
 
    
65
 
    public V get() throws InterruptedException, ExecutionException { return fSync.doGet(); }
66
 
 
67
 
    public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
68
 
        return fSync.doGet(unit.toNanos(timeout));
69
 
    }
70
 
 
71
 
    /**
72
 
     * Don't try to interrupt the DSF executor thread, just ignore the request 
73
 
     * if set.
74
 
     */
75
 
    public boolean cancel(boolean mayInterruptIfRunning) {
76
 
        return fSync.doCancel(); 
77
 
    }
78
 
 
79
 
    public boolean isCancelled() { return fSync.doIsCancelled(); }
80
 
 
81
 
    public boolean isDone() { return fSync.doIsDone(); }
82
 
    
83
 
    
84
 
    protected void doneException(Throwable t) {
85
 
        fSync.doSetException(t);
86
 
    }        
87
 
    
88
 
    abstract protected void execute(DataRequestMonitor<V> rm);
89
 
    
90
 
    public void run() {
91
 
        if (fSync.doRun()) {
92
 
            try {
93
 
                /*
94
 
                 * Create the executor which is going to handle the completion of the
95
 
                 * request monitor.  Normally a DSF executor is supplied here which
96
 
                 * causes the request monitor to be invoked in a new dispatch loop.
97
 
                 * But since the query is a synchronization object, it can handle
98
 
                 * the completion of the request in any thread.  
99
 
                 * Avoiding the use of a DSF executor is very useful because queries are
100
 
                 * meant to be used by clients calling from non-dispatch thread, and there
101
 
                 * is a chance that a client may execute a query just as a session is being
102
 
                 * shut down.  In that case, the DSF executor may throw a 
103
 
                 * RejectedExecutionException which would have to be handled by the query.
104
 
                 */
105
 
                execute(new DataRequestMonitor<V>(ImmediateExecutor.getInstance(), null) {
106
 
                    @Override
107
 
                    public void handleCompleted() {
108
 
                        if (isSuccess()) fSync.doSet(getData());
109
 
                        else fSync.doSetException(new CoreException(getStatus()));
110
 
                    }
111
 
                });
112
 
            } catch(Throwable t) {
113
 
                /*
114
 
                 * Catching the exception here will only work if the exception 
115
 
                 * happens within the execute.  It will not work in cases when 
116
 
                 * the execute submits other runnables, and the other runnables
117
 
                 * encounter the exception.
118
 
                 */ 
119
 
                fSync.doSetException(t);
120
 
                
121
 
                /*
122
 
                 * Since we caught the exception, it will not be logged by 
123
 
                 * DefaultDsfExecutable.afterExecution().  So log it here.
124
 
                 */
125
 
                DefaultDsfExecutor.logException(t);
126
 
            }
127
 
        }
128
 
    }
129
 
    
130
 
    @SuppressWarnings("serial")
131
 
    final class Sync extends AbstractQueuedSynchronizer {
132
 
        private static final int STATE_RUNNING = 1;
133
 
        private static final int STATE_DONE = 2;
134
 
        private static final int STATE_CANCELLED = 4;
135
 
 
136
 
        private V fResult;
137
 
        private Throwable fException;
138
 
 
139
 
        private boolean ranOrCancelled(int state) {
140
 
            return (state & (STATE_DONE | STATE_CANCELLED)) != 0;
141
 
        }
142
 
 
143
 
        @Override
144
 
        protected int tryAcquireShared(int ignore) {
145
 
            return doIsDone()? 1 : -1;
146
 
        }
147
 
 
148
 
        @Override
149
 
        protected boolean tryReleaseShared(int ignore) {
150
 
            return true; 
151
 
        }
152
 
 
153
 
        boolean doIsCancelled() {
154
 
            return getState() == STATE_CANCELLED;
155
 
        }
156
 
        
157
 
        boolean doIsDone() {
158
 
            return ranOrCancelled(getState());
159
 
        }
160
 
 
161
 
        V doGet() throws InterruptedException, ExecutionException {
162
 
            acquireSharedInterruptibly(0);
163
 
            if (getState() == STATE_CANCELLED) throw new CancellationException();
164
 
            if (fException != null) throw new ExecutionException(fException);
165
 
            return fResult;
166
 
        }
167
 
 
168
 
        V doGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
169
 
            if (!tryAcquireSharedNanos(0, nanosTimeout)) throw new TimeoutException();                
170
 
            if (getState() == STATE_CANCELLED) throw new CancellationException();
171
 
            if (fException != null) throw new ExecutionException(fException);
172
 
            return fResult;
173
 
        }
174
 
 
175
 
        void doSet(V v) {
176
 
            while(true) {
177
 
                int s = getState();
178
 
                if (ranOrCancelled(s)) return;
179
 
                if (compareAndSetState(s, STATE_DONE)) break;
180
 
            }
181
 
            fResult = v;
182
 
            releaseShared(0);
183
 
        }
184
 
 
185
 
        void doSetException(Throwable t) {
186
 
            while(true) {
187
 
                int s = getState();
188
 
                if (ranOrCancelled(s)) return;
189
 
                if (compareAndSetState(s, STATE_DONE)) break;
190
 
            }
191
 
            fException = t;
192
 
            fResult = null;
193
 
            releaseShared(0);
194
 
        }
195
 
 
196
 
        boolean doCancel() {
197
 
            while(true) {
198
 
                int s = getState();
199
 
                if (ranOrCancelled(s)) return false;
200
 
                if (compareAndSetState(s, STATE_CANCELLED)) break;
201
 
            }
202
 
            releaseShared(0);
203
 
            return true;
204
 
        }
205
 
 
206
 
        boolean doRun() {
207
 
            return compareAndSetState(0, STATE_RUNNING); 
208
 
        }
209
 
    }
210
 
}
211