On 29/01/13 07:44, Adam Murdoch wrote:
Implementation-wise, I would think about busting up building the task graph into 2 steps:

1. Build the task graph proper, with a node for each task in the graph and edges to represent the various types of dependencies.
2. Once the graph is built, calculate the execution plan:
- Take each node that has no incoming edges, sort them and then traverse each in turn.
- To traverse a node
- Take each soft dependency, sort them and traverse each in turn.
- Take each hard dependency, sort them and traverse each in turn.

I've finally managed to get the stuff that was preventing me from working on that out of the door and I'm looking into this again.

Buildinng a task graph seems to be a bit of an overkill to me for this feature as we can get away without it for now. There are two main problems I see with building the graph: - we would need to have three phases instead of the two you are mentioning - first build the graph with only 'hard' dependencies, then go through all nodes and add 'soft' dependencies (soft/always runs after dependencies can only be added when the nodes of the graph are known as a 'soft' dependency only kicks in if the task we should run after is in the graph) and only then perform a toposort - I don't feel competent enough to come up with how that graph should look like from the implementation point of view, what methods it should expose, etc

I believe the following is simpler and better for now:
- every time DefaultTaskExecutionPlan.addToTaskGraph() is called then create/update an unordered set of tasks that have to be executed and maintain a set of tasks that aren't dependencies of other tasks (have no incoming edges); the first set would be then used to check if a given 'soft' dependency should be taken into account when ordering and the second set would serve as the starting point for the toposort - add a CachingTaskDependencyResolveContext field to reuse resolved task dependecies between the two phases of the algorithm - add determineExecutionPlan() method that has to be called before any call to getTaskToExecute() and that performs a toposort the way you have described in the second phase of your algorithm with the result being what currently is the executionPlan field after the last call to addTaskToGraph() but with 'soft' dependencies taken into account.

I will start implementing it this way. Please let me know if you don't believe that this is the right way to go.

Reply via email to