1 /*
2 * Copyright 2024 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.netty.channel;
17
18 import io.netty.util.concurrent.EventExecutorChooserFactory;
19 import io.netty.util.internal.EmptyArrays;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.concurrent.Executor;
25 import java.util.concurrent.ThreadFactory;
26
27 /**
28 * {@link IoEventLoopGroup} implementation that will handle its tasks with multiple threads.
29 * <p>
30 * This group supports advanced thread management strategies, such as dynamic auto-scaling,
31 * by providing a custom {@link EventExecutorChooserFactory}. To enable utilization-based
32 * auto-scaling, pass an instance of
33 * {@link io.netty.util.concurrent.AutoScalingEventExecutorChooserFactory}.
34 */
35 public class MultiThreadIoEventLoopGroup extends MultithreadEventLoopGroup implements IoEventLoopGroup {
36
37 /**
38 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup} using the default number
39 * of threads and default {@link ThreadFactory}.
40 */
41 public MultiThreadIoEventLoopGroup(IoHandlerFactory ioHandlerFactory) {
42 this(0, ioHandlerFactory);
43 }
44
45 /**
46 /**
47 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup} using the default {@link ThreadFactory}.
48 *
49 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
50 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
51 * IO.
52 */
53 public MultiThreadIoEventLoopGroup(int nThreads, IoHandlerFactory ioHandlerFactory) {
54 this(nThreads, (Executor) null, ioHandlerFactory);
55 }
56
57 /**
58 * Create a new instance using the default number of thread.
59 *
60 * @param threadFactory the {@link ThreadFactory} that is used.
61 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
62 * IO.
63 */
64 public MultiThreadIoEventLoopGroup(ThreadFactory threadFactory, IoHandlerFactory ioHandlerFactory) {
65 this(0, threadFactory, ioHandlerFactory);
66 }
67
68 /**
69 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup} using the default number
70 * of threads.
71 *
72 * @param executor the {@link Executor} that is used.
73 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
74 * IO.
75 */
76 public MultiThreadIoEventLoopGroup(Executor executor,
77 IoHandlerFactory ioHandlerFactory) {
78 super(0, executor, ioHandlerFactory);
79 }
80
81 /**
82 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
83 *
84 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
85 * @param executor the {@link Executor} that is used.
86 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
87 * IO.
88 */
89 public MultiThreadIoEventLoopGroup(int nThreads, Executor executor,
90 IoHandlerFactory ioHandlerFactory) {
91 super(nThreads, executor, ioHandlerFactory);
92 }
93
94 /**
95 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
96 *
97 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
98 * @param threadFactory the {@link ThreadFactory} that is used.
99 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
100 * IO.
101 */
102 public MultiThreadIoEventLoopGroup(int nThreads, ThreadFactory threadFactory,
103 IoHandlerFactory ioHandlerFactory) {
104 super(nThreads, threadFactory, ioHandlerFactory);
105 }
106
107 /**
108 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
109 *
110 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
111 * @param executor the {@link Executor} that is used.
112 * @param chooserFactory the {@link EventExecutorChooserFactory} that is used to choose the
113 * {@link IoEventLoop} when {@link MultiThreadIoEventLoopGroup#next()} is
114 * called.
115 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
116 * IO.
117 */
118 public MultiThreadIoEventLoopGroup(int nThreads, Executor executor,
119 EventExecutorChooserFactory chooserFactory,
120 IoHandlerFactory ioHandlerFactory) {
121 super(nThreads, executor, chooserFactory, ioHandlerFactory);
122 }
123
124 /**
125 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
126 *
127 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
128 * @param executor the {@link Executor} that is used.
129 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
130 * IO.
131 * @param args extra args that are passed to {@link #newChild(Executor, Object...)} method.
132 */
133 protected MultiThreadIoEventLoopGroup(int nThreads, Executor executor,
134 IoHandlerFactory ioHandlerFactory, Object... args) {
135 super(nThreads, executor, combine(ioHandlerFactory, args));
136 }
137
138 /**
139 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
140 *
141 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
142 * @param threadFactory the {@link ThreadFactory} that is used.
143 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
144 * IO.
145 * @param args extra args that are passed to {@link #newChild(Executor, Object...)} method.
146 */
147 protected MultiThreadIoEventLoopGroup(int nThreads, ThreadFactory threadFactory,
148 IoHandlerFactory ioHandlerFactory, Object... args) {
149 super(nThreads, threadFactory, combine(ioHandlerFactory, args));
150 }
151
152 /**
153 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
154 *
155 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
156 * @param threadFactory the {@link ThreadFactory} that is used.
157 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
158 * IO.
159 * @param chooserFactory the {@link EventExecutorChooserFactory} that is used to choose the
160 * @param args extra args that are passed to {@link #newChild(Executor, Object...)} method.
161 */
162 protected MultiThreadIoEventLoopGroup(int nThreads, ThreadFactory threadFactory,
163 IoHandlerFactory ioHandlerFactory,
164 EventExecutorChooserFactory chooserFactory,
165 Object... args) {
166 super(nThreads, threadFactory, chooserFactory, combine(ioHandlerFactory, args));
167 }
168
169 /**
170 * Creates a new instance of the {@link MultiThreadIoEventLoopGroup}.
171 *
172 * @param nThreads the number of threads and so {@link EventLoop}s that are created.
173 * @param executor the {@link Executor} that is used.
174 * @param ioHandlerFactory the {@link IoHandlerFactory} that will be used to create {@link IoHandler} for handling
175 * IO.
176 * @param chooserFactory the {@link EventExecutorChooserFactory} that is used to choose the
177 * @param args extra args that are passed to {@link #newChild(Executor, Object...)} method.
178 */
179 protected MultiThreadIoEventLoopGroup(int nThreads, Executor executor,
180 IoHandlerFactory ioHandlerFactory,
181 EventExecutorChooserFactory chooserFactory,
182 Object... args) {
183 super(nThreads, executor, chooserFactory, combine(ioHandlerFactory, args));
184 }
185
186 // The return type should be IoHandleEventLoop but we choose EventLoop to allow us to introduce the IoHandle
187 // concept without breaking API.
188 @Override
189 protected EventLoop newChild(Executor executor, Object... args) throws Exception {
190 IoHandlerFactory handlerFactory = (IoHandlerFactory) args[0];
191 Object[] argsCopy;
192 if (args.length > 1) {
193 argsCopy = new Object[args.length - 1];
194 System.arraycopy(args, 1, argsCopy, 0, argsCopy.length);
195 } else {
196 argsCopy = EmptyArrays.EMPTY_OBJECTS;
197 }
198 return newChild(executor, handlerFactory, argsCopy);
199 }
200
201 /**
202 * Creates a new {@link IoEventLoop} to use with the given {@link Executor} and {@link IoHandler}.
203 *
204 * @param executor the {@link Executor} that should be used to handle execution of tasks and IO.
205 * @param ioHandlerFactory the {@link IoHandlerFactory} that should be used to obtain {@link IoHandler} to
206 * handle IO.
207 * @param args extra arguments that are based by the constructor.
208 * @return the created {@link IoEventLoop}.
209 */
210 protected IoEventLoop newChild(Executor executor, IoHandlerFactory ioHandlerFactory,
211 @SuppressWarnings("unused") Object... args) {
212 return new SingleThreadIoEventLoop(this, executor, ioHandlerFactory);
213 }
214
215 @Override
216 public IoEventLoop next() {
217 return (IoEventLoop) super.next();
218 }
219
220 private static Object[] combine(IoHandlerFactory handlerFactory, Object... args) {
221 List<Object> combinedList = new ArrayList<Object>();
222 combinedList.add(handlerFactory);
223 if (args != null) {
224 Collections.addAll(combinedList, args);
225 }
226 return combinedList.toArray(new Object[0]);
227 }
228 }