1 /* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/impl/conn/tsccm/RefQueueWorker.java $ 3 * $Revision: 673450 $ 4 * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $ 5 * 6 * ==================================================================== 7 * 8 * Licensed to the Apache Software Foundation (ASF) under one or more 9 * contributor license agreements. See the NOTICE file distributed with 10 * this work for additional information regarding copyright ownership. 11 * The ASF licenses this file to You under the Apache License, Version 2.0 12 * (the "License"); you may not use this file except in compliance with 13 * the License. You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 * ==================================================================== 23 * 24 * This software consists of voluntary contributions made by many 25 * individuals on behalf of the Apache Software Foundation. For more 26 * information on the Apache Software Foundation, please see 27 * <http://www.apache.org/>. 28 * 29 */ 30 31 package org.apache.http.impl.conn.tsccm; 32 33 import java.lang.ref.Reference; 34 import java.lang.ref.ReferenceQueue; 35 36 import org.apache.commons.logging.Log; 37 import org.apache.commons.logging.LogFactory; 38 39 40 41 /** 42 * A worker thread for processing queued references. 43 * {@link Reference Reference}s can be 44 * {@link ReferenceQueue queued} 45 * automatically by the garbage collector. 46 * If that feature is used, a daemon thread should be executing 47 * this worker. It will pick up the queued references and pass them 48 * on to a handler for appropriate processing. 49 */ 50 public class RefQueueWorker implements Runnable { 51 52 private final Log log = LogFactory.getLog(getClass()); 53 54 /** The reference queue to monitor. */ 55 protected final ReferenceQueue<?> refQueue; 56 57 /** The handler for the references found. */ 58 protected final RefQueueHandler refHandler; 59 60 61 /** 62 * The thread executing this handler. 63 * This attribute is also used as a shutdown indicator. 64 */ 65 protected volatile Thread workerThread; 66 67 68 /** 69 * Instantiates a new worker to listen for lost connections. 70 * 71 * @param queue the queue on which to wait for references 72 * @param handler the handler to pass the references to 73 */ 74 public RefQueueWorker(ReferenceQueue<?> queue, RefQueueHandler handler) { 75 if (queue == null) { 76 throw new IllegalArgumentException("Queue must not be null."); 77 } 78 if (handler == null) { 79 throw new IllegalArgumentException("Handler must not be null."); 80 } 81 82 refQueue = queue; 83 refHandler = handler; 84 } 85 86 87 /** 88 * The main loop of this worker. 89 * If initialization succeeds, this method will only return 90 * after {@link #shutdown shutdown()}. Only one thread can 91 * execute the main loop at any time. 92 */ 93 public void run() { 94 95 if (this.workerThread == null) { 96 this.workerThread = Thread.currentThread(); 97 } 98 99 while (this.workerThread == Thread.currentThread()) { 100 try { 101 // remove the next reference and process it 102 Reference<?> ref = refQueue.remove(); 103 refHandler.handleReference(ref); 104 } catch (InterruptedException e) { 105 //@@@ is logging really necessary? this here is the 106 //@@@ only reason for having a log in this class 107 if (log.isDebugEnabled()) { 108 log.debug(this.toString() + " interrupted", e); 109 } 110 } 111 } 112 } 113 114 115 /** 116 * Shuts down this worker. 117 * It can be re-started afterwards by another call to {@link #run run()}. 118 */ 119 public void shutdown() { 120 Thread wt = this.workerThread; 121 if (wt != null) { 122 this.workerThread = null; // indicate shutdown 123 wt.interrupt(); 124 } 125 } 126 127 128 /** 129 * Obtains a description of this worker. 130 * 131 * @return a descriptive string for this worker 132 */ 133 @Override 134 public String toString() { 135 return "RefQueueWorker::" + this.workerThread; 136 } 137 138 } // class RefQueueWorker 139 140