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