001package jmri.jmrit.audio;
002
003/**
004 * Base implementation of all common thread code for use by threads in the
005 * various Audio classes.
006 * <hr>
007 * This file is part of JMRI.
008 * <p>
009 * JMRI is free software; you can redistribute it and/or modify it under the
010 * terms of version 2 of the GNU General Public License as published by the Free
011 * Software Foundation. See the "COPYING" file for a copy of this license.
012 * <p>
013 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
014 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
015 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
016 *
017 * @author Matthew Harris copyright (c) 2009
018 */
019public abstract class AbstractAudioThread extends Thread implements AudioThread {
020
021    /**
022     * True while the thread is running.
023     */
024    private boolean alive = true;
025
026    /**
027     * True when thread should die.
028     */
029    private boolean die = false;
030
031    /**
032     * Simple counter to ensure that each created thread has a unique name.
033     */
034    private static long counter;
035
036    /**
037     * Default constructor that gives this thread a unique name based on the
038     * value of the static counter
039     */
040    public AbstractAudioThread() {
041        this.setName("audio-" + AbstractAudioThread.nextCounter());
042    }
043
044    private synchronized static long nextCounter() {
045        return counter++;
046    }
047
048    /**
049     * Perform necessary cleanup routines before shutting down.
050     */
051    protected void cleanup() {
052
053        // Thread is to shutdown
054        die(SET, true);
055
056        // End of thread
057        alive(SET, false);
058    }
059
060    @Override
061    public boolean isThreadAlive() {
062        return alive(GET, NA);
063    }
064
065    @Override
066    public void die() {
067        die(SET, true);
068    }
069
070    /**
071     * Checks if the thread is in the process of shutting down.
072     *
073     * @return true, if thread should die
074     */
075    protected boolean dying() {
076        return die(GET, NA);
077    }
078
079    /**
080     * Based on the 'action' parameter, sets or returns if the thread is running.
081     *
082     * @param action GET or SET
083     * @param value  for action==SET, new value; for action==GET, NA
084     * @return true, when thread is alive
085     */
086    private synchronized boolean alive(boolean action, boolean value) {
087        if (action == SET) {
088            alive = value;
089        }
090        return alive;
091    }
092
093    /**
094     * Based on the 'action' parameter, sets or returns if the thread should die.
095     *
096     * @param action GET or SET
097     * @param value  for action==SET, new value; for action==GET, NA
098     * @return true, when thread should die
099     */
100    private synchronized boolean die(boolean action, boolean value) {
101        if (action == SET) {
102            die = value;
103        }
104        return die;
105    }
106
107    /**
108     * Sleep for the specified number of milliseconds.
109     * <p>
110     * (Avoids cluttering the main code with the try-catch construct)
111     *
112     * @param ms number of milliseconds to sleep for
113     */
114    protected static void snooze(long ms) {
115        try {
116            Thread.sleep(ms);
117        } catch (InterruptedException ex) {
118        }
119    }
120
121}