1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.pool;
17
18 import io.netty.util.concurrent.Future;
19 import io.netty.util.concurrent.GenericFutureListener;
20 import io.netty.util.concurrent.GlobalEventExecutor;
21 import io.netty.util.concurrent.Promise;
22 import io.netty.util.internal.PlatformDependent;
23 import io.netty.util.internal.ReadOnlyIterator;
24
25 import java.io.Closeable;
26 import java.util.Iterator;
27 import java.util.Map.Entry;
28 import java.util.concurrent.ConcurrentMap;
29
30 import static io.netty.util.internal.ObjectUtil.checkNotNull;
31
32
33
34
35
36 public abstract class AbstractChannelPoolMap<K, P extends ChannelPool>
37 implements ChannelPoolMap<K, P>, Iterable<Entry<K, P>>, Closeable {
38 private final ConcurrentMap<K, P> map = PlatformDependent.newConcurrentHashMap();
39
40 @Override
41 public final P get(K key) {
42 P pool = map.get(checkNotNull(key, "key"));
43 if (pool == null) {
44 pool = newPool(key);
45 P old = map.putIfAbsent(key, pool);
46 if (old != null) {
47
48 poolCloseAsyncIfSupported(pool);
49 pool = old;
50 }
51 }
52 return pool;
53 }
54
55
56
57
58
59
60
61
62
63 public final boolean remove(K key) {
64 P pool = map.remove(checkNotNull(key, "key"));
65 if (pool != null) {
66 poolCloseAsyncIfSupported(pool);
67 return true;
68 }
69 return false;
70 }
71
72
73
74
75
76
77
78
79 private Future<Boolean> removeAsyncIfSupported(K key) {
80 P pool = map.remove(checkNotNull(key, "key"));
81 if (pool != null) {
82 final Promise<Boolean> removePromise = GlobalEventExecutor.INSTANCE.newPromise();
83 poolCloseAsyncIfSupported(pool).addListener(new GenericFutureListener<Future<? super Void>>() {
84 @Override
85 public void operationComplete(Future<? super Void> future) throws Exception {
86 if (future.isSuccess()) {
87 removePromise.setSuccess(Boolean.TRUE);
88 } else {
89 removePromise.setFailure(future.cause());
90 }
91 }
92 });
93 return removePromise;
94 }
95 return GlobalEventExecutor.INSTANCE.newSucceededFuture(Boolean.FALSE);
96 }
97
98
99
100
101
102
103
104 private static Future<Void> poolCloseAsyncIfSupported(ChannelPool pool) {
105 if (pool instanceof SimpleChannelPool) {
106 return ((SimpleChannelPool) pool).closeAsync();
107 } else {
108 try {
109 pool.close();
110 return GlobalEventExecutor.INSTANCE.newSucceededFuture(null);
111 } catch (Exception e) {
112 return GlobalEventExecutor.INSTANCE.newFailedFuture(e);
113 }
114 }
115 }
116
117 @Override
118 public final Iterator<Entry<K, P>> iterator() {
119 return new ReadOnlyIterator<Entry<K, P>>(map.entrySet().iterator());
120 }
121
122
123
124
125 public final int size() {
126 return map.size();
127 }
128
129
130
131
132 public final boolean isEmpty() {
133 return map.isEmpty();
134 }
135
136 @Override
137 public final boolean contains(K key) {
138 return map.containsKey(checkNotNull(key, "key"));
139 }
140
141
142
143
144 protected abstract P newPool(K key);
145
146 @Override
147 public final void close() {
148 for (K key: map.keySet()) {
149
150 removeAsyncIfSupported(key).syncUninterruptibly();
151 }
152 }
153 }