RFR: 8023168 - Cleanup LogManager class initialization and LogManager/LoggerContext relationship
Daniel Fuchs
daniel.fuchs at oracle.com
Thu Sep 5 18:18:24 UTC 2013
Hi Martin,
Thanks for the cheers! :-)
I am incorporating your comments.
Thanks for spotting these issues!
best regards,
-- daniel
On 9/5/13 6:49 PM, Martin Buchholz wrote:
> Random review comments:
>
> Let me cheerlead your efforts to clean up j.u.logging. It's not easy.
> Previous efforts (including by myself) have been incomplete because of
> failure to fully understand the big picture.
>
> I've thought that the right approach for write-mostly data structure
> like in j.u.logging (and in e.g. classloading) is to have
> mostly-immutable parts with volatile pointers that are updated using CAS.
>
> You have some typos:
> LogMnager
> initalization
> initializationCalled
>
> + *
> + **/
>
> =>
>
> */
>
>
>
> On Thu, Sep 5, 2013 at 7:43 AM, Daniel Fuchs <daniel.fuchs at oracle.com
> <mailto:daniel.fuchs at oracle.com>> wrote:
>
> Hi,
>
> Here is the new patch. It uses an additional volatile flag
> to avoid synchronizing once the log manager is fully initialized.
> I have added some comments to spell out the purpose of the flags,
> as well as some assertion that should make it clear what is expected,
> what is possible, and what is not.
>
> I have also implemented the other remarks from David, Peter, and Mandy.
>
> <http://cr.openjdk.java.net/~__dfuchs/webrev_8023168/webrev.__01/
> <http://cr.openjdk.java.net/~dfuchs/webrev_8023168/webrev.01/>>
>
> Testing is still under way - but the results so far are looking good.
> I also ran the JCK for api/java_util - nothing jumped at my face.
>
> I have modified my NetBeans configuration to run NetBeans 7.3 over
> my private build - and I'm not seeing any troubles either so far.
>
> (I had done that with the previous patch too)
>
> best regards,
>
> -- daniel
>
>
>
> On 9/5/13 2:43 PM, Daniel Fuchs wrote:
>
> On 9/5/13 1:51 PM, Peter Levart wrote:
>
> Threads that call ensureLogManagerInitialized() after
> that will find
> the flag
> is true before entering the synchronized block and will
> return directly.
>
>
> ...and such threads can see rootLogger field being either
> still null or
> not null but the Logger instance that is obtained via such
> data race can
> be half-initialized.
>
>
> I don't think so, because the flag isn't set to true until
> the initialization is finished.
>
> BTW - there was a reason for having both an initializationCalled
> *and* a synchronized at method level. The purpose of
> initializationCalled flag was to prevent infinite recursion in the
> same thread - because addLogger within ensureLogManagerInitialized
> will trigger a new call to ensureLogManagerInitialized that the
> synchronized won't block - since it's in the same thread.
>
> So I need in fact two flags: one initializationDone - which will
> be volatile - the other initializationCalled - which doesn't need
> to be since it will be always written/read from within the
> synchronized block.
>
> I toyed with the idea of using a single volatile three valued byte
> instead:
>
> initialization: 0 => uninitialized, 1 => initializing, 2 =>
> initialized
>
> I opted for the two booleans - but the three valued byte might
> be more
> efficient:
>
> 1)
>
> volatile byte initialization = 0;
>
> ensureLogManagerInitialized() {
> if (initialization == 2) return; // already done
> synchronized(this) {
> if (initialization > 0) return;
> initialization = 1; // avoids recursion
> try {
> // do stuff which might recurse on
> // ensureLogManagerInitialized()
> } finally {
> initialization = 2; // mark as done
> }
> }
> }
>
> vs 2)
>
> volatile boolean initializationDone = false;
> boolean initializationCalled = false;
>
> ensureLogManagerInitialized() {
> if (initializationDone) return; // already done
> synchronized(this) {
> if (initializedCalled || initializationDone) return;
> initializedCalled = true; // avoids recursion
> try {
> // do stuff which might recurse on
> // ensureLogManagerInitialized()
> } finally {
> initializationDone = true; // mark as done.
> }
> }
> }
>
> Don't know if you have a preference for one or the other.
> My current impl (still under test) is 2)
>
> best regards,
>
> -- daniel
>
>
> I can make rootLogger volatile. I'm not 100% sure it is
> required - but
> I think
> it is more correct, and as such it will make the code
> more maintainable.
> Good point. It's probably something I would have
> overlooked.
>
>
>
> I think volatile rootLogger field is required for correct
> publication of
> RootLogger instances if double-checked locking is used...
>
>
> Regards, Peter
>
>
>
>
More information about the core-libs-dev
mailing list