package org.maachang.util.thread ;

/**
 * ループスレッド用オブジェクト.
 *  
 * @version 2008/05/25
 * @author  masahito suzuki
 * @since  MaachangBase 1.00
 */
public abstract class LoopThread extends Thread {
    
    /**
     * スレッド停止管理フラグ.
     */
    private volatile boolean stopFlag = true ;
    
    /**
     * スレッドID.
     */
    protected int threadId = -1 ;
    
    /**
     * オブジェクトクリア処理.
     * <p>スレッドが停止したときに呼び出されます.</p>
     */
    protected abstract void clear() ;
    
    /**
     * 実行処理.
     * <p>スレッド実行を行う実装を行います.</p>
     * @return boolean [false]の場合、Thread.sleep(30)が発生します.
     * @exception Exception 例外.
     */
    protected abstract boolean execution() throws Exception ;
    
    /**
     * 例外発生時の処理を実装.
     * <p>スレッド内で例外が発生した場合の実装です.</p>
     * @param e Throwable 発生した例外が設定されます.
     */
    protected void toException( Throwable e ) {
        
    }
    
    /**
     * スレッド開始.
     * @exception Exception 例外.
     */
    public synchronized void startThread() throws Exception {
        this.stopFlag = false ;
        this.setDaemon( true ) ;
        this.start() ;
    }
    
    /**
     * スレッドIDを取得.
     * @return int スレッドIDが返されます.
     */
    public int getThreadId() {
        return threadId ;
    }
    
    /**
     * スレッド停止.
     */
    public void stopThread() {
        setStop( true ) ;
    }
    
    /**
     * スレッドが停止しているかチェック.
     * @return boolean [true]の場合、スレッド停止しています.
     */
    public synchronized boolean isStop() {
        return stopFlag ;
    }
    
    /**
     * スレッド停止.
     */
    protected synchronized void setStop( boolean mode ) {
        this.stopFlag = mode ;
    }
    
    /**
     * スレッド実行処理.
     */
    public void run() {
        boolean endFlag = false ;
        ThreadDeath threadDeach = null ;
        for( ;; ) {
            if( endFlag == true || isStop() == true ) {
                break ;
            }
            try {
                if( execution() == false ) {
                    Thread.sleep( 30L ) ;
                }
            } catch( InterruptedException ite ) {
                toException( ite ) ;
                endFlag = true ;
            } catch ( NullPointerException ne ) {
                toException( ne ) ;
                try {
                    Thread.sleep( 1L ) ;
                }
                catch( InterruptedException ite2 ) {
                    endFlag = true ;
                }
            } catch( OutOfMemoryError mem ) {
                toException( mem ) ;
                try {
                    Thread.sleep( 1L ) ;
                }
                catch( InterruptedException ite2 ) {
                    endFlag = true ;
                }
            } catch( Exception e ) {
                toException( e ) ;
                try {
                    Thread.sleep( 1L ) ;
                }
                catch( InterruptedException ite2 ) {
                    endFlag = true ;
                }
            } catch( ThreadDeath td ) {
                toException( td ) ;
                endFlag = true ;
                threadDeach = td ;
            }
        }
        synchronized( this ) {
            clear() ;
        }
        setStop( true ) ;
        if( threadDeach != null ) {
            throw threadDeach ;
        }
    }
    
}
