I think from this point of view an immutable object is just an extreme
case of an object with final fields, for which the final field export
issue is the only thread safety issue.

In thinking about all this, we must not assume that the way we do things
is the only way. I base my own multi-threaded Java on "Java Concurrency
in Practice", but the preface says:

=====================================================================
...we present a simplified set of rules for writing concurrent programs.
Experts may look at these rules and say "Hmmm, that's not entirely true:
class C is thread-safe even though it violates rule R."
=====================================================================

A program that consistently follows the JLCP recommendations is
multi-thread safe. A program that does not follow them may or may not be
multi-thread safe. We can't tell without doing detailed analysis against
the JLS.

Patricia

On 12/18/2013 4:42 AM, Peter wrote:
Pat your comment about non final fields is interesting.

Isn't it also the case that we need to safely publish an effectively immutable 
object to share it among threads?  That usually means copying it to a thread 
safe collection or shared via a synchronized method, volatile field, or final 
field in another object?

So we should also make sure that Jeri uses safe publication during export.

That would allow a service that has no final fields to start threads, then 
export from within a constructor safely, provided all operations on non final 
fields happen before starting threads and exporting.

All our services have final fields, so Starter is more appropriate for River's 
own services.

Regards,

Peter.

----- Original message -----
Hmm, good point, Startable, makes more sense.

An object can be exported using Startable.

I think we should have a policy to strongly discourage exporting from
constructors.

Regards,

Peter.

----- Original message -----
As far as I can tell, the special properties of completing a
constructor   in the JLS memory model are:

1. A happens-before edge from the end of the constructor to the start
of   a finalizer. (17.4.5)

2. The guarantee that any thread that only sees a reference to an
object   after the end of the constructor will see the correctly
initialized   values of all final fields. (17.5)

The special issue with final fields is that implementations have
freedom   to optimize access to final fields in ways that are not
permitted for   non-final fields. Strategies for thread safety that
work for non-final   fields do not necessarily work for final fields.
The requirement for   final field safety is that the constructor end
before another thread   accesses the newly constructed object.

Calling a start() method after construction if the class implements a
new interface seems to me to be harmless, backwards compatible, and
useful. It enables the simplest and most direct way of preventing
access   to the new object by another thread during construction.

The roadmap issue is whether it should be required, and if so the
level   of enforcement. For example, there is no reason to require it
if the   class does not declare any final fields.

Incidentally, and as a detail, "Commission" does not immediately make
me   think of having a start() method that should be called after
construction. If you do go this way, the name needs thought.
"Startable"   would be more obvious, more memorable, more likely to be
found on   searches, and more compatible with familiar interface names
such as   "Cloneable" and "Iterable".

Patricia


On 12/18/2013 2:18 AM, Peter wrote:
Well, now seems like a good time to have the conversation.

Yes there are other ways, but I haven't seen one safe implementation
yet, so...

Does someone have a better way to solve this problem, has someone
already solved this problem I'm unaware of that we can adopt, or is
there a way that's more satisfactory?

If not, is there something objectionable with the Commission
interface and if so, how can we fix it?

The SEVERE log message is logged by the River start package, other
containers or frameworks can choose whether or not to do so, but I'd
encourage them to do something similar, yes we can change it to WARN.

A much harsher option is to throw an exception during export which
breaks backward compatibility.

Regards,

Peter.

----- Original message -----
"org.apache.river.api.util.Commission is an interface services
should implement"

If it's a SHOULD, not a MUST, chucking out a SEVERE is incorrect
logger behaviour IMO. You could issue a WARN if you like but for
even that I'd say you need to provide a roadmap explaining why the
warning and what you intend to do in future and what you expect of
service writers such as myself.

