Skip to content

Commit 2e8f29c

Browse files
committed
Merge branch 'copy-on-write'
Use CopyOnWriteArrayList to simplify mutable list fields.
2 parents f7b4e30 + dcce181 commit 2e8f29c

File tree

2 files changed

+16
-49
lines changed

2 files changed

+16
-49
lines changed

src/main/java/org/scijava/console/DefaultConsoleService.java

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.ArrayList;
3838
import java.util.LinkedList;
3939
import java.util.List;
40+
import java.util.concurrent.CopyOnWriteArrayList;
4041

4142
import org.scijava.Context;
4243
import org.scijava.console.OutputEvent.Source;
@@ -69,9 +70,7 @@ public class DefaultConsoleService extends
6970
private OutputStreamReporter out, err;
7071

7172
/** List of listeners for {@code stdout} and {@code stderr} output. */
72-
private ArrayList<OutputListener> listeners;
73-
74-
private OutputListener[] cachedListeners;
73+
private List<OutputListener> listeners;
7574

7675
// -- ConsoleService methods --
7776

@@ -116,26 +115,19 @@ public void processArgs(final String... args) {
116115
@Override
117116
public void addOutputListener(final OutputListener l) {
118117
if (listeners == null) initListeners();
119-
synchronized (listeners) {
120-
listeners.add(l);
121-
cacheListeners();
122-
}
118+
listeners.add(l);
123119
}
124120

125121
@Override
126122
public void removeOutputListener(final OutputListener l) {
127123
if (listeners == null) initListeners();
128-
synchronized (listeners) {
129-
listeners.remove(l);
130-
cacheListeners();
131-
}
124+
listeners.remove(l);
132125
}
133126

134127
@Override
135128
public void notifyListeners(final OutputEvent event) {
136129
if (listeners == null) initListeners();
137-
final OutputListener[] toNotify = cachedListeners;
138-
for (final OutputListener l : toNotify)
130+
for (final OutputListener l : listeners)
139131
l.outputOccurred(event);
140132
}
141133

@@ -163,16 +155,11 @@ private synchronized void initListeners() {
163155
err = new OutputStreamReporter(Source.STDERR);
164156
syserr.getParent().addOutputStream(err);
165157

166-
listeners = new ArrayList<>();
167-
cachedListeners = listeners.toArray(new OutputListener[0]);
158+
listeners = new CopyOnWriteArrayList<>();
168159
}
169160

170161
// -- Helper methods --
171162

172-
private void cacheListeners() {
173-
cachedListeners = listeners.toArray(new OutputListener[listeners.size()]);
174-
}
175-
176163
private MultiPrintStream multiPrintStream(final PrintStream ps) {
177164
if (ps instanceof MultiPrintStream) return (MultiPrintStream) ps;
178165
return new MultiPrintStream(ps);

src/main/java/org/scijava/console/MultiOutputStream.java

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import java.io.IOException;
3636
import java.io.OutputStream;
3737
import java.util.ArrayList;
38+
import java.util.List;
39+
import java.util.concurrent.CopyOnWriteArrayList;
3840

3941
/**
4042
* A {@code MultiOutputStream} is a collection of constituent
@@ -49,81 +51,59 @@
4951
*/
5052
public class MultiOutputStream extends OutputStream {
5153

52-
private final ArrayList<OutputStream> streams;
53-
54-
private OutputStream[] cachedStreams;
54+
private final List<OutputStream> streams;
5555

5656
/**
5757
* Forwards output to a list of output streams.
5858
*
5959
* @param os Output streams which will receive this stream's output.
6060
*/
6161
public MultiOutputStream(final OutputStream... os) {
62-
streams = new ArrayList<>(os.length);
63-
for (int i = 0; i < os.length; i++) {
64-
streams.add(os[i]);
65-
}
66-
cacheStreams();
62+
streams = new CopyOnWriteArrayList<>(os);
6763
}
6864

6965
// -- MultiOutputStream methods --
7066

7167
/** Adds an output stream to those receiving this stream's output. */
7268
public void addOutputStream(final OutputStream os) {
73-
synchronized (streams) {
74-
streams.add(os);
75-
cacheStreams();
76-
}
69+
streams.add(os);
7770
}
7871

7972
/** Removes an output stream from those receiving this stream's output. */
8073
public void removeOutputStream(final OutputStream os) {
81-
synchronized (streams) {
82-
streams.remove(os);
83-
cacheStreams();
84-
}
74+
streams.remove(os);
8575
}
8676

8777
// -- OutputStream methods --
8878

8979
@Override
9080
public void write(final int b) throws IOException {
91-
final OutputStream[] toWrite = cachedStreams;
92-
for (final OutputStream stream : toWrite)
81+
for (final OutputStream stream : streams)
9382
stream.write(b);
9483
}
9584

9685
@Override
9786
public void write(final byte[] buf, final int off, final int len)
9887
throws IOException
9988
{
100-
final OutputStream[] toWrite = cachedStreams;
101-
for (final OutputStream stream : toWrite)
89+
for (final OutputStream stream : streams)
10290
stream.write(buf, off, len);
10391
}
10492

10593
// -- Closeable methods --
10694

10795
@Override
10896
public void close() throws IOException {
109-
final OutputStream[] toClose = cachedStreams;
110-
for (final OutputStream stream : toClose)
97+
for (final OutputStream stream : streams)
11198
stream.close();
11299
}
113100

114101
// -- Flushable methods --
115102

116103
@Override
117104
public void flush() throws IOException {
118-
final OutputStream[] toFlush = cachedStreams;
119-
for (final OutputStream stream : toFlush)
105+
for (final OutputStream stream : streams)
120106
stream.flush();
121107
}
122108

123-
// -- Helper methods --
124-
125-
private void cacheStreams() {
126-
cachedStreams = streams.toArray(new OutputStream[streams.size()]);
127-
}
128-
129109
}

0 commit comments

Comments
 (0)