Performs the given task when the scan finished. When no background scan is
running it performs the given task synchronously. When the background scan is
active it queues the given task and returns, the task is performed when the
background scan completes by the thread doing the background scan. The API
should be stable to NB 6.0.
The new API is a single public method runWhenScanFinished with the same
signature as the runUserActionTask method.
Created attachment 41259 [details]
A few comments:
1. How will the caller know if the task returned after completing the work or
the task got queued? This can be useful to take further action on the caller
side e.g. show wait cursor, progress bar and so on.
2. What is the relationship of the this thread doing the background scan and
the thread on which the regular runUserActionTasks() run? Can these two tasks
ever run in an interspersed fashion? Will the start of one cancel the other? I
think this need to be clarified.
3. In case the caller changes their mind how can they cancel the queed tasks?
Does the client have to come up with their own mechanism?
What if some kind of object was returned to indicate synchronous vs. queued
behavior. Could such object have the API to cancel the queued task?
[Sandip 2]: The background scan runs in the "Java Source Thread" (JST) this is
the same thread which performs the tasks registered by factories. When the
initial scan is running this tasks wait to the end of initial scan. The
difference is the tasks performed by the runUserActionTask which are performed
synchronously by the caller thread. The runUserActionTask firstly looks if the
JST is doing some task (including initial scan), if so it calls cancel on it (it
may take some time before the task ends and releases the java infrastructure
lock). Then it acquires the java infrastructure lock and performs synchronously
the given task. Finally it releases the java infrastructure lock and canceled
task is restarted.
When the runUserActionTask is called it stops background scan, after some time
it performs synchronously the given task and finally the background scan
continues. But actions which need usages database or resolve types should wait
when the background scan completes to get a correct state. For this the
runWhenScanFinished () is designed.
[Sandip 1,3] Currently user has to implement it, I agree that this may be
useful. I will add a return value. The problem is with the point 3 which
inherently introduces racecondition, but maybe it doesn't mind.
The raceconditio is: JST removes task from the queue, thread switch, user's
thread cancels the task, thread switch, JST performs even canceled task since in
the time of dispatch it was valid. So, the client of runWhenScanFinished cannot
rely on such a cancel anyway. The cancel mechanism may be implemented by the
task, which needs it, itself. For example if the task computes some data and
fills them into a view, it should check some synchronized flag at the beginning
of the task, also the fill method should be synchronized and recheck the flag.
The proposed cancel on the returned object from runWhenScanFinished can be
implemented without racecondition when the cancel will cal cancel on given task.
The task's cancel sets some flag canceled which is used to find out if it shoud
continue. But in this case the cancel can be called before the task run is
called. I believe it's not a problem, right?
Conclusion: I agree that the runWhenScanFinished should return result which can
be used to find out if the task was queued or performed. I am not sure with the
cancel mechanism, I need a feedback if the cancel even with problems mentioned
above is good for you.
Does runModificationTask() behaves differently than runUserActionTask() in
terms of cancelling the task/initial scan. I am wondering if we need similar
API corresponding to runModificationTask().
Is it possible to check the status of background scan without using this API.
Another minor suggestion is about API name. I personally think runAfterScan()
sounds better than run runWhenScanFinished.
For now I've changed the void runWhenScanFinished (CancellableTask,
boolean) to Future<Void> runWhenScanFinished (CancellableTask, boolean).
You can ask the future if it's already done Future.isDone(). You can
cancel it (the cancel can be called before CancellableTask.run).
Future.cancel(). And you can wait to the end of the task using Future.get().
[Deva 1] The CancellableTask.cancel used by runUserActionTask is useless since
the task passed to the JS.runUserActionTask are never canceled. They run
synchronously and has higher priority then the task registered by the factories.
I did the JS.runWhenScanFinished to keep the same semantics, the cancel on the
cancelable task in never called. If you call Future.cancel () and the background
scan is in progress it removes the deferred task from queue and returns true. If
the background scan is already finished and the posted tasks are performed or
are already done, the cancel returns false.
Created attachment 41440 [details]
Sandip agrees with the proposed API. I am going to integrate it.
Checking in apichanges.xml;
/cvs/java/source/apichanges.xml,v <-- apichanges.xml
new revision: 1.8; previous revision: 1.7
Checking in nbproject/project.properties;
/cvs/java/source/nbproject/project.properties,v <-- project.properties
new revision: 1.18; previous revision: 1.17
Checking in src/org/netbeans/api/java/source/JavaSource.java;
new revision: 1.45; previous revision: 1.44
Checking in src/org/netbeans/modules/java/source/classpath/GlobalSourcePath.java;
new revision: 1.8; previous revision: 1.7
Checking in src/org/netbeans/modules/java/source/usages/RepositoryUpdater.java;
new revision: 1.49; previous revision: 1.48
Checking in test/unit/src/org/netbeans/api/java/source/JavaSourceTest.java;
new revision: 1.11; previous revision: 1.10