/*
 * Copyright (C) 2005 NTT DATA Corporation
 * 
 * 
 */
package org.postgresforest.vm;

import org.postgresforest.Driver;


/**
 * クエリー実行スレッドの基底クラス。
 * スレッドpoolを実現するための機能を実装
 * @since 1.1
 */
public abstract class AbstractForestThread extends Thread 
{

	/** スレッド処理完了フラグ  */
	protected boolean m_isExecuted;

	/** スレッド実行終了フラグ  */
	protected boolean m_runnning;

	/** スレッド実行終了フラグ  */
	protected Lock m_executeSync;


	/**
	 * 
	 */
	public AbstractForestThread(LogUtil logUtil) {

		m_isExecuted = false;

		m_logUtil = logUtil;//Ver2.1

		m_executeSync = new Lock(1);//Ver2.1

		//waitExecute();

		// Ver3.1  DBCP 使用時にAPサーバが終了しない場合があるので、スレッドをdaemon化
		setDaemon(true);

		start();
		
		
	}


	/**
	 * スレッド処理完了待ち
	 * 
	 * 処理が完了するまでwaitする
	 */
	protected void waitExecute() {
		//スレッドの完了待ち
		while(isExecuted() == false){
			try {
				//Ver2.1
				//wait(5);
				m_executeSync.waitEnd();
			} catch (InterruptedException e) {
				//e.printStackTrace();
			}
		}
	}


	/**
	 * 処理開始指示
	 */
	public void execute()
	{
		waitExecute();
		synchronized(this){
			m_isExecuted = false;
			m_executeSync.reset(1);//Ver2.1
			notify();
		}
	}



	/**
	 * スレッド処理
	 * 起動されると待機状態となり、
	 * executeメソッドにより処理を実行する。
	 * 実行される処理は_execute()に記述される。
	 * 待機状態の前に実行される処理は_standby()に記述される。
	 * terminateスレッドにより終了する。
	 */
	public void run()
	{

		m_runnning = true;

		while(m_runnning){
			try{
				if (Driver.logDebug)
					m_logUtil.debug(getName() +": Waiting for processing...1");

				//処理要求待ち				
				synchronized(this){
					//Ver2.1
					//m_isExecuted = true;
					standby();

					if (Driver.logDebug)
						m_logUtil.debug(getName() +": Waiting for processing...2");
					wait();
				}
			
				//処理実行
				_execute();
			
			}catch(InterruptedException e){
	
			}
		}
	}


	/**
	 * スレッド待機前処理
	 * スレッド待機状態に入る前に呼び出される処理を実装する。
	 * 
	 */
	protected void standby(){
		m_isExecuted = true;
		m_executeSync.notifyEnd();//Ver2.1
	}

	/**
	 * スレッド処理
	 * スレッドから呼び出されるメイン処理を実装する。
	 * 
	 */
	abstract protected void _execute();
	
	/**
	 * スレッドの処理完了ステータス
	 * @return
	 */
	synchronized public boolean isExecuted() {
		return m_isExecuted;
	}

	/**
	 * スレッド終了指示
	 */
	synchronized public void terminate(){
	
		m_runnning = false;

		interrupt();
		try {
			join();
		} catch (InterruptedException e) {}

	}


	/** ログ出力 @since 2.1 */
	protected LogUtil m_logUtil;



}
