Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » cluster » util » [javadoc | source]
    1   /*
    2    * Copyright 1999,2004 The Apache Software Foundation.
    3    * 
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * 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,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   
   17   package org.apache.catalina.cluster.util;
   18   
   19   /**
   20    * The class <b>SingleRemoveSynchronizedAddLock</b> implement locking for accessing the queue
   21    * by a single remove thread and multiple add threads.
   22    *
   23    * A thread is only allowed to be either the remove or
   24    * an add thread.
   25    *
   26    * The lock can either be owned by the remove thread
   27    * or by a single add thread.
   28    *
   29    * If the remove thread tries to get the lock,
   30    * but the queue is empty, it will block (poll)
   31    * until an add threads adds an entry to the queue and
   32    * releases the lock.
   33    * 
   34    * If the remove thread and add threads compete for
   35    * the lock and an add thread releases the lock, then
   36    * the remove thread will get the lock first.
   37    *
   38    * The remove thread removes all entries in the queue
   39    * at once and proceeses them without further
   40    * polling the queue.
   41    *
   42    * The lock is not reentrant, in the sense, that all
   43    * threads must release an owned lock before competing
   44    * for the lock again!
   45    *
   46    * @author Rainer Jung
   47    * @author Peter Rossbach
   48    * @version 1.1
   49    */
   50    
   51   public class SingleRemoveSynchronizedAddLock {
   52       
   53       public SingleRemoveSynchronizedAddLock() {
   54       }
   55       
   56       public SingleRemoveSynchronizedAddLock(boolean dataAvailable) {
   57           this.dataAvailable=dataAvailable;
   58       }
   59       
   60       /**
   61        * Time in milliseconds after which threads
   62        * waiting for an add lock are woken up.
   63        * This is used as a safety measure in case
   64        * thread notification via the unlock methods
   65        * has a bug.
   66        */
   67       private long addWaitTimeout = 10000L;
   68   
   69       /**
   70        * Time in milliseconds after which threads
   71        * waiting for a remove lock are woken up.
   72        * This is used as a safety measure in case
   73        * thread notification via the unlock methods
   74        * has a bug.
   75        */
   76       private long removeWaitTimeout = 30000L;
   77   
   78       /**
   79        * The current remove thread.
   80        * It is set to the remove thread polling for entries.
   81        * It is reset to null when the remove thread
   82        * releases the lock and proceeds processing
   83        * the removed entries.
   84        */
   85       private Thread remover = null;
   86   
   87       /**
   88        * A flag indicating, if an add thread owns the lock.
   89        */
   90       private boolean addLocked = false;
   91   
   92       /**
   93        * A flag indicating, if the remove thread owns the lock.
   94        */
   95       private boolean removeLocked = false;
   96   
   97       /**
   98        * A flag indicating, if the remove thread is allowed
   99        * to wait for the lock. The flag is set to false, when aborting.
  100        */
  101       private boolean removeEnabled = true;
  102   
  103       /**
  104        * A flag indicating, if the remover needs polling.
  105        * It indicates, if the locked object has data available
  106        * to be removed.
  107        */
  108       private boolean dataAvailable = false;
  109   
  110       /**
  111        * @return Value of addWaitTimeout
  112        */
  113       public synchronized long getAddWaitTimeout() {
  114           return addWaitTimeout;
  115       }
  116   
  117       /**
  118        * Set value of addWaitTimeout
  119        */
  120       public synchronized void setAddWaitTimeout(long timeout) {
  121           addWaitTimeout = timeout;
  122       }
  123   
  124       /**
  125        * @return Value of removeWaitTimeout
  126        */
  127       public synchronized long getRemoveWaitTimeout() {
  128           return removeWaitTimeout;
  129       }
  130   
  131       /**
  132        * Set value of removeWaitTimeout
  133        */
  134       public synchronized void setRemoveWaitTimeout(long timeout) {
  135           removeWaitTimeout = timeout;
  136       }
  137   
  138       /**
  139        * Check if the locked object has data available
  140        * i.e. the remover can stop poling and get the lock.
  141        * @return True iff the lock Object has data available.
  142        */
  143       public synchronized boolean isDataAvailable() {
  144           return dataAvailable;
  145       }
  146   
  147       /**
  148        * Check if an add thread owns the lock.
  149        * @return True iff an add thread owns the lock.
  150        */
  151       public synchronized boolean isAddLocked() {
  152           return addLocked;
  153       }
  154   
  155       /**
  156        * Check if the remove thread owns the lock.
  157        * @return True iff the remove thread owns the lock.
  158        */
  159       public synchronized boolean isRemoveLocked() {
  160           return removeLocked;
  161       }
  162   
  163       /**
  164        * Check if the remove thread is polling.
  165        * @return True iff the remove thread is polling.
  166        */
  167       public synchronized boolean isRemovePolling() {
  168           if ( remover != null ) {
  169               return true;
  170           }
  171           return false;
  172       }
  173   
  174       /**
  175        * Acquires the lock by an add thread and sets the add flag.
  176        * If any add thread or the remove thread already acquired the lock
  177        * this add thread will block until the lock is released.
  178        */
  179       public synchronized void lockAdd() {
  180           if ( addLocked || removeLocked ) {
  181               do {
  182                   try {
  183                       wait(addWaitTimeout);
  184                   } catch ( InterruptedException e ) {
  185                   }
  186               } while ( addLocked || removeLocked );
  187           }
  188           addLocked=true;
  189       }
  190   
  191       /**
  192        * Acquires the lock by the remove thread and sets the remove flag.
  193        * If any add thread already acquired the lock or the queue is
  194        * empty, the remove thread will block until the lock is released
  195        * and the queue is not empty.
  196        */
  197       public synchronized boolean lockRemove() {
  198           removeLocked=false;
  199           removeEnabled=true;
  200           if ( ( addLocked || ! dataAvailable ) && removeEnabled ) {
  201               remover=Thread.currentThread();
  202               do {
  203                   try {
  204                       wait(removeWaitTimeout);
  205                   } catch ( InterruptedException e ) {
  206                   }
  207               } while ( ( addLocked || ! dataAvailable ) && removeEnabled );
  208               remover=null;
  209           }
  210           if ( removeEnabled ) {
  211               removeLocked=true;
  212           } 
  213           return removeLocked;
  214       }
  215   
  216       /**
  217        * Releases the lock by an add thread and reset the remove flag.
  218        * If the reader thread is polling, notify it.
  219        */
  220       public synchronized void unlockAdd(boolean dataAvailable) {
  221           addLocked=false;
  222           this.dataAvailable=dataAvailable;
  223           if ( ( remover != null ) && ( dataAvailable || ! removeEnabled ) ) {
  224               remover.interrupt();
  225           } else {
  226               notifyAll();
  227           }
  228       }
  229   
  230       /**
  231        * Releases the lock by the remove thread and reset the add flag.
  232        * Notify all waiting add threads,
  233        * that the lock has been released by the remove thread.
  234        */
  235       public synchronized void unlockRemove() {
  236           removeLocked=false;
  237           dataAvailable=false;
  238           notifyAll();
  239       }
  240   
  241       /**
  242        * Abort any polling remover thread
  243        */
  244       public synchronized void abortRemove() {
  245           removeEnabled=false;
  246           if ( remover != null ) {
  247               remover.interrupt();
  248           }
  249       }
  250   
  251   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » cluster » util » [javadoc | source]