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;
022import org.jgrapes.core.Components;
023
024/**
025 * The base class for completeion locks.
026 */
027@SuppressWarnings("PMD.AbstractClassWithoutAbstractMethod")
028public abstract class CompletionLockBase {
029
030    private final EventBase<?> event;
031    private final long timeout;
032    private Components.Timer timer;
033
034    /**
035     * @param event the event to be locked
036     * @param timeout
037     */
038    protected CompletionLockBase(EventBase<?> event, long timeout) {
039        this.event = event;
040        this.timeout = timeout;
041        event.addCompletionLock(this);
042    }
043
044    /* default */ long getTimeout() {
045        return timeout;
046    }
047
048    /**
049     * Removes this completion lock from the event that it was created for.
050     * 
051     * This method may be invoked even if the completion lock has already
052     * been removed. This allows locks to be used for disjunctive wait.
053     */
054    public void remove() {
055        event.removeCompletionLock(this);
056    }
057
058    /* default */ CompletionLockBase startTimer() {
059        if (timeout == 0) {
060            return this;
061        }
062        timer = Components.schedule(scheduledFor -> {
063            event.removeCompletionLock(this);
064        }, Instant.now().plusMillis(timeout));
065        return this;
066    }
067
068    /* default */ void cancelTimer() {
069        synchronized (this) {
070            if (timer != null) {
071                timer.cancel();
072                timer = null;
073            }
074        }
075    }
076}