/*==========================================================================*\ | $Id: TokenDispenser.java,v 1.5 2011/12/25 21:18:24 stedwar2 Exp $ |*-------------------------------------------------------------------------*| | Copyright (C) 2009-2011 Virginia Tech | | This file is part of Web-CAT. | | Web-CAT is free software; you can redistribute it and/or modify | it under the terms of the GNU Affero General Public License as published | by the Free Software Foundation; either version 3 of the License, or | (at your option) any later version. | | Web-CAT is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU Affero General Public License | along with Web-CAT; if not, see <http://www.gnu.org/licenses/>. \*==========================================================================*/ package org.webcat.jobqueue; import java.util.*; import org.apache.log4j.Logger; // ------------------------------------------------------------------------- /** * This class is used as a wait queue for worker threads, and allows * controlled dispensing of job tokens to worker threads. A "token" is * nothing more than granting permission to execute. This class is * based off the original GraderQueue class in the Grader * subsystem. * * @author Stephen Edwards * @author Last changed by $Author: stedwar2 $ * @version $Revision: 1.5 $, $Date: 2011/12/25 21:18:24 $ */ public class TokenDispenser { //~ Constructors .......................................................... // ---------------------------------------------------------- /** * Default constructor */ public TokenDispenser(String name, int initialCount) { this.name = name; this.tokens = initialCount; log.debug("creating token dispenser: " + name()); } //~ Methods ............................................................... // ---------------------------------------------------------- /** * Get the name of this dispenser (primarily used for debugging/info * purposes). * @return This dispenser's name. */ public String name() { return name; } // ---------------------------------------------------------- /** * Retrieve the next available token, blocking until one is available. */ public synchronized void getJobToken() { while (tokens == 0) { try { wait(); } catch (InterruptedException e) { log.error(name() + ": client was interrupted while waiting for a token."); } } tokens--; if (log.isDebugEnabled()) { log.debug(name() + ": releasing token to worker thread (" + tokens + " tokens remain)"); } } // ---------------------------------------------------------- /** * Add a token to the dispenser. */ public synchronized void depositToken() { if (log.isDebugEnabled()) { log.debug(name() + ": depositing one token"); } tokens++; notify(); } // ---------------------------------------------------------- /** * Add multiple tokens to the dispenser. * * @param count The number of tokens to add. */ public synchronized void depositTokens(long count) { if (log.isDebugEnabled()) { log.debug(name() + ": depositing " + count + " tokens"); } if (count > 0) { tokens += count; notify(); } } // ---------------------------------------------------------- /** * Add multiple tokens to the dispenser to ensure at least N are * available. * * @param N The minimum number of tokens to guarantee are present. * If fewer are in the dispenser, the difference will be added. */ public synchronized void ensureAtLeastNTokens(int n) { int amount = (n > tokens) ? (n - tokens) : 0; if (log.isDebugEnabled()) { log.debug(name() + ": ensuring " + amount + " tokens (already holding " + tokens + " tokens)"); } depositTokens(amount); } // ---------------------------------------------------------- @Override public String toString() { return getClass().getSimpleName() + " " + name() + " [" + tokens + " tokens]"; } //~ Instance/static variables ............................................. int tokens; private String name; static Logger log = Logger.getLogger( TokenDispenser.class ); }