NettyのAttributeMap


ここ数日nettyを見て、メモを取り始めました.
Netty 5ドキュメントのChannelHandlerの開始点では、handlerのステータス情報を保存するためのattachmentの使用について説明しています.

public class DataServerHandler extends SimpleChannelInboundHandler {
private final AttributeKey auth =
new AttributeKey("auth");

@Override
public void channelRead(ChannelHandlerContext ctx, Integer integer) {
Attribute attr = ctx.getAttr(auth);
//...
}

AttributeKeyとAttributeはmapのキー値ペアであるべきであり、このmapはChannelHandlerContextにバインドされるべきである.
ChannelHandlerContextの説明:
A ChannelHandler is provided with a ChannelHandlerContext object. A ChannelHandler is supposed to interact with the ChannelPipeline it belongs to via a context object. Using the context object, the ChannelHandler can pass events upstream or downstream, modify the pipeline dynamically, or store the information (attachment) which is specific to the handler.
handlerには対応するcontextがあり、handlerはこのcontextオブジェクトを通じてpipelineとインタラクティブになります.
このコンテキストオブジェクトを使用すると、...handlerの情報(attachment)を保存します.
ソースの表示:
DefaultChannelHandlerContextはDefaultAttributeMapを継承

final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext{...}

DefaultAttributeMapの実装:

@SuppressWarnings("rawtypes")
private static final AtomicReferenceFieldUpdater updater = AtomicReferenceFieldUpdater.newUpdater(DefaultAttributeMap.class, Map.class, "map");

private volatile Map, Attribute>> map;

@Override
public Attribute attr(AttributeKey key) {
Map, Attribute>> map = this.map;
if (map == null) {
// Not using ConcurrentHashMap due to high memory consumption.
// 2 IdentityHashMap,
map = new IdentityHashMap, Attribute>>(2);
if (!updater.compareAndSet(this, null, map)) {
// , map ,
//null ,
map = this.map;
}
}

// , attribute null, DefaultAttribute
synchronized (map) {
@SuppressWarnings("unchecked")
Attribute attr = (Attribute) map.get(key);
if (attr == null) {
attr = new DefaultAttribute(map, key);
map.put(key, attr);
}
return attr;
}
}
//......

作者はここで厳密な制御をしたことが見えて、ここを見て、心の中は安心感に満ちています:D
さらに注意したいのは、
ChannelHandlerContextのAttibuteMapはコンテキストにバインドされているため、あるコンテキストで定義したAttributeは別のhandlerのコンテキストでは見えません.
ChannelではAttributeMapも実装されており、ChannelにバインドされたAttributeMapを使用してhandler間でattachmentを渡すことができます.
ctx.channel().attr(...)...;