source: java/main/src/main/java/com/framsticks/util/dispatching/AbstractJoinable.java @ 193

Last change on this file since 193 was 193, checked in by Maciej Komosinski, 10 years ago

Set svn:eol-style native for all textual files

  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1package com.framsticks.util.dispatching;
2
3import java.util.Collections;
4import java.util.HashSet;
5import java.util.LinkedList;
6import java.util.List;
7import java.util.Set;
8
9import javax.annotation.Nonnull;
10
11import org.apache.commons.collections.CollectionUtils;
12import org.apache.logging.log4j.Logger;
13import org.apache.logging.log4j.LogManager;
14
15import com.framsticks.util.FramsticksException;
16
17public abstract class AbstractJoinable implements Joinable {
18
19        private static final Logger log = LogManager.getLogger(AbstractJoinable.class);
20        private static final Logger reportLog = LogManager.getLogger(AbstractJoinable.class.getName() + ".Report");
21
22        protected final Set<JoinableParent> owners = new HashSet<JoinableParent>();
23        protected final Set<JoinableParent> joinableListeners = new HashSet<JoinableParent>();
24
25        protected static final Set<AbstractJoinable> joinablesRegistry = Collections.synchronizedSet(new HashSet<AbstractJoinable>());
26
27        protected JoinableState state = JoinableState.INITILIAZED;
28        protected JoinableParent parent;
29        protected Monitor monitor;
30
31        /**
32         *
33         */
34        public AbstractJoinable() {
35                joinablesRegistry.add(this);
36        }
37
38
39
40        public static void report() {
41                if (!reportLog.isDebugEnabled()) {
42                        return;
43                }
44                StringBuilder b = new StringBuilder();
45                synchronized (joinablesRegistry) {
46                        for (AbstractJoinable j : joinablesRegistry) {
47                                b.append("\n").append(j.getState()).append(" : ").append(j).append(" - ").append(j.getClass());
48                        }
49                }
50                reportLog.debug("state: {}", b);
51        }
52
53        private synchronized boolean changeState(JoinableState state) {
54                if (this.state.ordinal() >= state.ordinal()) {
55                        return false;
56                }
57                if (this.state.ordinal() + 1 != state.ordinal()) {
58                        throw new FramsticksException().msg("failed to change state").arg("from", this.state).arg("to", state).arg("joinable", this);
59                }
60                this.state = state;
61                log.debug("{} changed state to {}", this, state);
62
63
64                List<JoinableParent> parents = new LinkedList<>();
65                CollectionUtils.addAll(parents, joinableListeners.iterator());
66
67                for (JoinableParent p : parents) {
68                        if (p != null) {
69                                log.debug("{} is notifying parent {} about change to {}", this, p, state);
70                                Dispatching.childChangedState(p, this, state);
71                        }
72                }
73                this.notifyAll();
74
75                report();
76
77                return true;
78        }
79
80
81
82        protected final boolean startJoinable() {
83                if (changeState(JoinableState.RUNNING)) {
84                        joinableStart();
85                        return true;
86                }
87                return false;
88        }
89
90        protected final boolean interruptJoinable() {
91                if (changeState(JoinableState.FINISHING)) {
92                        joinableInterrupt();
93                        return true;
94                }
95                return false;
96        }
97
98        protected final boolean finishJoinable() {
99                if (changeState(JoinableState.JOINABLE)) {
100                        joinableFinish();
101                        return true;
102                }
103                return false;
104        }
105
106
107
108        @Override
109        public final void join() throws InterruptedException {
110                synchronized (this) {
111                        if (this.state.equals(JoinableState.JOINED)) {
112                                return;
113                        }
114                        if (!this.state.equals(JoinableState.JOINABLE)) {
115                                throw new InterruptedException();
116                        }
117                }
118                joinableJoin();
119                changeState(JoinableState.JOINED);
120                // synchronized (this) {
121                //      this.state = JoinableState.JOINED;
122                // }
123        }
124
125        protected final boolean proceedToState(JoinableState state) {
126                switch (state) {
127                        case RUNNING:
128                                return startJoinable();
129                        case FINISHING:
130                                return interruptJoinable();
131                        case JOINABLE:
132                                return finishJoinable();
133                        default: return false;
134                }
135        }
136
137        protected abstract void joinableStart();
138
139        protected abstract void joinableInterrupt();
140
141        protected abstract void joinableFinish();
142
143        protected abstract void joinableJoin() throws InterruptedException;
144
145        public final boolean use(@Nonnull JoinableParent owner) {
146                boolean start = false;
147                synchronized (this) {
148                        if (owners.contains(owner)) {
149                                throw new FramsticksException().msg("owner is already using that joinable").arg("joinable", this).arg("owner", owner);
150                        }
151                        start = owners.isEmpty();
152                        log.debug("{} is using {}", owner, this);
153                        owners.add(owner);
154                        joinableListeners.add(owner);
155                }
156                if (start) {
157                        assert monitor == null;
158                        monitor = owner.getMonitor();
159                        return this.startJoinable();
160                }
161                return false;
162        }
163
164        public final boolean drop(@Nonnull JoinableParent owner) {
165                boolean stop = false;
166                synchronized (this) {
167                        if (!owners.contains(owner)) {
168                                // log.error("owner {} is not owning that joinable {}", owner, this);
169                                // return false;
170                                throw new FramsticksException().msg("object is not owning that joinable").arg("joinable", this).arg("object", owner);
171                        }
172                        // assert owners.containsKey(owner);
173                        owners.remove(owner);
174                        stop = owners.isEmpty();
175                        log.debug("{} is droping {} (users remaining: {})", owner, this, owners);
176                }
177                if (stop) {
178                        Dispatching.dispatcherGuardedInvoke(this, new RunAt<Object>(ThrowExceptionHandler.getInstance()) {
179                                @Override
180                                protected void runAt() {
181                                        interruptJoinable();
182                                }
183                        });
184                        return true;
185                }
186                return stop;
187        }
188
189        /**
190         * @return the state
191         */
192        public JoinableState getState() {
193                return state;
194        }
195
196        protected boolean isInState(JoinableState state) {
197                return this.state.equals(state);
198        }
199
200        protected boolean isRunning() {
201                return state.equals(JoinableState.RUNNING);
202        }
203
204        @Override
205        public String toString() {
206                return getClass().getSimpleName() + "(" + getName() + ")";
207        }
208
209        // @Override
210        public Monitor getMonitor() {
211                return monitor;
212        }
213
214}
Note: See TracBrowser for help on using the repository browser.