Make only default IdleStateEvents cached string representation (#9705)

Motivation:

In PR https://github.com/netty/netty/pull/9695   IdleStateEvents
were made to cache their string representation.   The reason for this
was to avoid creating garbage as these values would be used frequently.
However, these objects may be used on multiple event loops and this
may cause an unexpected race to occur.

Modification:
Only make the events that Netty creates cache their toString representation.

Result:
No races.
This commit is contained in:
Carl Mastrangelo 2019-10-23 23:35:11 -07:00 committed by Norman Maurer
parent 7150b42a56
commit 05480c190f

View File

@ -25,16 +25,21 @@ import io.netty.util.internal.StringUtil;
* A user event triggered by {@link IdleStateHandler} when a {@link Channel} is idle.
*/
public class IdleStateEvent {
public static final IdleStateEvent FIRST_READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, true);
public static final IdleStateEvent READER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.READER_IDLE, false);
public static final IdleStateEvent FIRST_WRITER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.WRITER_IDLE, true);
public static final IdleStateEvent WRITER_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.WRITER_IDLE, false);
public static final IdleStateEvent FIRST_ALL_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.ALL_IDLE, true);
public static final IdleStateEvent ALL_IDLE_STATE_EVENT = new IdleStateEvent(IdleState.ALL_IDLE, false);
public static final IdleStateEvent FIRST_READER_IDLE_STATE_EVENT =
new DefaultIdleStateEvent(IdleState.READER_IDLE, true);
public static final IdleStateEvent READER_IDLE_STATE_EVENT =
new DefaultIdleStateEvent(IdleState.READER_IDLE, false);
public static final IdleStateEvent FIRST_WRITER_IDLE_STATE_EVENT =
new DefaultIdleStateEvent(IdleState.WRITER_IDLE, true);
public static final IdleStateEvent WRITER_IDLE_STATE_EVENT =
new DefaultIdleStateEvent(IdleState.WRITER_IDLE, false);
public static final IdleStateEvent FIRST_ALL_IDLE_STATE_EVENT =
new DefaultIdleStateEvent(IdleState.ALL_IDLE, true);
public static final IdleStateEvent ALL_IDLE_STATE_EVENT =
new DefaultIdleStateEvent(IdleState.ALL_IDLE, false);
private final IdleState state;
private final boolean first;
private String strVal;
/**
* Constructor for sub-classes.
@ -63,9 +68,20 @@ public class IdleStateEvent {
@Override
public String toString() {
if (strVal == null) {
strVal = StringUtil.simpleClassName(this) + "(" + state + (first ? ", first" : "") + ')';
return StringUtil.simpleClassName(this) + '(' + state + (first ? ", first" : "") + ')';
}
private static final class DefaultIdleStateEvent extends IdleStateEvent {
private final String representation;
DefaultIdleStateEvent(IdleState state, boolean first) {
super(state, first);
this.representation = "IdleStateEvent(" + state + (first ? ", first" : "") + ')';
}
@Override
public String toString() {
return representation;
}
return strVal;
}
}