Gregg Wonderly wrote:
I'm thinking more and more that this runAfter business should really be
a O(1) thing. If runAfter() is implemented to return true, can not that
decision be made at the time of enqueue? It just looks like so much of
this is spread around to so few actual users in the current API. As I
look over the usages, there is some fuzzy logic involved in some cases
where the sequence number is used for ordering. In a couple of other
cases, there is a specific task that another task wants to run after.
In the end, it seems like the API should be
something more like
TaskManager.addAfter( Task myTask, Task dependedOnTask );
and, there would be something like
TaskManager.addWithSequencer( Task myTask, new Sequencer() {
public void runAfter( List<Task> lst, int cnt ) {
// search lst and return result
}
});
So that simple checks can be made for "hasSequencer". The first
case could just result in a call like
TaskManager.addWithSequencer( Task myTask, new Sequencer() {
public void runAfter( List<Task> lst, int cnt ) {
int idx = lst.indexOf( dependedOnTask );
return idx >= 0 && idx < cnt;
}
});
...
One detail on this. A lot of the problem with the original TaskManager
implementation was over-reliance on ArrayList. In general, random access
by index is the enemy of efficient queue-like operations. Linked lists,
or something like TreeSet, make efficient queues but have inefficient
index access. I think it is very important to remove any commitment to
indexed access from the interfaces.
Given the number of non-sequence callers, I'm seriously considering a
SimpleTaskManager that knows nothing at all about dependencies between
tasks and has no data structures to support them. It would do no run
time tests for the existence of sequence rules. Added tasks would
unconditionally go straight to the ready state, and into the data
structure for allocation to threads.
I might make its Task an abstract class, rather than interface. That
way, I can make runAfter a final method preventing specification of a
runAfter in an extending class. I could also get rid of my TaskWrapper,
because the abstract base class could carry any per-task data the
implementation needs.
Patricia