001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.tomcat.util.net;
019:
020: import java.net.Socket;
021:
022: import org.apache.tomcat.util.threads.ThreadWithAttributes;
023:
024: /**
025: * Regular master slave thread pool. Slave threads will wait for work.
026: */
027: class MasterSlaveWorkerThread implements Runnable {
028:
029: protected PoolTcpEndpoint endpoint;
030: protected String threadName;
031: protected boolean stopped = false;
032: private Object threadSync = new Object();
033: private Thread thread = null;
034: private boolean available = false;
035: private Socket socket = null;
036: private TcpConnection con = new TcpConnection();
037: private Object[] threadData = null;
038:
039: public MasterSlaveWorkerThread(PoolTcpEndpoint endpoint,
040: String threadName) {
041: this .endpoint = endpoint;
042: this .threadName = threadName;
043: }
044:
045: /**
046: * Process an incoming TCP/IP connection on the specified socket. Any
047: * exception that occurs during processing must be logged and swallowed.
048: * <b>NOTE</b>: This method is called from our Connector's thread. We
049: * must assign it to our own thread so that multiple simultaneous
050: * requests can be handled.
051: *
052: * @param socket TCP socket to process
053: */
054: synchronized void assign(Socket socket) {
055:
056: // Wait for the Processor to get the previous Socket
057: while (available) {
058: try {
059: wait();
060: } catch (InterruptedException e) {
061: }
062: }
063:
064: // Store the newly available Socket and notify our thread
065: this .socket = socket;
066: available = true;
067: notifyAll();
068:
069: }
070:
071: /**
072: * Await a newly assigned Socket from our Connector, or <code>null</code>
073: * if we are supposed to shut down.
074: */
075: private synchronized Socket await() {
076:
077: // Wait for the Connector to provide a new Socket
078: while (!available) {
079: try {
080: wait();
081: } catch (InterruptedException e) {
082: }
083: }
084:
085: // Notify the Connector that we have received this Socket
086: Socket socket = this .socket;
087: available = false;
088: notifyAll();
089:
090: return (socket);
091:
092: }
093:
094: /**
095: * The background thread that listens for incoming TCP/IP connections and
096: * hands them off to an appropriate processor.
097: */
098: public void run() {
099:
100: // Process requests until we receive a shutdown signal
101: while (!stopped) {
102:
103: // Wait for the next socket to be assigned
104: Socket socket = await();
105: if (socket == null)
106: continue;
107:
108: // Process the request from this socket
109: endpoint.processSocket(socket, con, threadData);
110:
111: // Finish up this request
112: endpoint.recycleWorkerThread(this );
113:
114: }
115:
116: // Tell threadStop() we have shut ourselves down successfully
117: synchronized (threadSync) {
118: threadSync.notifyAll();
119: }
120:
121: }
122:
123: /**
124: * Start the background processing thread.
125: */
126: public void start() {
127: threadData = endpoint.getConnectionHandler().init();
128: thread = new ThreadWithAttributes(null, this );
129: thread.setName(threadName);
130: thread.setDaemon(true);
131: thread.start();
132: }
133:
134: /**
135: * Stop the background processing thread.
136: */
137: public void stop() {
138: stopped = true;
139: assign(null);
140: thread = null;
141: threadData = null;
142: }
143:
144: }
|