001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016: package org.columba.core.base;
017:
018: /**
019: * A Semaphore class to be used by multiple threads that needs to be notified when a
020: * thread has released this semaphore. Depending threads uses one of the
021: * waitUntilReleased() method to wait for the semaphore, then when the Thread that
022: * owns the Semaphore (called the hold() method) calls the release method all other
023: * threads are awaken.
024: *
025: * All threads that invoke waitUntilReleased() waits until a thread invokes the
026: * release()
027: *
028: * @author erma
029: */
030: public final class Semaphore {
031:
032: private Object lockObject = new Object();
033:
034: private boolean isReleased = false;
035:
036: /**
037: * Creates a new instance of Semaphore
038: */
039: public Semaphore() {
040: this (true);
041: }
042:
043: /**
044: * Creates a new instance of Semaphore
045: *
046: * @param isHolding if the semaphore should hold all threads from the begining or
047: * not.
048: */
049: public Semaphore(boolean isHolding) {
050: if (isHolding) {
051: hold();
052: } else {
053: release();
054: }
055: }
056:
057: /**
058: * Holds this semaphores. Threads that call the waitUntilReleased stops until the
059: * release() method is called.
060: *
061: * @see #release()
062: */
063: public void hold() {
064: isReleased = false;
065: }
066:
067: /**
068: * Waits the current thread until another thread invokes the relase() or
069: * continues if another thread already has invoked the release(). This method
070: * behaves exactly as if it simply performs the call waitUntilReleased(0).
071: *
072: * @throws InterruptedException if another thread has interrupted the current
073: * thread.
074: */
075: public void waitUntilReleased() throws InterruptedException {
076: waitUntilReleased(0);
077: }
078:
079: /**
080: * Waits the current thread until another thread invokes the relase() or
081: * continues if another thread already has invoked the release().
082: *
083: * @param timeout the maximum time to wait in milliseconds.
084: * @throws InterruptedException if another thread has interrupted the current
085: * thread.
086: */
087: public void waitUntilReleased(long timeout)
088: throws InterruptedException {
089: if (!isReleased) {
090: synchronized (lockObject) {
091: lockObject.wait(timeout);
092: }
093: }
094: }
095:
096: /**
097: * Release all threads that has invoked the waitUntilReleased().
098: */
099: public void release() {
100: isReleased = true;
101: synchronized (lockObject) {
102: lockObject.notifyAll();
103: }
104: }
105:
106: /**
107: * Returns if the semaphore holds all threads that invoke the waitUntilReleased()
108: * methods.
109: *
110: * @return true or false
111: */
112: public boolean isHolding() {
113: return !isReleased;
114: }
115: }
|