001 /* 002 Based on some code found with Google, somewhere in the Internet 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.util; 019 020 import org.apache.log4j.Logger; 021 022 023 024 /** 025 * This is a simple implementation of the well-known semaphore synchronization feature. 026 * 027 * <p>It allows a given number of thread to be blocked waiting for a 028 * resource to be freed by the threads that are currently using it. */ 029 030 public class Semaphore { 031 static Logger logger = Logger.getLogger("semaphore"); 032 033 /** The available resources count. */ 034 protected int count = 0; 035 private int waitingCount = 0; 036 037 /** 038 * The semaphore constructor that allows the programmer to assign a 039 * number of resources item that are greater than 0 or 1 (meaning 040 * that several threads (n exactly) can use the semaphore at the 041 * same time). 042 * 043 * @param n the number of resource items */ 044 045 public Semaphore(int n) { 046 this.count = n; 047 } 048 049 /** 050 * The default constructor for this semaphore equivalent to 051 * <code>Semaphore(0)</code>. 052 * 053 * <p>This constructor means that no resources are available by 054 * default. Thus, the first thread (t1) that will acquire the 055 * semaphore will eventually by blocked until another thread (t2) 056 * releases a resource on this semaphore. 057 * 058 * <p>This use of the semaphore feature is quite strange regarding 059 * resources (since the deblocking thread (t2) releases a resource 060 * that it never acquired!!) but it can be very usefull for 061 * synchronization especially if t1 waits for a result that is 062 * being calculating by t2 and that is not yet available. */ 063 064 public Semaphore() { 065 } 066 067 /** 068 * Gets the number of threads that are currently blocked on this 069 * semaphore. 070 * 071 * <p>This method is an indication but is not safe since a thread 072 * can be released meantime you evaluate its result. 073 * 074 * @return the waiting threads number at the moment you have asked 075 * it */ 076 077 public int getWaitingCount() { 078 return waitingCount; 079 } 080 081 public int getCount() { 082 return count; 083 } 084 085 /** 086 * Acquires a resource on this semaphore with no timeout. 087 * 088 * <p>If no resources are available anymore (count == 0), then the 089 * thread that performed this call is blocked until another thread 090 * releases a resource.</p> 091 * 092 * @return true if the resource could be aquired. 093 * 094 * @see #acquire(long) 095 * @see #release() 096 */ 097 public boolean acquire() { 098 return acquire(0); 099 } 100 101 /** 102 * Acquires a resource on this semaphore. 103 * 104 * <p>If no resources are available anymore (count == 0), then the 105 * thread that performed this call is blocked until another thread 106 * releases a resource. 107 * 108 * @param timeout milliseconds to wait for. 0 means wait for ever. 109 * @return true if the resource could be aquired. 110 * 111 * @see #acquire() 112 * @see #release() 113 */ 114 public synchronized boolean acquire(long timeout) { 115 waitingCount++; 116 while(count == 0) { 117 logger.debug(this+" acquire, waiting; count = "+count); 118 try { 119 wait(timeout); 120 // I think this is not correct in the general case but 121 // should work if there's only on thread waiting. 122 if (count==0) 123 return false; 124 } catch (InterruptedException e) { 125 //keep trying 126 } 127 } 128 logger.debug(this+" acquired, count = "+count+"(--)"); 129 count--; 130 waitingCount--; 131 return true; 132 } 133 134 /** 135 * Releases a resource on this semaphore. 136 * 137 * <p>If one or several threads are blocked, waiting for a resource 138 * to be available, then this call will necessaraly makes one of 139 * them take the semaphore's monitor (the others, if any will block 140 * again). There is absolutly no way of knowing which thread will 141 * take the monitor first. 142 * 143 * @see #acquire() 144 */ 145 public synchronized void release() { 146 logger.debug(this+" release, count = "+count+"(++)"); 147 count++; 148 notify(); //alert a thread that's blocking on this semaphore 149 } 150 }