001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.felix.framework.util;
020
021 /**
022 * This class implements a simple one-shot gate for threads. The gate
023 * starts closed and will block any threads that try to wait on it. Once
024 * opened, all waiting threads will be released. The gate cannot be reused.
025 **/
026 public class ThreadGate
027 {
028 private boolean m_open = false;
029 private Object m_msg = null;
030 private boolean m_initialized = false;
031
032 /**
033 * Open the gate and release any waiting threads.
034 **/
035 public synchronized void open()
036 {
037 m_open = true;
038 notifyAll();
039 }
040
041 /**
042 * Returns the message object associated with the gate; the
043 * message is just an arbitrary object used to pass information
044 * to the waiting threads.
045 * @return the message object associated with the gate.
046 **/
047 public synchronized Object getMessage()
048 {
049 return m_msg;
050 }
051
052 /**
053 * Sets the message object associated with the gate. The message
054 * object can only be set once, subsequent calls to this method
055 * are ignored.
056 * @param msg the message object to associate with this gate.
057 **/
058 public synchronized void setMessage(Object msg)
059 {
060 if (!m_initialized)
061 {
062 m_msg = msg;
063 m_initialized = true;
064 }
065 }
066
067 /**
068 * Wait for the gate to open.
069 * @return <tt>true</tt> if the gate was opened or <tt>false</tt> if the timeout expired.
070 * @throws java.lang.InterruptedException If the calling thread is interrupted;
071 * the gate still remains closed until opened.
072 **/
073 public synchronized boolean await(long timeout) throws InterruptedException
074 {
075 long start = System.currentTimeMillis();
076 long remaining = timeout;
077 while (!m_open)
078 {
079 wait(remaining);
080 if (timeout > 0)
081 {
082 remaining = timeout - (System.currentTimeMillis() - start);
083 if (remaining <= 0)
084 {
085 break;
086 }
087 }
088 }
089 return m_open;
090 }
091 }