You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by gm...@apache.org on 2004/09/06 20:28:17 UTC

cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

gmazza      2004/09/06 11:28:17

  Modified:    src/java/org/apache/fop/fo FONode.java FOTreeBuilder.java
               src/java/org/apache/fop/fo/pagination Root.java
  Log:
  Switched to a static FOInputHandler object for the FOTree instead of relying on recursion to get to the FOInputHandler object stored at pagination.Root.
  
  Revision  Changes    Path
  1.43      +15 -1     xml-fop/src/java/org/apache/fop/fo/FONode.java
  
  Index: FONode.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/FONode.java,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- FONode.java	5 Sep 2004 04:00:51 -0000	1.42
  +++ FONode.java	6 Sep 2004 18:28:17 -0000	1.43
  @@ -41,6 +41,12 @@
   
       protected static String FO_URI = FOElementMapping.URI;
   
  +    /** 
  +     * FOInputHandler that handles FO events occurring 
  +     * during FO Tree processing.
  +     */
  +    protected static FOInputHandler foInputHandler = null;
  +
       /** Parent FO node */
       protected FONode parent;
   
  @@ -73,12 +79,20 @@
       }
   
       /**
  +     * Sets the FOInputHandler that the FOTree processing fires events to
  +     * @param inputHandler the FOInputHandler subclass to send FO events to
  +     */
  +    public static void setFOInputHandler(FOInputHandler inputHandler) {
  +        FONode.foInputHandler = inputHandler;
  +    } 
  +
  +    /**
        * Recursively goes up the FOTree hierarchy until the fo:root is found,
        * which returns the parent FOInputHandler.
        * @return the FOInputHandler object that is the parent of the FO Tree
        */
       public FOInputHandler getFOInputHandler() {
  -        return parent.getFOInputHandler();
  +        return FONode.foInputHandler;
       }
   
       /**
  
  
  
  1.47      +1 -1      xml-fop/src/java/org/apache/fop/fo/FOTreeBuilder.java
  
  Index: FOTreeBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/FOTreeBuilder.java,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- FOTreeBuilder.java	5 Sep 2004 04:00:51 -0000	1.46
  +++ FOTreeBuilder.java	6 Sep 2004 18:28:17 -0000	1.47
  @@ -217,6 +217,7 @@
        */
       public void startDocument() throws SAXException {
           rootFObj = null;    // allows FOTreeBuilder to be reused
  +        FONode.setFOInputHandler(foInputHandler);
           if (log.isDebugEnabled()) {
               log.debug("Building formatting object tree");
           }
  @@ -273,7 +274,6 @@
   
           if (rootFObj == null) {
               rootFObj = (Root) foNode;
  -            rootFObj.setFOInputHandler(foInputHandler);
           } else {
               currentFObj.addChildNode(foNode);
           }
  
  
  
  1.25      +0 -25     xml-fop/src/java/org/apache/fop/fo/pagination/Root.java
  
  Index: Root.java
  ===================================================================
  RCS file: /home/cvs/xml-fop/src/java/org/apache/fop/fo/pagination/Root.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- Root.java	4 Sep 2004 19:53:07 -0000	1.24
  +++ Root.java	6 Sep 2004 18:28:17 -0000	1.25
  @@ -49,11 +49,6 @@
        */
       private int runningPageNumberCounter = 0;
   
  -    /** 
  -     * Controlling FOTreeHandler object for this FO Tree
  -     */
  -    private FOInputHandler foInputHandler = null;
  -
       /**
        * @see org.apache.fop.fo.FONode#FONode(FONode)
        */
  @@ -200,26 +195,6 @@
        */
       public Bookmarks getBookmarks() {
           return bookmarks;
  -    }
  -
  -    /**
  -     * Sets the Document that this Root is attached to
  -     * @param document the apps.Document implementation to which this Root
  -     * is attached
  -     */
  -    public void setFOInputHandler(FOInputHandler foInputHandler) {
  -        this.foInputHandler = foInputHandler;
  -    }
  -
  -    /**
  -     * This method overrides the FONode version. The FONode version calls the
  -     * method by the same name for the parent object. Since Root is at the top
  -     * of the tree, it returns the actual FOInputHandler object. Thus, any FONode
  -     * can use this chain to find which FOInputHandler it is being built for.
  -     * @return the FOInputHandler implementation that this Root is attached to
  -     */
  -    public FOInputHandler getFOInputHandler() {
  -        return foInputHandler;
       }
   
       /**
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: fop-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: fop-cvs-help@xml.apache.org


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Jeremias Maerki <de...@greenmail.ch>.
To be a bit more positive and not just criticizing, this could probably
be solved using a ThreadLocal [1] which would make the whole thing
almost as handy as a normal static variable but thread-safe. But I've
never done this myself, yet, so I can't talk out of experience. Just an
additional 0.05 CHF.

[1] http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadLocal.html

On 06.09.2004 22:01:27 Jeremias Maerki wrote:
> Ok, the FOEventHandler is created in the FOTreeBuilder. One FO
> TreeBuilder is instantiated per processing run. The FOEventHandler is
> set on FONode's static variable during startDocument(). The
> FOEventHandler keeps track of used fonts, number of pages, tracking IDs
> etc. which are all relevant to one document run.
> 
> Now imagine a situation where multiple processing runs occur and just
> after the TreeBuilder sets the FOEventHandler on FONode in
> startDocument() and continues layout, another thread starts another
> processing run and runs through FOTreeBuilder.startDocument() before the
> whole layout process of the first processing run is finished. The second
> run will replace the FOEventHandler on FONode with a new one and the
> first thread will suddenly work on a different FOEventHandler because
> both threads access the same static variable. The behaviour will be
> non-deterministic.
> 
> Statics are often handy and seductive but are very dangerous in a
> multi-threaded environment. FOP is expected to work this way as many
> mails on fop-user prove. Statics are fine for constants and mostly ok
> for singletons and a few other opportunities, but I made it a rule for
> myself to be very catious when I think about using a static variable. I
> try to avoid them whenever possible.
> 
> On 06.09.2004 21:45:34 Glen Mazza wrote:
> > Please elaborate.
> > 
> > Jeremias Maerki wrote:
> > 
> > >I'm sorry, Glen, but I think you will have to revisit that one. If I'm
> > >not absolutely wrong, this will break multi-threading capabilities.
> > >
> > >On 06.09.2004 20:28:17 gmazza wrote:
> > >  
> > >
> > >>gmazza      2004/09/06 11:28:17
> > >>
> > >>  Modified:    src/java/org/apache/fop/fo FONode.java FOTreeBuilder.java
> > >>               src/java/org/apache/fop/fo/pagination Root.java
> > >>  Log:
> > >>  Switched to a static FOInputHandler object for the FOTree instead of relying on recursion to get to the FOInputHandler object stored at pagination.Root.



Jeremias Maerki


Multi-threading testbed (was: Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java)

Posted by Jeremias Maerki <de...@greenmail.ch>.
I've done that already. It wasn't so much work but I had to get rid of
the Avalon Fortress container first. It still uses the Avalon
Framework, though.

That's how it works: There's a sample configuration file in
test/java/org/apache/fop/threading that shows how to configure the MT
testbed. The filename to the configuration file is given to the Main
class as a command line parameter. The rest should be pretty easy to
manage. You can specify how many threads you want to run, which FO or
XML/XSLT combinations and how many times the tasks should be run until
the thread dies.

There's still a lot of room for improvements. I haven't bothered with
adjusting to the different configuration in HEAD, yet. It's just a small
tool for reproducing multi-threading problems.

And to cater for the curious: FOP really fails as soon as you run two
threads ATM.

Have fun.

On 07.09.2004 20:47:07 Jeremias Maerki wrote:
> I will try to dig up my multi-threading
> testbed I wrote for FOP maintenance branch a couple of years ago when we
> were tracking down multi-threading problems. It will need a bit of
> adjustment for HEAD but I think it makes sense to put it somewhere in
> the test directory so we can easily stress-test FOP.


Jeremias Maerki


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Glen Mazza <gr...@yahoo.com>.
I reverted it to the original recursive method, this
appears to be the best compromise for everyone's
wishes.  

Glen

--- Finn Bock <bc...@worldonline.dk> wrote:

> 
> >>> A (farfetched) argument against ThreadLocals
> would be that they 
> >>> prevent one FOP processing run to occur
> recursively during another 
> >>> independent processing run. Like an extension
> element that itself 
> >>> will attempt to process another fo document.
> 
> [Glen]
> 
> > I think that restriction is implicit in the XSL
> Recommendation, because 
> > fo:instream-foreign-object [1], has the
> requirement that its child be 
> > from a *non-XSL* namespace.  If the rec intended
> FO documents to be 
> > processed recursively, they wouldn't have had a
> non-XSL namespace 
> > requirement (i.e., why bother to require users to
> have a 
> > <finn:fodocument> that would just wrap <fo:root/>,
> if you can just use 
> > the latter tag directly?)  Indeed, this
> restriction could be an argument 
> > *for* using ThreadLocals.
> 
> No, not really.
> 
> ThreadLocals should be used for storing data that is
> local to each 
> thread (thread singletons). They are not a way to
> introduce global 
> variables which just so happens to work in tomcat.
> 
> regards,
> finn
> 
> 
> 


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Finn Bock <bc...@worldonline.dk>.
>>> A (farfetched) argument against ThreadLocals would be that they 
>>> prevent one FOP processing run to occur recursively during another 
>>> independent processing run. Like an extension element that itself 
>>> will attempt to process another fo document.

[Glen]

> I think that restriction is implicit in the XSL Recommendation, because 
> fo:instream-foreign-object [1], has the requirement that its child be 
> from a *non-XSL* namespace.  If the rec intended FO documents to be 
> processed recursively, they wouldn't have had a non-XSL namespace 
> requirement (i.e., why bother to require users to have a 
> <finn:fodocument> that would just wrap <fo:root/>, if you can just use 
> the latter tag directly?)  Indeed, this restriction could be an argument 
> *for* using ThreadLocals.

No, not really.

ThreadLocals should be used for storing data that is local to each 
thread (thread singletons). They are not a way to introduce global 
variables which just so happens to work in tomcat.

regards,
finn



Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Glen Mazza <gr...@yahoo.com>.
Jeremias Maerki wrote:

>On 07.09.2004 21:11:09 Finn Bock wrote:
>  
>
>>[Jeremias Maerki]
>>
>>    
>>
>>>Question to everyone: We currently don't have a multi-threaded design
>>>like Peter West's approach. Can anyone think of a reason that all the
>>>FO-building and layouting process for one processing run may run within
>>>more than one thread? I don't think threre is one if the SAX event
>>>delivery is always within one thread (big if). If there isn't I believe
>>>we could make use of a ThreadLocal to put some shared data that will be
>>>easily accessible from all involved components. Initialize the
>>>ThreadLocal in startDocument() and clear it in endDocument(). I realize
>>>there's a certain risk involved but it could really shorten the access
>>>ways for shared data especially for the FO tree, if that's really a
>>>problem (I'd also like to know if it really is. Anyone?).
>>>      
>>>
>>A (farfetched) argument against ThreadLocals would be that they prevent 
>>one FOP processing run to occur recursively during another independent 
>>processing run. Like an extension element that itself will attempt to 
>>process another fo document.
>>    
>>
>
>  
>
I think that restriction is implicit in the XSL Recommendation, because 
fo:instream-foreign-object [1], has the requirement that its child be 
from a *non-XSL* namespace.  If the rec intended FO documents to be 
processed recursively, they wouldn't have had a non-XSL namespace 
requirement (i.e., why bother to require users to have a 
<finn:fodocument> that would just wrap <fo:root/>, if you can just use 
the latter tag directly?)  Indeed, this restriction could be an argument 
*for* using ThreadLocals.

[1] 
http://www.w3.org/TR/2001/REC-xsl-20011015/slice6.html#fo_instream-foreign-object

>Good point, actually. IMO FOP should support rendering documents
>snippets. One use case for this is an FO paragraph or two within SVG (FO
>embedded in SVG embedded in FO). 
>

I don't think we should be encouraging that use case or developing in 
that direction.  Shouldn't the standard be to write your document using 
FO, and incorporate images using SVG as you need them?  Or, if the text 
handling capability of SVG is too primitive, to have subsequent versions 
of the SVG recommendation improve upon it, rather than have users move 
to the FO namespace within their SVG?

We *could* code to have FOP embed SVG embed FOP embed SVG over and over 
again, but I'm not sure it would buy the user anything over proper 
document planning as described above.

I also don't like the idea of "snippets"--non portable divergences from 
the XSL standard of having fo:root be the top of all FO documents.  We 
should not be encouraging users to starting their work with fo:blocks 
(it is only speculative what such FO's would mean absent their parents 
anyway.)  Let's wait until the XSL rec defines snippets first--they 
might do that someday, actually.

>And what a coincidence: I've had a
>discussion exactly today where we talked about rendering FO snippets to
>EMF (Windows enhanced metafile format) for inclusion in a Win32-based
>reporting engine.
>
>  
>

I would see another application calling FOP, providing a default 
fo:root-based structure around the snippet that the user provides (say, 
an fo:block).  But asking FOP to process a snippet with nothing else is 
kind of like asking javac to compile a class snippet (say, just an "if" 
statement.).  Too much to ask--compilers and FO Processors both have 
grammars to follow.

>>My preference would be to explicit pass the shared data (in this case 
>>the FOEventHandler) to the classes that needs it. If the recursion Glen 
>>discovered is deemed too slow, then store the FOEventHandler in an 
>>instance field for each FONode.
>>    
>>
>
>My preference, too. But having too much in FONode will generate a lot
>memory consumption. Just the logger instance in the maintenance branch
>takes up a lot of memory. As long as we can keep such a reference to
>count one I don't think this is such a big problem, however.
>
>  
>

>The ThreadLocal was just an intriguing idea but your comment already lets
>me dismiss it. It's probably more trouble than it's worth.
>
>
>Jeremias Maerki
>
>
>  
>

I'm not sure I would mind ThreadLocal here.  According to [2], it is 
kind of fast, at least in 1.4.  That, or returning to the old recursion 
method, appear to me to be the best options.

[2] http://www-106.ibm.com/developerworks/java/library/j-threads3.html

A third option, which may also have nice benefits, is getting rid of 
startElement() and endElement() within the FO's, and doing that all in 
FOTreeBuilder.

Glen


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Finn Bock <bc...@worldonline.dk>.
>>My preference would be to explicit pass the shared data (in this case 
>>the FOEventHandler) to the classes that needs it. If the recursion Glen 
>>discovered is deemed too slow, then store the FOEventHandler in an 
>>instance field for each FONode.

[Jeremias]

> My preference, too. But having too much in FONode will generate a lot
> memory consumption. 

Then maybe we can select some specific node types that will carry an 
actual reference to the FOEventHandler. Like fo:root (obviously), 
fo:flow and fo:block and all other node type will reference their 
parent. We can then pick the right tradeoff between memory and CPU.

It's just a thought.

regards,
finn

Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Jeremias Maerki <de...@greenmail.ch>.
On 07.09.2004 21:11:09 Finn Bock wrote:
> [Jeremias Maerki]
> 
> > Question to everyone: We currently don't have a multi-threaded design
> > like Peter West's approach. Can anyone think of a reason that all the
> > FO-building and layouting process for one processing run may run within
> > more than one thread? I don't think threre is one if the SAX event
> > delivery is always within one thread (big if). If there isn't I believe
> > we could make use of a ThreadLocal to put some shared data that will be
> > easily accessible from all involved components. Initialize the
> > ThreadLocal in startDocument() and clear it in endDocument(). I realize
> > there's a certain risk involved but it could really shorten the access
> > ways for shared data especially for the FO tree, if that's really a
> > problem (I'd also like to know if it really is. Anyone?).
> 
> A (farfetched) argument against ThreadLocals would be that they prevent 
> one FOP processing run to occur recursively during another independent 
> processing run. Like an extension element that itself will attempt to 
> process another fo document.

Good point, actually. IMO FOP should support rendering documents
snippets. One use case for this is an FO paragraph or two within SVG (FO
embedded in SVG embedded in FO). And what a coincidence: I've had a
discussion exactly today where we talked about rendering FO snippets to
EMF (Windows enhanced metafile format) for inclusion in a Win32-based
reporting engine.

> My preference would be to explicit pass the shared data (in this case 
> the FOEventHandler) to the classes that needs it. If the recursion Glen 
> discovered is deemed too slow, then store the FOEventHandler in an 
> instance field for each FONode.

My preference, too. But having too much in FONode will generate a lot
memory consumption. Just the logger instance in the maintenance branch
takes up a lot of memory. As long as we can keep such a reference to
count one I don't think this is such a big problem, however.

The ThreadLocal was just an intriguing idea but your comment already lets
me dismiss it. It's probably more trouble than it's worth.


Jeremias Maerki


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Glen Mazza <gr...@yahoo.com>.
--- Simon Pepping <sp...@leverkruid.nl> wrote:
> 
> PageLayoutManager has a seed for multithreading; it
> implements
> Runnable. The idea is to let each page sequence run
> in its own
> thread. It has not been worked out. 

I'm uncertain of its benefit (that which calls FOP
should do the multithreading, not FOP itself, no? 
e.g., a servlet generating 10 reports, one on each
thread, rather than have the servlet and FOP both
multithreading at the same time.)  I'm inclined to
have it removed, lest it turn into another distraction
from our work.  Anyway, if Xalan isn't
multithreading--and I don't believe they are--then I'm
unsure that we should be.

Glen


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Simon Pepping <sp...@leverkruid.nl>.
On Tue, Sep 07, 2004 at 08:47:07PM +0200, Jeremias Maerki wrote:
> 
> Question to everyone: We currently don't have a multi-threaded design
> like Peter West's approach. Can anyone think of a reason that all the
> FO-building and layouting process for one processing run may run within
> more than one thread? I don't think threre is one if the SAX event
> delivery is always within one thread (big if). If there isn't I believe
> we could make use of a ThreadLocal to put some shared data that will be
> easily accessible from all involved components. Initialize the
> ThreadLocal in startDocument() and clear it in endDocument(). I realize
> there's a certain risk involved but it could really shorten the access
> ways for shared data especially for the FO tree, if that's really a
> problem (I'd also like to know if it really is. Anyone?).

PageLayoutManager has a seed for multithreading; it implements
Runnable. The idea is to let each page sequence run in its own
thread. It has not been worked out. Using a ThreadLocal for
FOInputHandler would make this more difficult. This is not a typical
usage case for ThreadLocal as mentioned in the java documentation. I
do not find it an attractive idea.

Regards, Simon

-- 
Simon Pepping
home page: http://www.leverkruid.nl


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Finn Bock <bc...@worldonline.dk>.
[Jeremias Maerki]

> Question to everyone: We currently don't have a multi-threaded design
> like Peter West's approach. Can anyone think of a reason that all the
> FO-building and layouting process for one processing run may run within
> more than one thread? I don't think threre is one if the SAX event
> delivery is always within one thread (big if). If there isn't I believe
> we could make use of a ThreadLocal to put some shared data that will be
> easily accessible from all involved components. Initialize the
> ThreadLocal in startDocument() and clear it in endDocument(). I realize
> there's a certain risk involved but it could really shorten the access
> ways for shared data especially for the FO tree, if that's really a
> problem (I'd also like to know if it really is. Anyone?).

A (farfetched) argument against ThreadLocals would be that they prevent 
one FOP processing run to occur recursively during another independent 
processing run. Like an extension element that itself will attempt to 
process another fo document.

My preference would be to explicit pass the shared data (in this case 
the FOEventHandler) to the classes that needs it. If the recursion Glen 
discovered is deemed too slow, then store the FOEventHandler in an 
instance field for each FONode.

regards,
finn


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Jeremias Maerki <de...@greenmail.ch>.
On 07.09.2004 00:20:18 Glen Mazza wrote:
> Jeremias Maerki wrote:
> 
> >On 06.09.2004 22:31:24 Glen Mazza wrote:
> >  
> >
> >>Jeremias Maerki wrote:

<snip/>
> >What is an application in your terminology? I don't think there is such
> >a thing in Java. At least it's not a technical term but only a logical
> >one. If you deploy fop.jar using the boot classloader in Tomcat and
> >deploy two "applications" (each using a separate classloader for each
> >WAR file). Both webapps are using FOP in a different way, you still have
> >only one static foEventHandler variable which is shared between two
> >applications. That's probably a non-realistic approach for FOP, but
> >Xerces and Xalan are usually deployed this way.
> >  
> >
> OK, from what you're saying then, Xerces and Xalan should have no (or 
> next to no) static variables because they are so heavily shared (i.e., 
> stored in Tomcat /common or /shared directories).  Correct?

That's not the precise reason but you're on the right track. They don't
even have to be in the /common or /shared directories. Even if you put
Xalan in the WEB-INF/lib of your webapp (assume JDK 1.3, and assume
Xalan would make use of static variables to hold XSLT variables, which
it probably doesn't) you would run into problems because your Servlet
will be called within several threads simultaneously.

Not every static variable is bad. But if static variables are used to
communicate between components this will almost always leed to trouble
in my experience. As I said they are seductive because they are easy to
program with and you will probably get away with it if you're only
programming a GUI application, but as soon as you do server-side
programming this gets bad.

<snip/>

> Let me take a look at your two links first (Tomcat classloader and 
> ThreadLocal).   We'll get this reverted (to something) soon.

Fair enough. We've got time. I will try to dig up my multi-threading
testbed I wrote for FOP maintenance branch a couple of years ago when we
were tracking down multi-threading problems. It will need a bit of
adjustment for HEAD but I think it makes sense to put it somewhere in
the test directory so we can easily stress-test FOP.

Question to everyone: We currently don't have a multi-threaded design
like Peter West's approach. Can anyone think of a reason that all the
FO-building and layouting process for one processing run may run within
more than one thread? I don't think threre is one if the SAX event
delivery is always within one thread (big if). If there isn't I believe
we could make use of a ThreadLocal to put some shared data that will be
easily accessible from all involved components. Initialize the
ThreadLocal in startDocument() and clear it in endDocument(). I realize
there's a certain risk involved but it could really shorten the access
ways for shared data especially for the FO tree, if that's really a
problem (I'd also like to know if it really is. Anyone?).


Jeremias Maerki


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Glen Mazza <gr...@yahoo.com>.
Jeremias Maerki wrote:

>On 06.09.2004 22:31:24 Glen Mazza wrote:
>  
>
>>Jeremias Maerki wrote:
>>
>>    
>>
>>>Ok, the FOEventHandler is created in the FOTreeBuilder. One FO
>>>TreeBuilder is instantiated per processing run. The FOEventHandler is
>>>set on FONode's static variable during startDocument(). The
>>>FOEventHandler keeps track of used fonts, number of pages, tracking IDs
>>>etc. which are all relevant to one document run.
>>> 
>>>
>>>      
>>>
>>Incidentally, I'd like to get the fonts out of FOEventHandler, I think 
>>they should be declared only within those subclasses of FOEventHandler 
>>that need them.  But we can take up that issue later.
>>    
>>
>
>Here you need to be more precise. Are you talking about the set of
>available fonts or the set of used fonts within the document/processing
>run? The former is not a problem in this matter, but the other is as are
>the other examples I mentioned. They are specific to the rendering run.
>
>  
>
Let's leave this for now.  My thoughts on it aren't complete anyway.

>>>Now imagine a situation where multiple processing runs occur and just
>>>after the TreeBuilder sets the FOEventHandler on FONode in
>>>startDocument() and continues layout, another thread starts another
>>>processing run and runs through FOTreeBuilder.startDocument() before the
>>>whole layout process of the first processing run is finished. 
>>>
>>>      
>>>
>>But that would be another instance of the application, so that would be 
>>another instance's FOEventHandler that would be altered.  Statics are 
>>common to a running instance, not all running instances of the same 
>>application in general.  Please continue to elaborate.
>>    
>>
>
>A static variable is unique within the same classloader. If you deploy
>FOP as a servlet there is one classloader loading the FOP classes and
>FONode's static foEventHandler variable is shared between all instances
>of the Fop class and therefore between rendering runs. Now Tomcat can
>initiate multiple FOP rendering runs in multiple threads and that's
>where the trouble begins.
>
>  
>
I see now.  This would indeed be a problem--we will probably need to 
revert my change.

>What is an application in your terminology? I don't think there is such
>a thing in Java. At least it's not a technical term but only a logical
>one. If you deploy fop.jar using the boot classloader in Tomcat and
>deploy two "applications" (each using a separate classloader for each
>WAR file). Both webapps are using FOP in a different way, you still have
>only one static foEventHandler variable which is shared between two
>applications. That's probably a non-realistic approach for FOP, but
>Xerces and Xalan are usually deployed this way.
>  
>
OK, from what you're saying then, Xerces and Xalan should have no (or 
next to no) static variables because they are so heavily shared (i.e., 
stored in Tomcat /common or /shared directories).  Correct?

>A figure showing Tomcat's classloader hierarchy:
>http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html
>
>I think in your view of the things you'd have to provide a classloader
>for each instance of Fop to they don't bump into each other, but that's
>not what you will want.
>  
>

I agree--that would not be desirable.

>  
>
>>Also, are you aware of why I switched to a static?  To end the 
>>continuous recursion to the fo:root each time any of the child nodes 
>>need to call getFOEventHandler().startThisFormattingObject() and/or 
>>getFOEventHandler().endSomeFormattingObject().
>>    
>>
>
>Yes, I realize that. That's why I proposed looking at ThreadLocal after
>thinking some more about the problem. On the other side have you done
>speed checks to figure out if the recursion is really a problem? Java
>can optimize pretty well by itself and often it's not worth
>breaking your head. Also something I learned on this list.
>
>
>  
>
Let me take a look at your two links first (Tomcat classloader and 
ThreadLocal).   We'll get this reverted (to something) soon.

>Jeremias Maerki (off to bed...)
>
>
>  
>
At only 6pm?  ;-)  Anyway, thanks for the education today.

Glen


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Jeremias Maerki <de...@greenmail.ch>.
On 06.09.2004 22:31:24 Glen Mazza wrote:
> Jeremias Maerki wrote:
> 
> >Ok, the FOEventHandler is created in the FOTreeBuilder. One FO
> >TreeBuilder is instantiated per processing run. The FOEventHandler is
> >set on FONode's static variable during startDocument(). The
> >FOEventHandler keeps track of used fonts, number of pages, tracking IDs
> >etc. which are all relevant to one document run.
> >  
> >
> Incidentally, I'd like to get the fonts out of FOEventHandler, I think 
> they should be declared only within those subclasses of FOEventHandler 
> that need them.  But we can take up that issue later.

Here you need to be more precise. Are you talking about the set of
available fonts or the set of used fonts within the document/processing
run? The former is not a problem in this matter, but the other is as are
the other examples I mentioned. They are specific to the rendering run.

> >Now imagine a situation where multiple processing runs occur and just
> >after the TreeBuilder sets the FOEventHandler on FONode in
> >startDocument() and continues layout, another thread starts another
> >processing run and runs through FOTreeBuilder.startDocument() before the
> >whole layout process of the first processing run is finished. 
> >
> But that would be another instance of the application, so that would be 
> another instance's FOEventHandler that would be altered.  Statics are 
> common to a running instance, not all running instances of the same 
> application in general.  Please continue to elaborate.

A static variable is unique within the same classloader. If you deploy
FOP as a servlet there is one classloader loading the FOP classes and
FONode's static foEventHandler variable is shared between all instances
of the Fop class and therefore between rendering runs. Now Tomcat can
initiate multiple FOP rendering runs in multiple threads and that's
where the trouble begins.

What is an application in your terminology? I don't think there is such
a thing in Java. At least it's not a technical term but only a logical
one. If you deploy fop.jar using the boot classloader in Tomcat and
deploy two "applications" (each using a separate classloader for each
WAR file). Both webapps are using FOP in a different way, you still have
only one static foEventHandler variable which is shared between two
applications. That's probably a non-realistic approach for FOP, but
Xerces and Xalan are usually deployed this way.

A figure showing Tomcat's classloader hierarchy:
http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

I think in your view of the things you'd have to provide a classloader
for each instance of Fop to they don't bump into each other, but that's
not what you will want.

> Also, are you aware of why I switched to a static?  To end the 
> continuous recursion to the fo:root each time any of the child nodes 
> need to call getFOEventHandler().startThisFormattingObject() and/or 
> getFOEventHandler().endSomeFormattingObject().

Yes, I realize that. That's why I proposed looking at ThreadLocal after
thinking some more about the problem. On the other side have you done
speed checks to figure out if the recursion is really a problem? Java
can optimize pretty well by itself and often it's not worth
breaking your head. Also something I learned on this list.


Jeremias Maerki (off to bed...)


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Glen Mazza <gr...@yahoo.com>.
Jeremias Maerki wrote:

>Ok, the FOEventHandler is created in the FOTreeBuilder. One FO
>TreeBuilder is instantiated per processing run. The FOEventHandler is
>set on FONode's static variable during startDocument(). The
>FOEventHandler keeps track of used fonts, number of pages, tracking IDs
>etc. which are all relevant to one document run.
>  
>
Incidentally, I'd like to get the fonts out of FOEventHandler, I think 
they should be declared only within those subclasses of FOEventHandler 
that need them.  But we can take up that issue later.

>Now imagine a situation where multiple processing runs occur and just
>after the TreeBuilder sets the FOEventHandler on FONode in
>startDocument() and continues layout, another thread starts another
>processing run and runs through FOTreeBuilder.startDocument() before the
>whole layout process of the first processing run is finished. 
>
But that would be another instance of the application, so that would be 
another instance's FOEventHandler that would be altered.  Statics are 
common to a running instance, not all running instances of the same 
application in general.  Please continue to elaborate.

Also, are you aware of why I switched to a static?  To end the 
continuous recursion to the fo:root each time any of the child nodes 
need to call getFOEventHandler().startThisFormattingObject() and/or 
getFOEventHandler().endSomeFormattingObject().

Glen


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Jeremias Maerki <de...@greenmail.ch>.
Ok, the FOEventHandler is created in the FOTreeBuilder. One FO
TreeBuilder is instantiated per processing run. The FOEventHandler is
set on FONode's static variable during startDocument(). The
FOEventHandler keeps track of used fonts, number of pages, tracking IDs
etc. which are all relevant to one document run.

Now imagine a situation where multiple processing runs occur and just
after the TreeBuilder sets the FOEventHandler on FONode in
startDocument() and continues layout, another thread starts another
processing run and runs through FOTreeBuilder.startDocument() before the
whole layout process of the first processing run is finished. The second
run will replace the FOEventHandler on FONode with a new one and the
first thread will suddenly work on a different FOEventHandler because
both threads access the same static variable. The behaviour will be
non-deterministic.

Statics are often handy and seductive but are very dangerous in a
multi-threaded environment. FOP is expected to work this way as many
mails on fop-user prove. Statics are fine for constants and mostly ok
for singletons and a few other opportunities, but I made it a rule for
myself to be very catious when I think about using a static variable. I
try to avoid them whenever possible.

On 06.09.2004 21:45:34 Glen Mazza wrote:
> Please elaborate.
> 
> Jeremias Maerki wrote:
> 
> >I'm sorry, Glen, but I think you will have to revisit that one. If I'm
> >not absolutely wrong, this will break multi-threading capabilities.
> >
> >On 06.09.2004 20:28:17 gmazza wrote:
> >  
> >
> >>gmazza      2004/09/06 11:28:17
> >>
> >>  Modified:    src/java/org/apache/fop/fo FONode.java FOTreeBuilder.java
> >>               src/java/org/apache/fop/fo/pagination Root.java
> >>  Log:
> >>  Switched to a static FOInputHandler object for the FOTree instead of relying on recursion to get to the FOInputHandler object stored at pagination.Root.



Jeremias Maerki


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Glen Mazza <gr...@yahoo.com>.
Please elaborate.

Jeremias Maerki wrote:

>I'm sorry, Glen, but I think you will have to revisit that one. If I'm
>not absolutely wrong, this will break multi-threading capabilities.
>
>On 06.09.2004 20:28:17 gmazza wrote:
>  
>
>>gmazza      2004/09/06 11:28:17
>>
>>  Modified:    src/java/org/apache/fop/fo FONode.java FOTreeBuilder.java
>>               src/java/org/apache/fop/fo/pagination Root.java
>>  Log:
>>  Switched to a static FOInputHandler object for the FOTree instead of relying on recursion to get to the FOInputHandler object stored at pagination.Root.
>>    
>>
>
>
>Jeremias Maerki
>
>
>  
>


Re: cvs commit: xml-fop/src/java/org/apache/fop/fo/pagination Root.java

Posted by Jeremias Maerki <de...@greenmail.ch>.
I'm sorry, Glen, but I think you will have to revisit that one. If I'm
not absolutely wrong, this will break multi-threading capabilities.

On 06.09.2004 20:28:17 gmazza wrote:
> gmazza      2004/09/06 11:28:17
> 
>   Modified:    src/java/org/apache/fop/fo FONode.java FOTreeBuilder.java
>                src/java/org/apache/fop/fo/pagination Root.java
>   Log:
>   Switched to a static FOInputHandler object for the FOTree instead of relying on recursion to get to the FOInputHandler object stored at pagination.Root.


Jeremias Maerki