On 20/09/2013, at 9:31 AM, Marcin Erdmann <marcin.erdm...@proxerd.pl> wrote:

> I think I managed to fulfill all the requirements in the implementation I've 
> just pushed to my fork: https://github.com/erdi/gradle/tree/should-run-after.
> 
> In the end I went for a simpler and what looks to be a more efficient 
> solution. Basically when building the execution plan I track should run after 
> edges that were visited and take snapshots of execution plan for any visited 
> task that has should run after successors. When a cycle is detected (just 
> like before, if we end up in a previously visited node that we haven't yet 
> finished processing successors for) we check if we walked through any should 
> run after edges. If yes then we remove that edge from the graph, restore 
> execution plan to the state from before visiting the 'from node' of that edge 
> and start processing successors of that task from scratch. If there are no 
> should run after edges we travelled through and we detect a cycle then we 
> report it.

It's a neat idea.

> 
> I'll add some docs for this over the weekend. 
> 
> Marcin
> 
> 
> On Sat, Sep 14, 2013 at 4:23 PM, Marcin Erdmann <marcin.erdm...@proxerd.pl> 
> wrote:
> Hi all,
> 
> I started looking into how to implement shouldRunAfter task ordering rule. 
> Some time ago Adam wrote:
> 
> The idea is to add a very weak task execution rule that only provides hints 
> for execution order and implies nothing else. So, if A shouldRunAfterB then:
> 
> 1. If A or B are not scheduled to run, ignore the rule.
> 2. Run A after B only if there are no other contradictory rules on the 
> ordering of A and B. That is, ignore cycles introduced by shouldRunAfterrules.
> 3. The dependencies of A shouldRunAfter B and its dependencies.
> 4. If B fails or is not run, A can still be run.
> 5. If there is an idle worker thread and A is the only task whose 
> dependencies have been satisfied, then run A regardless of whether B has 
> beenrun or not. That is, prefer running the task over an idle worker thread.
> 
> Similar to mustRunAfter, but different in #2 and #5 above.
> 
> #1, #3 and #4 are straightforward. With regards to #2 the idea is to:
> at the beginning of DefaultTaskExecutionPlan.determineExecutionPlan() find 
> all cycles in the execution graph using CachingDirectedGraphWalker the same 
> way as in onOrderingCycle()
> find the first cycle that has no shouldRunAfter edges and throw a 
> CircularReferenceException
> if no such cycles are found iterate over all cycles and for each remove the 
> first found shouldRunAfter edge (possibly with some logging?) - this will 
> break the cycle; it's possible that a cycle won't have a shouldRunAfter edge 
> as some cycles may share a shouldRunAfter edge that has been already removed 
> but because we checked for cycles without shouldRunAfter edges before we know 
> that all cycles in this phase had such edge at one point
> continue with execution plan determination
> The downside here is that we would be adding another graph traversal to the 
> process. On the other hand I don't see how we could detect and break cycles 
> with shouldRunAfter edges in them without doing so.
> 
> With regards to #5, do I understand correctly that it simply means that 
> shouldRunAfter ordering should not be treated as a dependency in context of 
> TaskInfo.allDependenciesComplete()?
> 
> Marcin
>  
> 


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Join us at the Gradle eXchange 2013, Oct 28th in London, UK: 
http://skillsmatter.com/event/java-jee/gradle-exchange-2013



Reply via email to