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 39cc7a6739
commit ff9df03d21

View File

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