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   */
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 }