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