1 /*
2 * Copyright 2009 Red Hat, Inc.
3 *
4 * Red Hat licenses this file to you under the Apache License, version 2.0
5 * (the "License"); you may not use this file except in compliance with the
6 * License. You may obtain a copy of the License at:
7 *
8 * http://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 org.jboss.netty.channel.socket.oio;
17
18 import java.util.concurrent.Executor;
19 import java.util.concurrent.RejectedExecutionException;
20
21 import org.jboss.netty.channel.Channel;
22 import org.jboss.netty.channel.ChannelPipeline;
23 import org.jboss.netty.channel.group.ChannelGroup;
24 import org.jboss.netty.channel.socket.DatagramChannel;
25 import org.jboss.netty.channel.socket.DatagramChannelFactory;
26 import org.jboss.netty.util.internal.ExecutorUtil;
27
28 /**
29 * A {@link DatagramChannelFactory} which creates a blocking I/O based
30 * {@link DatagramChannel}. It utilizes the good old blocking I/O API which
31 * has support for multicast.
32 *
33 * <h3>How threads work</h3>
34 * <p>
35 * There is only one type of threads in {@link OioDatagramChannelFactory};
36 * worker threads.
37 *
38 * <h4>Worker threads</h4>
39 * <p>
40 * Each {@link Channel} has a dedicated worker thread, just like a
41 * traditional blocking I/O thread model.
42 *
43 * <h3>Life cycle of threads and graceful shutdown</h3>
44 * <p>
45 * Worker threads are acquired from the {@link Executor} which was specified
46 * when a {@link OioDatagramChannelFactory} was created (i.e. {@code workerExecutor}.)
47 * Therefore, you should make sure the specified {@link Executor} is able to
48 * lend the sufficient number of threads.
49 * <p>
50 * Worker threads are acquired lazily, and then released when there's nothing
51 * left to process. All the related resources are also released when the
52 * worker threads are released. Therefore, to shut down a service gracefully,
53 * you should do the following:
54 *
55 * <ol>
56 * <li>close all channels created by the factory usually using
57 * {@link ChannelGroup#close()}, and</li>
58 * <li>call {@link #releaseExternalResources()}.</li>
59 * </ol>
60 *
61 * Please make sure not to shut down the executor until all channels are
62 * closed. Otherwise, you will end up with a {@link RejectedExecutionException}
63 * and the related resources might not be released properly.
64 *
65 * <h3>Limitation</h3>
66 * <p>
67 * A {@link DatagramChannel} created by this factory does not support asynchronous
68 * operations. Any I/O requests such as {@code "write"} will be performed in a
69 * blocking manner.
70 *
71 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
72 * @author <a href="http://gleamynode.net/">Trustin Lee</a>
73 *
74 * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
75 *
76 * @apiviz.landmark
77 */
78 public class OioDatagramChannelFactory implements DatagramChannelFactory {
79
80 private final Executor workerExecutor;
81 final OioDatagramPipelineSink sink;
82
83 /**
84 * Creates a new instance.
85 *
86 * @param workerExecutor
87 * the {@link Executor} which will execute the I/O worker threads
88 */
89 public OioDatagramChannelFactory(Executor workerExecutor) {
90 if (workerExecutor == null) {
91 throw new NullPointerException("workerExecutor");
92 }
93 this.workerExecutor = workerExecutor;
94 sink = new OioDatagramPipelineSink(workerExecutor);
95 }
96
97 public DatagramChannel newChannel(ChannelPipeline pipeline) {
98 return new OioDatagramChannel(this, pipeline, sink);
99 }
100
101 public void releaseExternalResources() {
102 ExecutorUtil.terminate(workerExecutor);
103 }
104 }