[FELIX-4336] Use smarter thread locals for ThreadIo so that streams that have been deactivated won't be used and delegate to the previous stream instead
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1546581 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/Marker.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/Marker.java
index 95c50e5..84dc7ce 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/Marker.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/Marker.java
@@ -23,26 +23,41 @@
public class Marker
{
- Marker previous;
+ final Marker previous;
InputStream in;
PrintStream out;
PrintStream err;
- ThreadIOImpl parent;
+ volatile boolean deactivated;
- public Marker(ThreadIOImpl parent, InputStream in, PrintStream out, PrintStream err, Marker previous)
+ public Marker(InputStream in, PrintStream out, PrintStream err, Marker previous)
{
this.previous = previous;
- this.parent = parent;
this.in = in;
this.out = out;
this.err = err;
}
- Marker activate()
+ public InputStream getIn()
{
- parent.in.setStream(in);
- parent.out.setStream(out);
- parent.err.setStream(err);
- return previous;
+ return deactivated ? previous.getIn() : in;
+ }
+
+ public PrintStream getOut()
+ {
+ return deactivated ? previous.getOut() : out;
+ }
+
+ public PrintStream getErr()
+ {
+ return deactivated ? previous.getErr() : err;
+ }
+
+ void deactivate()
+ {
+ deactivated = true;
+ // Set to null for garbage collection
+ in = null;
+ out = null;
+ err = null;
}
}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java
index c4e2a12..bf50878 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java
@@ -28,10 +28,19 @@
public class ThreadIOImpl implements ThreadIO
{
static private final Logger log = Logger.getLogger(ThreadIOImpl.class.getName());
- ThreadPrintStream err = new ThreadPrintStream(System.err);
- ThreadPrintStream out = new ThreadPrintStream(System.out);
- ThreadInputStream in = new ThreadInputStream(System.in);
- ThreadLocal<Marker> current = new InheritableThreadLocal<Marker>();
+
+ final Marker defaultMarker = new Marker(System.in, System.out, System.err, null);
+ final ThreadPrintStream err = new ThreadPrintStream(this, System.err, true);
+ final ThreadPrintStream out = new ThreadPrintStream(this, System.out, false);
+ final ThreadInputStream in = new ThreadInputStream(this, System.in);
+ final ThreadLocal<Marker> current = new InheritableThreadLocal<Marker>()
+ {
+ @Override
+ protected Marker initialValue()
+ {
+ return defaultMarker;
+ }
+ };
public void start()
{
@@ -46,9 +55,9 @@
public void stop()
{
- System.setErr(err.dflt);
- System.setOut(out.dflt);
- System.setIn(in.dflt);
+ System.setErr(defaultMarker.err);
+ System.setOut(defaultMarker.out);
+ System.setIn(defaultMarker.in);
}
private void checkIO()
@@ -72,6 +81,20 @@
}
}
+ Marker current()
+ {
+ Marker m = current.get();
+ if (m.deactivated)
+ {
+ while (m.deactivated)
+ {
+ m = m.previous;
+ }
+ current.set(m);
+ }
+ return m;
+ }
+
public void close()
{
checkIO(); // derek
@@ -80,18 +103,10 @@
{
throw new IllegalStateException("No thread io active");
}
-
- Marker previous = top.previous;
- if (previous == null)
+ if (top != defaultMarker)
{
- in.end();
- out.end();
- err.end();
- }
- else
- {
- this.current.set(previous);
- previous.activate();
+ top.deactivate();
+ this.current.set(top.previous);
}
}
@@ -101,8 +116,7 @@
assert out != null;
assert err != null;
checkIO(); // derek
- Marker marker = new Marker(this, in, out, err, current.get());
+ Marker marker = new Marker(in, out, err, current.get());
this.current.set(marker);
- marker.activate();
}
}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadInputStream.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadInputStream.java
index 9f27c59..893d121 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadInputStream.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadInputStream.java
@@ -23,39 +23,19 @@
public class ThreadInputStream extends InputStream
{
- ThreadLocal<InputStream> map = new InheritableThreadLocal<InputStream>();
- InputStream dflt;
+ final InputStream dflt;
+ final ThreadIOImpl io;
- public ThreadInputStream(InputStream in)
+ public ThreadInputStream(ThreadIOImpl threadIO, InputStream in)
{
+ io = threadIO;
dflt = in;
}
private InputStream getCurrent()
{
- InputStream in = map.get();
- if (in != null)
- {
- return in;
- }
- return dflt;
- }
-
- public void setStream(InputStream in)
- {
- if (in != dflt && in != this)
- {
- map.set(in);
- }
- else
- {
- map.remove();
- }
- }
-
- public void end()
- {
- map.remove();
+ Marker marker = io.current();
+ return marker.getIn();
}
/**
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java
index e8893f6..6cd14bc 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadPrintStream.java
@@ -25,40 +25,22 @@
public class ThreadPrintStream extends PrintStream
{
- PrintStream dflt;
- ThreadLocal<PrintStream> map = new InheritableThreadLocal<PrintStream>();
+ final PrintStream dflt;
+ final ThreadIOImpl io;
+ final boolean errorStream;
- public ThreadPrintStream(PrintStream out)
+ public ThreadPrintStream(ThreadIOImpl threadIO, PrintStream out, boolean error)
{
super(out);
dflt = out;
+ io = threadIO;
+ errorStream = error;
}
public PrintStream getCurrent()
{
- PrintStream out = map.get();
- if (out != null)
- {
- return out;
- }
- return dflt;
- }
-
- public void setStream(PrintStream out)
- {
- if (out != dflt && out != this)
- {
- map.set(out);
- }
- else
- {
- map.remove();
- }
- }
-
- public void end()
- {
- map.remove();
+ Marker marker = io.current();
+ return errorStream ? marker.getErr() : marker.getOut();
}
/**