/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.tomcat.util.net; import java.net.Socket; import org.apache.tomcat.util.threads.ThreadPoolRunnable; /* * I switched the threading model here. * * We used to have a "listener" thread and a "connection" * thread, this results in code simplicity but also a needless * thread switch. * * Instead I am now using a pool of threads, all the threads are * simmetric in their execution and no thread switch is needed. */ class LeaderFollowerWorkerThread implements ThreadPoolRunnable { /* This is not a normal Runnable - it gets attached to an existing thread, runs and when run() ends - the thread keeps running. It's better to keep the name ThreadPoolRunnable - avoid confusion. We also want to use per/thread data and avoid sync wherever possible. */ PoolTcpEndpoint endpoint; public LeaderFollowerWorkerThread(PoolTcpEndpoint endpoint) { this.endpoint = endpoint; } public Object[] getInitData() { // no synchronization overhead, but 2 array access Object obj[]=new Object[2]; obj[1]= endpoint.getConnectionHandler().init(); obj[0]=new TcpConnection(); return obj; } public void runIt(Object perThrData[]) { // Create per-thread cache if (endpoint.isRunning()) { // Loop if endpoint is paused while (endpoint.isPaused()) { try { Thread.sleep(1000); } catch (InterruptedException e) { // Ignore } } // Accept a new connection Socket s = null; try { s = endpoint.acceptSocket(); } finally { // Continue accepting on another thread... if (endpoint.isRunning()) { endpoint.tp.runIt(this); } } // Process the connection if (null != s) { endpoint.processSocket(s, (TcpConnection) perThrData[0], (Object[]) perThrData[1]); } } } }