001package ch.qos.logback.core.util;
002
003import ch.qos.logback.core.Context;
004import ch.qos.logback.core.spi.ContextAwareBase;
005
006/**
007 * Allows masking of interrupt flag if previously the flag is already set. Does
008 * nothing otherwise.
009 * 
010 * Typical use:
011 * 
012 * <pre>
013 * InterruptUtil interruptUtil = new InterruptUtil(context);
014 * 
015 * try {
016 *     interruptUtil.maskInterruptFlag();
017 *     someOtherThread.join(delay);
018 * } catch (InterruptedException e) {
019 *     // reachable only if join does not succeed within delay.
020 *     // Without the maskInterruptFlag() call, the join() would have returned
021 *     // immediately
022 *     // had the current thread been interrupted previously, i.e. before entering
023 *     // the above block
024 * } finally {
025 *     interruptUtil.unmaskInterruptFlag();
026 * }
027 * </pre>
028 * 
029 * @author Ceki Gulcu
030 * @since 1.2.2
031 */
032public class InterruptUtil extends ContextAwareBase {
033
034    final boolean previouslyInterrupted;
035
036    public InterruptUtil(Context context) {
037        super();
038        setContext(context);
039        previouslyInterrupted = Thread.currentThread().isInterrupted();
040    }
041
042    public void maskInterruptFlag() {
043        if (previouslyInterrupted) {
044            Thread.interrupted();
045        }
046    }
047
048    public void unmaskInterruptFlag() {
049        if (previouslyInterrupted) {
050            try {
051                Thread.currentThread().interrupt();
052            } catch (SecurityException se) {
053                addError("Failed to interrupt current thread", se);
054            }
055        }
056    }
057
058}