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