-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathAbstractConvertor.java
More file actions
218 lines (190 loc) · 4.9 KB
/
AbstractConvertor.java
File metadata and controls
218 lines (190 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
package com.laytonsmith.abstraction;
import com.laytonsmith.PureUtilities.DaemonManager;
import com.laytonsmith.core.environments.Environment;
import com.laytonsmith.core.events.BindableEvent;
import com.laytonsmith.core.events.Driver;
import com.laytonsmith.core.events.EventUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractConvertor implements Convertor {
private final List<Runnable> shutdownHooks = new ArrayList<>();
@Override
public void addShutdownHook(Runnable r) {
shutdownHooks.add(r);
}
@Override
public void runShutdownHooks(Environment env) {
// Fire off the shutdown event, before we shut down all the internal hooks
EventUtils.TriggerListener(Driver.SHUTDOWN, "shutdown", new BindableEvent() {
@Override
public Object _GetObject() {
return new Object();
}
}, env);
Iterator<Runnable> iter = shutdownHooks.iterator();
while(iter.hasNext()) {
iter.next().run();
iter.remove();
}
}
/**
* Runs the task either now or later. In the case of a default Convertor, it just runs the task now.
*
* @param dm
* @param r
*/
@Override
public void runOnMainThreadLater(DaemonManager dm, Runnable r) {
r.run();
}
@Override
public <T> T runOnMainThreadAndWait(Callable<T> callable) throws Exception {
return (T) callable.call();
}
@Override
public MCWorldCreator getWorldCreator(String worldName) {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public MCCommand getNewCommand(String name) {
throw new UnsupportedOperationException("Not supported in this implementation.");
}
@Override
public MCCommandSender GetCorrectSender(MCCommandSender unspecific) {
throw new UnsupportedOperationException("Not supported in this implementation.");
}
private final Map<Integer, Task> tasks = new HashMap<>();
private final AtomicInteger taskIDs = new AtomicInteger(0);
@Override
public void ClearAllRunnables() {
synchronized(tasks) {
for(Task task : tasks.values()) {
task.unregister();
}
tasks.clear();
}
}
@Override
public void ClearFutureRunnable(int id) {
synchronized(tasks) {
if(tasks.containsKey(id)) {
tasks.get(id).unregister();
tasks.remove(id);
}
}
}
@Override
public int SetFutureRepeater(DaemonManager dm, long ms, long initialDelay, final Runnable r) {
int id = taskIDs.getAndIncrement();
Task t = new Task(id, dm, true, initialDelay, ms, new Runnable() {
@Override
public void run() {
triggerRunnable(r);
}
});
synchronized(tasks) {
tasks.put(id, t);
t.register();
}
return id;
}
@Override
public int SetFutureRunnable(DaemonManager dm, long ms, final Runnable r) {
int id = taskIDs.getAndIncrement();
Task t = new Task(id, dm, false, ms, 0, new Runnable() {
@Override
public void run() {
triggerRunnable(r);
}
});
synchronized(tasks) {
tasks.put(id, t);
t.register();
}
return id;
}
/**
* A subclass may need to do special handling for the actual trigger of a scheduled task, though not need to do
* anything special for the scheduling itself. In this case, subclasses may override this method, and whenever a
* scheduled task is intended to be run, it will be passed to this method instead. By default, the runnable is
* simply run.
*
* @param r
*/
protected synchronized void triggerRunnable(Runnable r) {
r.run();
}
private class Task {
/**
* The task id
*/
private final int id;
/**
* The DaemonManager
*/
private final DaemonManager dm;
/**
* True if this is an interval, false otherwise.
*/
private final boolean repeater;
/**
* The initial delay. For timeouts, this is just the delay.
*/
private final long initialDelay;
/**
* The delay between triggers. For intervals, this is ignored.
*/
private final long interval;
/**
* The task itself.
*/
private final Runnable task;
private Timer timer;
public Task(int id, DaemonManager dm, boolean repeater, long initialDelay, long interval, Runnable task) {
this.id = id;
this.dm = dm;
this.repeater = repeater;
this.initialDelay = initialDelay;
if(repeater) {
this.interval = interval;
} else {
this.interval = Long.MAX_VALUE;
}
this.task = task;
}
public void register() {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
task.run();
if(!repeater) {
unregister();
synchronized(tasks) {
tasks.remove(id);
}
}
}
}, initialDelay, interval);
if(dm != null) {
dm.activateThread(null);
}
}
public void unregister() {
timer.cancel();
if(dm != null) {
dm.deactivateThread(null);
}
}
public int getId() {
return id;
}
}
}