1 /*
2 * Hunt - A refined core library for D programming language.
3 *
4 * Copyright (C) 2018-2019 HuntLabs
5 *
6 * Website: https://www.huntlabs.net/
7 *
8 * Licensed under the Apache-2.0 License.
9 *
10 */11 12 modulehunt.util.AbstractLifecycle;
13 14 importcore.atomic;
15 16 importhunt.util.Lifecycle;
17 importhunt.util.Common;
18 importhunt.util.Runnable;
19 importhunt.logging;
20 21 22 /**
23 * Interface for objects that may participate in a phased
24 * process such as lifecycle management.
25 *
26 * @see SmartLifecycle
27 */28 interfacePhased {
29 30 /**
31 * Return the phase value of this object.
32 */33 intgetPhase();
34 }
35 36 37 /**
38 * An extension of the {@link Lifecycle} interface for those objects that require to
39 * be started upon ApplicationContext refresh and/or shutdown in a particular order.
40 * The {@link #isAutoStartup()} return value indicates whether this object should
41 * be started at the time of a context refresh. The callback-accepting
42 * {@link #stop(Runnable)} method is useful for objects that have an asynchronous
43 * shutdown process. Any implementation of this interface <i>must</i> invoke the
44 * callback's {@code run()} method upon shutdown completion to avoid unnecessary
45 * delays in the overall ApplicationContext shutdown.
46 *
47 * <p>This interface extends {@link Phased}, and the {@link #getPhase()} method's
48 * return value indicates the phase within which this Lifecycle component should
49 * be started and stopped. The startup process begins with the <i>lowest</i> phase
50 * value and ends with the <i>highest</i> phase value ({@code Integer.MIN_VALUE}
51 * is the lowest possible, and {@code Integer.MAX_VALUE} is the highest possible).
52 * The shutdown process will apply the reverse order. Any components with the
53 * same value will be arbitrarily ordered within the same phase.
54 *
55 * <p>Example: if component B depends on component A having already started,
56 * then component A should have a lower phase value than component B. During
57 * the shutdown process, component B would be stopped before component A.
58 *
59 * <p>Any explicit "depends-on" relationship will take precedence over the phase
60 * order such that the dependent bean always starts after its dependency and
61 * always stops before its dependency.
62 *
63 * <p>Any {@code Lifecycle} components within the context that do not also
64 * implement {@code SmartLifecycle} will be treated as if they have a phase
65 * value of 0. That way a {@code SmartLifecycle} implementation may start
66 * before those {@code Lifecycle} components if it has a negative phase value,
67 * or it may start after those components if it has a positive phase value.
68 *
69 * <p>Note that, due to the auto-startup support in {@code SmartLifecycle}, a
70 * {@code SmartLifecycle} bean instance will usually get initialized on startup
71 * of the application context in any case. As a consequence, the bean definition
72 * lazy-init flag has very limited actual effect on {@code SmartLifecycle} beans.
73 *
74 * @author Mark Fisher
75 */76 interfaceSmartLifecycle : Lifecycle, Phased {
77 78 /**
79 * Returns {@code true} if this {@code Lifecycle} component should get
80 * started automatically by the container at the time that the containing
81 * {@link ApplicationContext} gets refreshed.
82 * <p>A value of {@code false} indicates that the component is intended to
83 * be started through an explicit {@link #start()} call instead, analogous
84 * to a plain {@link Lifecycle} implementation.
85 * @see #start()
86 * @see #getPhase()
87 */88 boolisAutoStartup();
89 90 /**
91 * Indicates that a Lifecycle component must stop if it is currently running.
92 * <p>The provided callback is used by the {@link LifecycleProcessor} to support
93 * an ordered, and potentially concurrent, shutdown of all components having a
94 * common shutdown order value. The callback <b>must</b> be executed after
95 * the {@code SmartLifecycle} component does indeed stop.
96 * <p>The {@link LifecycleProcessor} will call <i>only</i> this variant of the
97 * {@code stop} method; i.e. {@link Lifecycle#stop()} will not be called for
98 * {@code SmartLifecycle} implementations unless explicitly delegated to within
99 * the implementation of this method.
100 * @see #stop()
101 * @see #getPhase()
102 */103 voidstop(Runnablecallback);
104 105 aliasstop = Lifecycle.stop;
106 107 intgetPhase();
108 109 }
110 111 /**
112 */113 abstractclassAbstractLifecycle : Lifecycle {
114 115 protectedsharedbool_isRunning;
116 117 this() {
118 119 }
120 121 boolisRunning() {
122 return_isRunning;
123 }
124 125 boolisStopped() {
126 return !_isRunning;
127 }
128 129 voidstart() {
130 if (cas(&_isRunning, false, true)) {
131 initialize();
132 } else {
133 version(HUNT_DEBUG) warning("Starting repeatedly!");
134 }
135 }
136 137 voidstop() {
138 if (cas(&_isRunning, true, false)) {
139 destroy();
140 } else {
141 version(HUNT_DEBUG) warning("Stopping repeatedly!");
142 }
143 }
144 145 abstractprotectedvoidinitialize();
146 147 abstractprotectedvoiddestroy();
148 }