1 /* 2 * Copyright 2013 The Netty Project 3 * 4 * The Netty Project licenses this file to you under the Apache License, 5 * version 2.0 (the "License"); you may not use this file except in compliance 6 * with the License. You may obtain a copy of the License at: 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 package io.netty5.channel.group; 17 18 import io.netty5.bootstrap.ServerBootstrap; 19 import io.netty5.buffer.api.Buffer; 20 import io.netty5.buffer.api.DefaultBufferAllocators; 21 import io.netty5.channel.Channel; 22 import io.netty5.channel.ChannelHandler; 23 import io.netty5.channel.ChannelHandlerContext; 24 import io.netty5.channel.ChannelId; 25 import io.netty5.channel.EventLoop; 26 import io.netty5.channel.ServerChannel; 27 import io.netty5.util.concurrent.GlobalEventExecutor; 28 29 import java.nio.charset.StandardCharsets; 30 import java.util.Set; 31 32 /** 33 * A thread-safe {@link Set} that contains open {@link Channel}s and provides 34 * various bulk operations on them. Using {@link ChannelGroup}, you can 35 * categorize {@link Channel}s into a meaningful group (e.g. on a per-service 36 * or per-state basis.) A closed {@link Channel} is automatically removed from 37 * the collection, so that you don't need to worry about the life cycle of the 38 * added {@link Channel}. A {@link Channel} can belong to more than one 39 * {@link ChannelGroup}. 40 * 41 * <h3>Broadcast a message to multiple {@link Channel}s</h3> 42 * <p> 43 * If you need to broadcast a message to more than one {@link Channel}, you can 44 * add the {@link Channel}s associated with the recipients and call {@link ChannelGroup#write(Object)}: 45 * <pre> 46 * <strong>{@link ChannelGroup} recipients = 47 * new {@link DefaultChannelGroup}({@link GlobalEventExecutor}.INSTANCE);</strong> 48 * recipients.add(channelA); 49 * recipients.add(channelB); 50 * .. 51 * <strong>recipients.write({@link DefaultBufferAllocators#preferredAllocator()}.copyOf( 52 * "Service will shut down for maintenance in 5 minutes.", 53 * {@link StandardCharsets#UTF_8}));</strong> 54 * </pre> 55 * 56 * <h3>Simplify shutdown process with {@link ChannelGroup}</h3> 57 * <p> 58 * If both {@link ServerChannel}s and non-{@link ServerChannel}s exist in the 59 * same {@link ChannelGroup}, any requested I/O operations on the group are 60 * performed for the {@link ServerChannel}s first and then for the others. 61 * <p> 62 * This rule is very useful when you shut down a server in one shot: 63 * 64 * <pre> 65 * <strong>{@link ChannelGroup} allChannels = 66 * new {@link DefaultChannelGroup}({@link GlobalEventExecutor}.INSTANCE);</strong> 67 * 68 * public static void main(String[] args) throws Exception { 69 * {@link ServerBootstrap} b = new {@link ServerBootstrap}(..); 70 * ... 71 * b.childHandler(new MyHandler()); 72 * 73 * // Start the server 74 * b.getPipeline().addLast("handler", new MyHandler()); 75 * {@link Channel} serverChannel = b.bind(..).sync(); 76 * <strong>allChannels.add(serverChannel);</strong> 77 * 78 * ... Wait until the shutdown signal reception ... 79 * 80 * // Close the serverChannel and then all accepted connections. 81 * <strong>allChannels.close().await();</strong> 82 * } 83 * 84 * public class MyHandler implements {@link ChannelHandler} { 85 * {@code @Override} 86 * public void channelActive({@link ChannelHandlerContext} ctx) { 87 * // closed on shutdown. 88 * <strong>allChannels.add(ctx.channel());</strong> 89 * ctx.fireChannelActive(); 90 * } 91 * } 92 * </pre> 93 */ 94 public interface ChannelGroup extends Set<Channel>, Comparable<ChannelGroup> { 95 96 /** 97 * Returns the name of this group. A group name is purely for helping 98 * you to distinguish one group from others. 99 */ 100 String name(); 101 102 /** 103 * Returns the {@link Channel} which has the specified {@link ChannelId}. 104 * 105 * @return the matching {@link Channel} if found. {@code null} otherwise. 106 */ 107 Channel find(ChannelId id); 108 109 /** 110 * Writes the specified {@code message} to all {@link Channel}s in this 111 * group. 112 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically 113 * {@linkplain Buffer#copy() copied} to avoid a race condition. 114 * Please note that this operation is asynchronous as {@link Channel#write(Object)} is. 115 * 116 * @return itself 117 */ 118 ChannelGroupFuture write(Object message); 119 120 /** 121 * Writes the specified {@code message} to all {@link Channel}s in this 122 * group that are matched by the given {@link ChannelMatcher}. 123 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically 124 * {@linkplain Buffer#copy() copied} to avoid a race condition. 125 * Please note that this operation is asynchronous as {@link Channel#write(Object)} is. 126 * 127 * @return the {@link ChannelGroupFuture} instance that notifies when 128 * the operation is done for all channels 129 */ 130 ChannelGroupFuture write(Object message, ChannelMatcher matcher); 131 132 /** 133 * Flush all {@link Channel}s in this 134 * group. 135 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically 136 * {@linkplain Buffer#copy() copied} to avoid a race condition. 137 * Please note that this operation is asynchronous as {@link Channel#flush()} is. 138 * 139 * @return the {@link ChannelGroupFuture} instance that notifies when 140 * the operation is done for all channels 141 */ 142 ChannelGroup flush(); 143 144 /** 145 * Flush all {@link Channel}s in this group that are matched by the given {@link ChannelMatcher}. 146 * If the specified {@code message} is an instance of {@link Buffer}, it is automatically 147 * {@linkplain Buffer#copy() copied} to avoid a race condition. 148 * Please note that this operation is asynchronous as {@link Channel#flush()} is. 149 * 150 * @return the {@link ChannelGroupFuture} instance that notifies when 151 * the operation is done for all channels 152 */ 153 ChannelGroup flush(ChannelMatcher matcher); 154 155 /** 156 * Shortcut for calling {@link #write(Object)} and {@link #flush()}. 157 */ 158 ChannelGroupFuture writeAndFlush(Object message); 159 160 /** 161 * @deprecated Use {@link #writeAndFlush(Object)} instead. 162 */ 163 @Deprecated 164 ChannelGroupFuture flushAndWrite(Object message); 165 166 /** 167 * Shortcut for calling {@link #write(Object)} and {@link #flush()} and only act on 168 * {@link Channel}s that are matched by the {@link ChannelMatcher}. 169 */ 170 ChannelGroupFuture writeAndFlush(Object message, ChannelMatcher matcher); 171 172 /** 173 * @deprecated Use {@link #writeAndFlush(Object, ChannelMatcher)} instead. 174 */ 175 @Deprecated 176 ChannelGroupFuture flushAndWrite(Object message, ChannelMatcher matcher); 177 178 /** 179 * Disconnects all {@link Channel}s in this group from their remote peers. 180 * 181 * @return the {@link ChannelGroupFuture} instance that notifies when 182 * the operation is done for all channels 183 */ 184 ChannelGroupFuture disconnect(); 185 186 /** 187 * Disconnects all {@link Channel}s in this group from their remote peers, 188 * that are matched by the given {@link ChannelMatcher}. 189 * 190 * @return the {@link ChannelGroupFuture} instance that notifies when 191 * the operation is done for all channels 192 */ 193 ChannelGroupFuture disconnect(ChannelMatcher matcher); 194 195 /** 196 * Closes all {@link Channel}s in this group. If the {@link Channel} is 197 * connected to a remote peer or bound to a local address, it is 198 * automatically disconnected and unbound. 199 * 200 * @return the {@link ChannelGroupFuture} instance that notifies when 201 * the operation is done for all channels 202 */ 203 ChannelGroupFuture close(); 204 205 /** 206 * Closes all {@link Channel}s in this group that are matched by the given {@link ChannelMatcher}. 207 * If the {@link Channel} is connected to a remote peer or bound to a local address, it is 208 * automatically disconnected and unbound. 209 * 210 * @return the {@link ChannelGroupFuture} instance that notifies when 211 * the operation is done for all channels 212 */ 213 ChannelGroupFuture close(ChannelMatcher matcher); 214 215 /** 216 * @deprecated This method will be removed in the next major feature release. 217 * 218 * Deregister all {@link Channel}s in this group from their {@link EventLoop}. 219 * Please note that this operation is asynchronous as {@link Channel#deregister()} is. 220 * 221 * @return the {@link ChannelGroupFuture} instance that notifies when 222 * the operation is done for all channels 223 */ 224 @Deprecated 225 ChannelGroupFuture deregister(); 226 227 /** 228 * @deprecated This method will be removed in the next major feature release. 229 * 230 * Deregister all {@link Channel}s in this group from their {@link EventLoop} that are matched by the given 231 * {@link ChannelMatcher}. Please note that this operation is asynchronous as {@link Channel#deregister()} is. 232 * 233 * @return the {@link ChannelGroupFuture} instance that notifies when 234 * the operation is done for all channels 235 */ 236 @Deprecated 237 ChannelGroupFuture deregister(ChannelMatcher matcher); 238 239 /** 240 * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that are part of this 241 * {@link ChannelGroup}, at the time of calling, are closed. 242 */ 243 ChannelGroupFuture newCloseFuture(); 244 245 /** 246 * Returns the {@link ChannelGroupFuture} which will be notified when all {@link Channel}s that are part of this 247 * {@link ChannelGroup}, at the time of calling, are closed. 248 */ 249 ChannelGroupFuture newCloseFuture(ChannelMatcher matcher); 250 }