Peter, 

sounds great. How does your implementation using threadLocal
works when going across <ant> or <antcall>? Just curious.

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]

Reply via email to