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

Reply via email to