org.apache.tomcat.util.net.LeaderFollowerWorkerThread Maven / Gradle / Ivy
/*
* 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]);
}
}
}
}