1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.channel;
17
18 import org.jboss.netty.util.internal.ConcurrentIdentityWeakKeyHashMap;
19
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.Map.Entry;
23 import java.util.concurrent.ConcurrentMap;
24
25
26
27
28
29
30
31
32
33
34
35
36 public class ChannelLocal<T> implements Iterable<Entry<Channel, T>> {
37
38 private final ConcurrentMap<Channel, T> map =
39 new ConcurrentIdentityWeakKeyHashMap<Channel, T>();
40
41 private final ChannelFutureListener remover = new ChannelFutureListener() {
42 public void operationComplete(ChannelFuture future) throws Exception {
43 remove(future.getChannel());
44 }
45 };
46
47 private final boolean removeOnClose;
48
49
50
51
52
53 public ChannelLocal() {
54 this(false);
55 }
56
57
58
59
60
61
62
63 public ChannelLocal(boolean removeOnClose) {
64 this.removeOnClose = removeOnClose;
65 }
66
67
68
69
70
71
72 protected T initialValue(Channel channel) {
73 return null;
74 }
75
76
77
78
79 public T get(Channel channel) {
80 if (channel == null) {
81 throw new NullPointerException("channel");
82 }
83
84 T value = map.get(channel);
85 if (value == null) {
86 value = initialValue(channel);
87 if (value != null) {
88 T oldValue = setIfAbsent(channel, value);
89 if (oldValue != null) {
90 value = oldValue;
91 }
92 }
93 }
94 return value;
95 }
96
97
98
99
100
101
102 public T set(Channel channel, T value) {
103 if (value == null) {
104 return remove(channel);
105 } else {
106 if (channel == null) {
107 throw new NullPointerException("channel");
108 }
109 T old = map.put(channel, value);
110 if (removeOnClose) {
111 channel.getCloseFuture().addListener(remover);
112 }
113 return old;
114 }
115 }
116
117
118
119
120
121
122
123 public T setIfAbsent(Channel channel, T value) {
124 if (value == null) {
125 return get(channel);
126 } else {
127 if (channel == null) {
128 throw new NullPointerException("channel");
129 }
130 T mapping = map.putIfAbsent(channel, value);
131
132 if (removeOnClose && mapping == null) {
133 channel.getCloseFuture().addListener(remover);
134 }
135 return mapping;
136 }
137 }
138
139
140
141
142
143
144
145
146
147
148 public T remove(Channel channel) {
149 if (channel == null) {
150 throw new NullPointerException("channel");
151 }
152 T removed = map.remove(channel);
153 if (removed == null) {
154 return initialValue(channel);
155 } else {
156 if (removeOnClose) {
157 channel.getCloseFuture().removeListener(remover);
158 }
159 return removed;
160 }
161 }
162
163
164
165
166 public Iterator<Entry<Channel, T>> iterator() {
167 return Collections.unmodifiableSet(map.entrySet()).iterator();
168 }
169 }