001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.concurrent;
019
020import net.tridentsdk.docs.InternalUseOnly;
021
022import javax.annotation.concurrent.ThreadSafe;
023
024/**
025 * A wrapper over {@link java.lang.Runnable} that provides access to the scheduling facilities after scheduled
026 *
027 * @author The TridentSDK Team
028 * @since 0.3-alpha-DP
029 */
030@ThreadSafe
031public abstract class ScheduledRunnable implements Runnable {
032    private static volatile int currentId = 0;
033
034    private final int id;
035    private volatile ScheduledTask task;
036
037    public ScheduledRunnable() {
038        id = currentId += 1;
039    }
040
041    /**
042     * Guaranteed to be run before this Runnable on the main thread, even if this runnable is going to be run
043     * asynchronously, useful for collecting resources to work on.
044     *
045     * <p>This method is invoked synchronously relative to the {@link #run()} method</p>
046     */
047    public void beforeRun() {
048    }
049
050    /**
051     * Runs after this runnable has finished asynchronously
052     *
053     * <p>This method does not require the code to be thread-safe</p>
054     */
055    public void afterAsyncRun() {
056    }
057
058    /**
059     * Runs after this runnable has been executed synchronously
060     */
061    public void afterSyncRun() {
062    }
063
064    /**
065     * Cancels the task and removes from execution. See {@link ScheduledTask#cancel()}
066     *
067     * <p>WARNING: This is a delegated function. DO NOT call this method before it is scheduled. A NullPointerException
068     * will be thrown. This can be called when {@code task() != null}.</p>
069     */
070    public final void cancel() {
071        task.cancel();
072    }
073
074    /**
075     * Gets how long between runs this is supposed to wait if it is a repeating task
076     *
077     * <p>WARNING: This is a delegated function. DO NOT call this method before it is scheduled. A NullPointerException
078     * will be thrown. This can be called when {@code task() != null}.</p>
079     */
080    public final long interval() {
081        return task.interval();
082    }
083
084    /**
085     * Sets how long this runnable should wait between executions if this is a repeating task
086     *
087     * <p>If this task is  synchronous to the main thread, the change will be immediate, if it is not, the change may
088     * take an iteration to take effect, however {@link ScheduledRunnable#interval()} will reflect the changes
089     * immediately</p>
090     *
091     * <p>WARNING: This is a delegated function. DO NOT call this method before it is scheduled. A NullPointerException
092     * will be thrown. This can be called when {@code task() != null}.</p>
093     */
094    public final void setInterval(long interval) {
095        task.setInterval(interval);
096    }
097
098    /**
099     * Used internally to refer to this runnable, probably shouldn't be used by plugins
100     */
101    public final int id() {
102        return this.id;
103    }
104
105    /**
106     * The scheduled representation of the runnable
107     *
108     * @return the {@link ScheduledTask} object held within the scheduling implementation
109     */
110    public ScheduledTask asScheduledTask() {
111        return this.task;
112    }
113
114    @InternalUseOnly
115    public void markSchedule(ScheduledTask task) {
116        this.task = task;
117    }
118}