One benefit of allowing this flexibility may be the ability to re-use
your IoC container so that more configuration information is in one
place.

I haven't kept up with jdk1.5 but I am guessing the problem mentioned
below on double-locking has been resolved for that release.  I'm not
sure what performance hit the solution would cause but I would guess it
would be minor to force a shared memory area check for all threads.

I have seen features that basically read:  "Don't do this unless you
know what you're doing".  If the framework were to allow for one of
those rules in this case, then some people that know what they're doing
can put their own solution around the framework to start struts from
Spring for example.  I'm sure there are other thoughts that I wouldn't
even be able to guess right now.

This leads me to believe that documentation is the way to go for these
types of things to allow maximum flexibility.  To "code" in the
restriction removes the ability altogether.  If jdk1.5 does have the
volatility keyword doing the shared check you can even code it in now
and know that it will work whenever the user is in the environment that
supports it and have that in the documentation ("Only guaranteed with
1.5 forward", for example).

Since the project is open-source I would hope the most flexible approach
is adopted to allow others to add their own ingenuity.  If all config is
accessible for all projects it would be easier to embed the different
open source projects within one another.

Just my 2 cents...

Regards...djsuarez

-----Original Message-----
From: Craig McClanahan [mailto:[EMAIL PROTECTED] 
Sent: Sunday, December 19, 2004 3:01 PM
To: Struts Users Mailing List; [EMAIL PROTECTED]
Subject: Re: Dynamically adding an ActionMapping

On Sun, 19 Dec 2004 09:53:55 -0500, Frank W. Zammetti
<[EMAIL PROTECTED]> wrote:
> While I agree completely with your point about maintainability and
> testability (I can't think of a single situation where I would ever
> consider dynamic configuration modification), I'm interested in how
this
> might be allowed anyway...
> 
> Wouldn't it be possible to create a thread-safe modification method
that
> locks the underlying structures during modification?  I don't think
you
> need to ensure thread safety on the read operation, just the
> modification operation...

This is *exactly* where the problem lies.  If one looks inside the
implementation of HashMap, one sees that there are times when the
internal data structures are being modified, and are in a potentially
inconsistent state that would corrupt a read operation happening on a
simultaneously executing thread.  If you are accessing a HashMap with
read and write operations on multiple threads, the only safe thing to
do is lock all the reads, as well as all the writes.

There was actually an attempt at dealing with this issue -- the
FastHashMap class that was originally in Struts 1.0, and ended up in
Commons Collections.  The basic idea was that this map operated in one
of two modes:

* "Fast" mode lets you do reads without locks, while simultaneous
  writes make a copy of the entire Map, perform the update, and then
  replace the ponter to the internal data structure with a (hopefully)
  atomic operation.

* "Slow" mode locks all accesses for you.

However, enough people raised thread safety concerns about this class
that we chose not to use it in Struts 1.1.

A second approach you might look at is the "double checked locking"
idiom, where your read method would try to detect (via a flag or
something) that a write operation is in progress, and only lock if
that's the case.  However, nobody has been able to come up with a
reliable mechanism to enforce this, due to some of the intricate
details about how threading is done in a JVM (especially on
multiprocessor machines where the threads really *are* running
simultaneously) -- basically, it just doesn't work.  Google for
"Double Checked Locking is Broken" for more info on this.

> 
> You yourself said no locks are needed during read time when you know
the
> configuration won't change, and I assume that's the mechanism by which
> you assure the performance aspects, by simply not synchronizing during
> read... If that's the case, I would think simply synchronizing in the
> modification method would allow you to still have the performance
while
> introducing the ability to safely modify the configuration.

The "freeze" operation that is performed after the configuration data
is read prohibits any future operations that might change the
underlying maps -- that's what guarantees that we can safely read from
the maps without locking anything.

> 
> Granted, that introduces a bottleneck because every request would have
> to wait until any modification is complete, but I would consider it
the
> pervue of the app developer to decide if that's a problem or not (and
> make sure it isn't through reasonable usage of the ability and proper
> app architecture around it).

Per above, locking only the writes is not good enough.

> 
> I guess the question I should ask is when you say the configuration
"is
> frozen", is anything really done to make it read-only?  Or is it
simply
> the case that one COULD right now modify the configuration if they are
> willing to forgo thread safety?

Take a look at org.apache.struts.config.FormBeanConfig for an example
of how the protection guarantee is implemented (the other cases are
done in a similar way):

* The "formProperties" HashMap (containing the definitions
  of your properties for a DynaActionForm) is a protected variable,
  with no public way to access it.

* The only mutation mechanisms for this map are other methods
  in this class (addFormPropertyConfig() and removeFormPropertyConfig())
  that both check for the frozen state before allowing the modification,
  and throw an exception if it is frozen.

Thus, there is no mechanism in the standard implementation to bypass
the protection, as long as freeze() is called after all the
configuration has been done and requests haven't started yet.  Because
the configuration is done during the init() method of ActionServlet --
which the container guarantees to run to completion before any
requests are accepted -- that guarantee is completed as well.

Your only escape hatch is that you can subclass FormBeanConfig and use
your own copy instead -- but at that point you are on your own. 
Struts makes zero guarantees about thread safe access to the maps at
that point.

And if you do that to allow dynamic modifications, but don't lock on
the reads as well, I think you're walking across a very thin
tightrope, high above the floor, with no net.

Craig

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to