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