This implementation is threadsafe. On 24 September 2014 09:24, Gary Gregory <garydgreg...@gmail.com> wrote:
> Hm... so how do we pick one. Are there cases w/i Log4j where we'd want one > in one case and the other in another case? > > Hm... I am warming up to having the same states as OSGi... > > Gary > > On Wed, Sep 24, 2014 at 9:07 AM, Matt Sicker <boa...@gmail.com> wrote: > >> Looks like I meant to add this to a different branch. This is how I think >> LifeCycle classes should work, though, so feedback would be good. If >> possible, I'd like to replace the current ALC with the proposed AALC (which >> would just be renamed to AbstractLifeCycle). >> >> On 24 September 2014 06:43, Gary Gregory <garydgreg...@gmail.com> wrote: >> >>> Hm... and why does start() behave differently in AALC from ALC? AALC is >>> not used either... so... what is it in there for? >>> >>> Gary >>> >>> On Wed, Sep 24, 2014 at 7:37 AM, Gary Gregory <garydgreg...@gmail.com> >>> wrote: >>> >>>> Do we really want two LifeCycle abstract classes? >>>> >>>> Will this not be a case -- like plug in builders vs. factory methods -- >>>> where we have two ways of doing the same thing? >>>> >>>> When do I use one vs. the other? You'd need to Javadoc that at least. >>>> >>>> Shouldn't we just have one way of doing this? >>>> >>>> Gary >>>> ---------- Forwarded message ---------- >>>> From: <mattsic...@apache.org> >>>> Date: Wed, Sep 24, 2014 at 1:39 AM >>>> Subject: [2/4] git commit: Add LifeCycle abstract class that uses >>>> AtomicReference. >>>> To: comm...@logging.apache.org >>>> >>>> >>>> Add LifeCycle abstract class that uses AtomicReference. >>>> >>>> >>>> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo >>>> Commit: >>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/1a332afa >>>> Tree: >>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1a332afa >>>> Diff: >>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1a332afa >>>> >>>> Branch: refs/heads/master >>>> Commit: 1a332afa33c55a72ae8ab5ec83cd5964de3fdc67 >>>> Parents: b701951 >>>> Author: Matt Sicker <mattsic...@apache.org> >>>> Authored: Sun Sep 21 20:30:50 2014 -0500 >>>> Committer: Matt Sicker <mattsic...@apache.org> >>>> Committed: Tue Sep 23 23:32:49 2014 -0500 >>>> >>>> ---------------------------------------------------------------------- >>>> .../log4j/core/AbstractAtomicLifeCycle.java | 102 >>>> +++++++++++++++++++ >>>> .../apache/logging/log4j/core/LifeCycle.java | 9 +- >>>> 2 files changed, 108 insertions(+), 3 deletions(-) >>>> ---------------------------------------------------------------------- >>>> >>>> >>>> >>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1a332afa/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractAtomicLifeCycle.java >>>> ---------------------------------------------------------------------- >>>> diff --git >>>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractAtomicLifeCycle.java >>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractAtomicLifeCycle.java >>>> new file mode 100644 >>>> index 0000000..05a343a >>>> --- /dev/null >>>> +++ >>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractAtomicLifeCycle.java >>>> @@ -0,0 +1,102 @@ >>>> +package org.apache.logging.log4j.core; >>>> + >>>> +import java.io.Serializable; >>>> +import java.util.concurrent.atomic.AtomicReference; >>>> + >>>> +import org.apache.logging.log4j.core.util.Throwables; >>>> +import org.apache.logging.log4j.status.StatusLogger; >>>> + >>>> +/** >>>> + * An extensible {@link LifeCycle} using an {@link AtomicReference} to >>>> wrap its {@link LifeCycle.State}. Thus, classes >>>> + * which extend this class will follow the finite state machine as >>>> follows: >>>> + * <ol> >>>> + * <li>When {@link #start()} is called, {@link #doStart()} is called >>>> if and only if this is in the INITIALIZED state or >>>> + * the STOPPED state.</li> >>>> + * <li>Before {@link #doStart()} is called, this will be in the >>>> STARTING state.</li> >>>> + * <li>After {@link #doStart()} is called, this will be in the STARTED >>>> state if no exception was thrown; otherwise, >>>> + * this will be in the INITIALIZED state again, and the exception >>>> thrown will be re-thrown (if unchecked) or wrapped >>>> + * in an {@link java.lang.reflect.UndeclaredThrowableException} and >>>> then rethrown (if checked).</li> >>>> + * <li>When {@link #stop()} is called, {@link #doStop()} is called if >>>> and only if this is in the STARTED state.</li> >>>> + * <li>Before {@link #doStop()} is called, this will be in the >>>> STOPPING state.</li> >>>> + * <li>After {@link #doStop()} is called, this will be in the STOPPED >>>> state. Any exceptions thrown will be re-thrown >>>> + * as described above.</li> >>>> + * </ol> >>>> + * >>>> + * @since 2.1 >>>> + */ >>>> +public abstract class AbstractAtomicLifeCycle implements LifeCycle, >>>> Serializable { >>>> + >>>> + private static final long serialVersionUID = 1L; >>>> + >>>> + protected static final StatusLogger LOGGER = >>>> StatusLogger.getLogger(); >>>> + >>>> + private final AtomicReference<State> state = new >>>> AtomicReference<State>(State.INITIALIZED); >>>> + >>>> + @Override >>>> + public void start() { >>>> + if (state.compareAndSet(State.INITIALIZED, State.STARTING) || >>>> + state.compareAndSet(State.STOPPED, State.STARTING)) { >>>> + try { >>>> + doStart(); >>>> + state.set(State.STARTED); >>>> + } catch (final Exception e) { >>>> + state.set(State.INITIALIZED); >>>> + Throwables.rethrow(e); >>>> + } >>>> + } >>>> + } >>>> + >>>> + /** >>>> + * Performs the start-up logic. This method is called only if this >>>> is in the INITIALIZED or STOPPED state. >>>> + * >>>> + * @throws Exception >>>> + */ >>>> + protected abstract void doStart() throws Exception; >>>> + >>>> + @Override >>>> + public void stop() { >>>> + if (state.compareAndSet(State.STARTED, State.STOPPING)) { >>>> + try { >>>> + doStop(); >>>> + } catch (Exception e) { >>>> + Throwables.rethrow(e); >>>> + } finally { >>>> + state.set(State.STOPPED); >>>> + } >>>> + } >>>> + } >>>> + >>>> + /** >>>> + * Performs the tear-down logic. This method is called only if >>>> this is in the STARTED state. >>>> + * >>>> + * @throws Exception >>>> + */ >>>> + protected abstract void doStop() throws Exception; >>>> + >>>> + @Override >>>> + public boolean isStarted() { >>>> + return state.get() == State.STARTED; >>>> + } >>>> + >>>> + @Override >>>> + public boolean isStopped() { >>>> + return state.get() == State.STOPPED; >>>> + } >>>> + >>>> + @Override >>>> + public boolean equals(final Object o) { >>>> + if (this == o) { >>>> + return true; >>>> + } >>>> + if (o == null || getClass() != o.getClass()) { >>>> + return false; >>>> + } >>>> + final AbstractAtomicLifeCycle that = (AbstractAtomicLifeCycle) >>>> o; >>>> + return state.equals(that.state); >>>> + } >>>> + >>>> + @Override >>>> + public int hashCode() { >>>> + return state.hashCode(); >>>> + } >>>> +} >>>> >>>> >>>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1a332afa/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java >>>> ---------------------------------------------------------------------- >>>> diff --git >>>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java >>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java >>>> index e75ebd5..191edcd 100644 >>>> --- >>>> a/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java >>>> +++ >>>> b/log4j-core/src/main/java/org/apache/logging/log4j/core/LifeCycle.java >>>> @@ -18,7 +18,7 @@ >>>> package org.apache.logging.log4j.core; >>>> >>>> /** >>>> - * All proper Java frameworks implement some sort of object life >>>> cycle. In Log4j, the main interface for handling >>>> + * Generic object life cycle support interface. In Log4j, the main >>>> interface for handling >>>> * the life cycle context of an object is this one. An object first >>>> starts in the {@link State#INITIALIZED} state >>>> * by default to indicate the class has been loaded. From here, >>>> calling the {@link #start()} method will change this >>>> * state to {@link State#STARTING}. After successfully being started, >>>> this state is changed to {@link State#STARTED}. >>>> @@ -26,9 +26,12 @@ package org.apache.logging.log4j.core; >>>> * stopped, this goes into the {@link State#STOPPED} state. In most >>>> circumstances, implementation classes should >>>> * store their {@link State} in a {@code volatile} field or inside an >>>> * {@link java.util.concurrent.atomic.AtomicReference} dependant on >>>> synchronization and concurrency requirements. >>>> + * >>>> + * @see AbstractLifeCycle >>>> + * @see AbstractAtomicLifeCycle >>>> */ >>>> public interface LifeCycle { >>>> - >>>> + >>>> /** >>>> * Status of a life cycle like a {@link LoggerContext}. >>>> */ >>>> @@ -44,7 +47,7 @@ public interface LifeCycle { >>>> /** Has stopped. */ >>>> STOPPED >>>> } >>>> - >>>> + >>>> void start(); >>>> >>>> void stop(); >>>> >>>> >>>> >>>> >>>> -- >>>> E-Mail: garydgreg...@gmail.com | ggreg...@apache.org >>>> Java Persistence with Hibernate, Second Edition >>>> <http://www.manning.com/bauer3/> >>>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>>> Spring Batch in Action <http://www.manning.com/templier/> >>>> Blog: http://garygregory.wordpress.com >>>> Home: http://garygregory.com/ >>>> Tweet! http://twitter.com/GaryGregory >>>> >>> >>> >>> >>> -- >>> E-Mail: garydgreg...@gmail.com | ggreg...@apache.org >>> Java Persistence with Hibernate, Second Edition >>> <http://www.manning.com/bauer3/> >>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> >>> Spring Batch in Action <http://www.manning.com/templier/> >>> Blog: http://garygregory.wordpress.com >>> Home: http://garygregory.com/ >>> Tweet! http://twitter.com/GaryGregory >>> >> >> >> >> -- >> Matt Sicker <boa...@gmail.com> >> > > > > -- > E-Mail: garydgreg...@gmail.com | ggreg...@apache.org > Java Persistence with Hibernate, Second Edition > <http://www.manning.com/bauer3/> > JUnit in Action, Second Edition <http://www.manning.com/tahchiev/> > Spring Batch in Action <http://www.manning.com/templier/> > Blog: http://garygregory.wordpress.com > Home: http://garygregory.com/ > Tweet! http://twitter.com/GaryGregory > -- Matt Sicker <boa...@gmail.com>