On Monday 20 October 2003 11:43, Jose Alberto Fernandez wrote: > Peter, > > sounds great. How does your implementation using threadLocal > works when going across <ant> or <antcall>? Just curious.
The local properties do not cross to the ant/antcall project. They could but I figured that as they are "local", they do not need to. Peter > > Jose Alberto > > > -----Original Message----- > > From: peter reilly [mailto:[EMAIL PROTECTED] > > Sent: 20 October 2003 09:59 > > To: Ant Developers List > > Subject: Re: Macrodef and parallel in a recursive situation > > > > > > I have written the code to support local properties. > > While I was doing this, I realized that the attributes > > of a macrodef could/should be local properties as well, > > removing some of the issues seen last week (use of attribute > > in a bsf script and support of parallel/recursive). > > > > The following shows it in using a new task called local. > > > > <project name="local"> > > <property name="prop1" value="a global value"/> > > <target name="test1"> > > <local name="prop1" value="a local value"/> > > <echo>prop1 is "${prop1}"</echo> > > </target> > > <target name="test2" depends="test1"> > > <echo>prop1 is "${prop1}"</echo> > > </target> > > </project> > > > > This ant test2 generates the following: > > > > test1: > > prop1 is "a local value" > > > > test2: > > prop1 is "a global value" > > > > Each taskcontainer sets up a new local scope: > > > > <target name="sequential"> > > <local name="prop2" value="in target"/> > > <sequential> > > <local name="prop2" value="in sequential"/> > > <echo>prop2 is "${prop2}"</echo> > > </sequential> > > <echo>prop2 is "${prop2}"</echo> > > </target> > > > > will generate the following: > > sequential: > > prop2 is "in sequential" > > prop2 is "in target" > > > > The value part of <local> is optional, and the local > > property may be set by a subsequent <property>, <property> > > will only set it if the value is not set. > > > > <target name="notset"> > > <local name="prop3"/> > > <echo>prop3 is "${prop3}"</echo> > > <property name="prop3" value="is set"/> > > <property name="prop3" value="is set again"/> > > <echo>prop3 is "${prop3}"</echo> > > </target> > > > > will generate the following: > > notset: > > prop3 is "${prop3}" > > prop3 is "is set" > > > > prop3 is still a local variable and will not be seen outside > > the target. > > > > The local properties are thread local so the following works > > as expected: > > <target name="parallel"> > > <local name="prop4"/> > > <parallel> > > <sequential> > > <property name="prop4" value="thread1"/> > > <echo>t1: prop4 is "${prop4}"</echo> > > </sequential> > > <sequential> > > <property name="prop4" value="thread2"/> > > <echo>t2: prop4 is "${prop4}"</echo> > > </sequential> > > <sequential> > > <property name="prop4" value="thread3"/> > > <echo>t3: prop4 is "${prop4}"</echo> > > </sequential> > > </parallel> > > </target> > > > > parallel: > > t2: prop4 is "thread2" > > t1: prop4 is "thread1" > > t3: prop4 is "thread3" > > > > Use with macrodef. > > ----------------- > > > > Attributes may now be implemented as local properties, which > > means that they will be seen as normal properties by ant > > tasks - including script. > > > > <target name="macro"> > > <macrodef name="callscript"> > > <attribute name="x"/> > > <sequential> > > <script language="beanshell"> > > System.out.println("x is '" + > > project.getProperty("x") + "'"); > > </script> > > </sequential> > > </macrodef> > > > > <callscript x="this is x"/> > > </target> > > > > will generate: > > macro: > > x is 'this is x' > > > > Macrodef does not do the attribute substitutions so the following > > <target name="macro2"> > > <macrodef name="callscript"> > > <attribute name="x"/> > > <sequential> > > <script language="beanshell"> > > System.out.println("x is '${x}'"); > > </script> > > </sequential> > > </macrodef> > > > > <callscript x="this is x"/> > > </target> > > will generate: > > macro2: > > x is '${x}' > > as <script/> does not do property expansion. > > > > A variation of the recurive macrodef last week may be done by: > > <target name="recur"> > > <macrodef name="recur"> > > <attribute name="thread"/> > > <attribute name="current"/> > > <sequential> > > <antcontrib:if> > > <equals arg1="0" arg2="${current}"/> > > <then> > > <echo message="Thread: ${thread} done"/> > > </then> > > <else> > > <antcontrib:math > > datatype = "int" > > operand1 = "${current}" > > operation = "-" > > operand2 = "1" > > result = "current" > > /> > > <echo message = "T: ${thread}, C: ${current}" /> > > <sleep seconds="1"/> > > <recur current = "${current}" thread = "${thread}" /> > > </else> > > </antcontrib:if> > > </sequential> > > </macrodef> > > > > <parallel> > > <recur thread="1" current="5"/> > > <recur thread="2" current="6"/> > > <recur thread="3" current="2"/> > > </parallel> > > </target> > > > > The output is: > > recur: > > T: 3, C: 1 > > T: 1, C: 4 > > T: 2, C: 5 > > T: 3, C: 0 > > T: 1, C: 3 > > T: 2, C: 4 > > Thread: 3 done > > T: 1, C: 2 > > T: 2, C: 3 > > T: 1, C: 1 > > T: 2, C: 2 > > T: 1, C: 0 > > T: 2, C: 1 > > Thread: 1 done > > T: 2, C: 0 > > Thread: 2 done > > > > > > > > I realize that it is late in the day to get this > > into ant1.6, but I think that it will make macrodef > > much more usefull and easy to port current antcalls. > > > > The changes are quite small (mostly to PropertyHelper). > > > > Peter > > > > On Saturday 18 October 2003 16:22, Jose Alberto Fernandez wrote: > > > > From: peter reilly [mailto:[EMAIL PROTECTED] > > > > > > > > I think that we may need a thread local variable to > > > > handle parallel. > > > > > > > > This would mean some deep messing with the Property handling. > > > > > > I do not see how thread locals would help here. I guess the > > > > question > > > > > is whether tasks in parallel should be able to modify the global > > > properties in the frame, or should the changes be local to the > > > parallel branch (and somehow joined at the end of execution). > > > > > > That would mean each parallel computation branch is independent. I > > > guess I am suggesting the second type of implementation > > > > proposed for > > > > > <local-property> to be used instead for <parallel>. I think > > > > that would > > > > > be a much more efficient way to do it. So here is how it would work: > > > > > > 1) Add new attribute independent (default false) to <parallel>. > > > > > > 2) When independent is true, each thread will use a cloned project > > > frame for its execution. So all properties and reference > > > > manipulation > > > > > will be independent of each other. When the thread ends, any new > > > properties added in the cloned frame, will be added to the original > > > parent frame, following the common rules for setting > > > > properties. Which > > > > > means that the first thread that finish will win on setting the > > > property, if another thread ends later and tries to set the same > > > variable, it will loose. For references, we need to copy > > > > any changes > > > > > and due to its semantics all threads will contribute as they end. > > > > > > 3) When independent is false, parallel works as today (for backward > > > compatibility), all threads see each others changes. > > > > > > This rules seem easy programable without big changes to CORE. > > > > > > I would still like having <local-property> which could be > > > > implemented > > > > > as per the first description proposed below. > > > > > > Jose Alberto > > > > > > > Peter > > > > > > > > On Friday 17 October 2003 17:57, Jose Alberto Fernandez wrote: > > > > > > From: peter reilly [mailto:[EMAIL PROTECTED] > > > > > > > > > > > > I would rather have Jose's idea of a <local-property/> task. > > > > > > > > > > > > This could be used outside of macrodef. > > > > > > > > > > > > The only problem is the implementation. > > > > > > > > > > Indeed, there is an easy implementation but will not solve > > > > > > > > the case of > > > > > > > > > <parallel>, because the local definition would really be a > > > > > > > > temporary > > > > > > > > > global one: > > > > > > > > > > public class LocalProperty extends Sequential { > > > > > private String property; > > > > > private String oldValue; > > > > > > > > > > public setName(String i_property){property = i_property;} > > > > > > > > > > public void execute() { > > > > > if (property == null) throw new BuildException("name > > > > > > > > attribute is > > > > > > > > > mandatory"); > > > > > try { > > > > > oldValue = getProject().getProperty(property); > > > > > getProject().setProperty(property, null); // This > > > > may need > > > > > > > changes to core > > > > > super.execute(); > > > > > } > > > > > finally { > > > > > // This is using the deprecated setProperty method > > > > > // that actually changes the properties even if set > > > > > getProject().setProperty(property, oldValue); > > > > > } > > > > > } > > > > > } > > > > > > > > > > Here we just change the property value on the project > > > > > > > > frame, for the > > > > > > > > > duration of the task. And put the old value back before > > > > we leave. > > > > > > > The problem with this simple implementation is that all the > > > > > > > > parallel > > > > > > > > > branches will see the change, which is exactly what we were > > > > > > > > trying to > > > > > > > > > avoid. To do it > > > > > right, we would need to create a new execution frame that > > > > > > > > would be use > > > > > > > > > in the > > > > > "super" call. > > > > > > > > > > But if we do that (which is like what <ant> or > > > > <antcall> do), what > > > > > > > happens if the user defines properties other than the > > > > > > > > local-property > > > > > > > > > inside the code? > > > > > Somehow, we would need to find them and propagate them back > > > > > > > > to the frame > > > > > > > > > above > > > > > upon exit. > > > > > > > > > > <local-property name="x"> > > > > > <property name="y" value="myY"/> > > > > > <local-property> > > > > > <echo message="${y}"/> > > > > > > > > > > [echo] myY > > > > > > > > > > Doable, but not that easy anymore. > > > > > > > > > > What do you guys think? > > > > > > > > > > Jose Alberto > > > > > > > > > > > Peter > > > > --------------------------------------------------------------------- > > > > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]