View Javadoc
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 }