Commission, at least from my point of view, is your means (maybe
the River community's - did you ask us?) for satisfying your needs
in respect of the JMM. As we've discussed previously, there are
other ways too and they work and they are safe if you know what
you're doing. Your contention was that most don't know what
they're doing hence, presumably, Commission.

So the thing is, you are seemingly on a road to asserting more
structure (gosh, a standard?) on the way people write their
services. If so, you'd best start flagging that honestly and openly
via a roadmap, deprecation and such/whatever rather than sticking
out logger messages with no clear guidance and at the cost of a
certain amount of nuisance (no admin I know likes SEVERE's being
logged for something which isn't critical cos it's noise they don't
want in log files).

And of course, we all know that when some entity asserts a standard
or requirement on others for entry, they may choose not to enter.
Does this help your community or hinder it? The answer to that is,
it depends. On what? Have you asked or tested? How have you tested?
What would be considered validation or lack of support?

I am not out to flame or troll rather I want to see this community
demonstrating good behaviour and I'm not feeling like what's going
on around Commission (what is that big change in version number
really saying?) is such.

On 18 December 2013 08:52, Peter <j...@zeus.net.au> wrote:

Just to clarify org.apache.river.api.util.Commission is an
interface services should implement, I would encourage all
container projects to pick up the interface and make suggestions
for improvement if there are any issues.

Interface Commission {
void start () throws Exception;
}

It's called after JMM safe construction to allow the service to
start any threads and be exported.

Regards,

Peter.

----- Original message -----

The way that services are instantiated and setup is an
implementation detail.          When I think of compatibility I
think of the API and the lookup methods.          We think of
compatibility from a client point of view.          From the
client point of view, using a service looks like this:

- Use multicast of unicast discovery to find one or more
ServiceRegistrar instances              - Call lookup(…) on one
or more of these instances to get a set of service candidates
             - Choose a candidate and prepare() it using a
ProxyPreparer, to yield a usable service proxy.              -
Make calls on it.          Ideally hang on to this proxy
instance, so you can skip the discovery and lookup next time
you need it.              - If the call fails, repeat the
lookup (and possibly discovery) til you get a proxy that works.

Nowhere does the client need to know whether the service
instance is started up using the “com.sun.jini.start”
mechanism, your Commission interface, some other IOC container
(Rio, Harvester, Seven or RiverContainer) or some unknown
mechanism that starts with a static main() method.

JSK2.0 was 2.0 because of the introduction of the proxy
verification mechanisms, as well as JERI.          Absent some
new client usage mechanism, River doesn’t need to go to 3.0.

Cheers,

Greg.



On Dec 17, 2013, at 1:58 PM, Peter <j...@zeus.net.au> wrote:

I think changing services to use safe construction techniques
is enough to cause the version jump.

At this point I've allowed services to continue unsafe
construction practices, while logging a SEVERE warning when
the Commission interface isn't implemented, rather than fail.

This is a fundamental change to the way services are written.

Regards,

Peter.

----- Original message -----

Assuming that there aren’t major incompatibilities, I think
that would be a “minor” version change according to our
versioning policy, so we’d be looking at the “2.3” branch
rather than a “3.0” release.

I’m still unnerved by the massive amounts of changes to
both code and tests in the qa_refactor branch, as well as
the apparent instability of the code, although that seems
to be improving.                  In the next few weeks I’m
going to try and setup a cross-test case, to see what the
“2.2” tests say about the potential “2.3” release and
vice-versa.

I think what I’d really like to see is an incremental
approach where we update limited components of the “2.2”
branch, one at a time. Is there anything that we could pull
out piecemeal? Maybe it
would
make sense to split out the infrastructure services, like
Reggie, Mahalo, and Outrigger into different sub-projects
that could be updated separately?

Any thoughts?

Greg.

On Dec 17, 2013, at 5:03 AM, Peter <j...@zeus.net.au>
wrote:

When the qa_refactor branch stabilises, I plan to merge
trunk and provide a beta release for client compatibility
testing.

Changes made have been focused on making our code thread
safe, there are significant changes internally, the
public api remains focused on backward compatibility,
however it is advisable that client services adopt new
safe construction techniques for services and implement
the new Commission interface.

What's a suitable test period for client testing?

Regards,

Peter.












Reply via email to