001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2017-2018 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.core.internal;
020
021import java.time.Instant;
022
023import org.jgrapes.core.Components;
024
025/**
026 * The base class for completeion locks.
027 */
028@SuppressWarnings("PMD.AbstractClassWithoutAbstractMethod")
029public abstract class CompletionLockBase {
030
031    private final EventBase<?> event;
032    private final long timeout;
033    private Components.Timer timer;
034
035    /**
036     * @param event the event to be locked
037     * @param timeout
038     */
039    protected CompletionLockBase(EventBase<?> event, long timeout) {
040        this.event = event;
041        this.timeout = timeout;
042        event.addCompletionLock(this);
043    }
044
045    /* default */ long getTimeout() {
046        return timeout;
047    }
048
049    /**
050     * Removes this completion lock from the event that it was created for.
051     * 
052     * This method may be invoked even if the completion lock has already
053     * been removed. This allows locks to be used for disjunctive wait.
054     */
055    public void remove() {
056        event.removeCompletionLock(this);
057    }
058
059    /* default */ CompletionLockBase startTimer() {
060        if (timeout == 0) {
061            return this;
062        }
063        timer = Components.schedule(scheduledFor -> {
064            event.removeCompletionLock(this);
065        }, Instant.now().plusMillis(timeout));
066        return this;
067    }
068
069    /* default */ void cancelTimer() {
070        synchronized (this) {
071            if (timer != null) {
072                timer.cancel();
073                timer = null;
074            }
075        }
076    }
077}