package org.maachang.comet.httpd.engine.comet ;


/**
 * コメットプーリング管理.
 *
 * @version 2007/08/24
 * @author  masahito suzuki
 * @since   MaachangComet 1.00
 */
class ExecutionPoolComet {
    
    /**
     * 最大プーリング数.
     */
    private static final int MAX_POOL = 100 ;
    
    /**
     * 最小プーリング数.
     */
    private static final int MIN_POOL = 5 ;
    
    /**
     * デフォルトプーリング数.
     */
    private static final int DEFAULT_POOL = 10 ;
    
    /**
     * スレッドプーリング.
     */
    private ExecutionOnePoolComet[] pool = null ;
    
    /**
     * 次回有効項番.
     */
    private int nextNo = -1 ;
    
    /**
     * 同期オブジェクト.
     */
    private final Object sync = new Object() ;
    
    /**
     * コンストラクタ.
     */
    public ExecutionPoolComet() {
        this( DEFAULT_POOL ) ;
    }
    
    /**
     * コンストラクタ.
     * <BR><BR>
     * 条件を設定してオブジェクトを生成します.
     * <BR>
     * @param pool 対象のプーリング数を設定します.
     */
    public ExecutionPoolComet( int pool ) {
        if( pool <= MIN_POOL ) {
            pool = MIN_POOL ;
        }
        else if( pool >= MAX_POOL ) {
            pool = MAX_POOL ;
        }
        this.pool = new ExecutionOnePoolComet[ pool ] ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        this.clear() ;
    }
    
    /**
     * 情報クリア.
     * <BR><BR>
     * 情報をクリアします.
     */
    public synchronized void clear() {
        pool = null ;
    }
    
    /**
     * 処理対象のコメットオブジェクトを追加.
     * <BR><BR>
     * 処理対象のコメットオブジェクトを追加します.
     * <BR>
     * @param comet 対象のコメット情報を設定します.
     * @param args コメット実行処理に渡したい、パラメータを設定します.
     * @param groupId 対象のグループIDを設定します.
     */
    public void executionComet( Comet comet,Object args,String groupId ) {
        if( pool == null ) {
            if( comet != null ) {
                comet.clear() ;
            }
            return ;
        }
        for(;;) {
            synchronized( sync ) {
                nextNo ++ ;
                if( pool.length <= nextNo ) {
                    nextNo = 0 ;
                }
                if( pool[ nextNo ] == null ) {
                    pool[ nextNo ] = new ExecutionOnePoolComet() ;
                }
                else if( pool[ nextNo ].isStopThread() == true ) {
                    pool[ nextNo ] = new ExecutionOnePoolComet() ;
                }
                
                if( pool[ nextNo ].executionComet( comet,args,groupId ) == false ) {
                    waitTime() ;
                }
                else {
                    break ;
                }
            }
        }
    }
    
    /**
     * オブジェクトが有効であるかチェック.
     * <BR><BR>
     * オブジェクトが有効であるかチェックします.
     * <BR>
     * @return boolean [true]の場合は有効です.
     */
    public synchronized boolean isUse() {
        return ( pool == null ) ? true : false ;
    }
    
    /**
     * プーリング数を取得.
     * <BR><BR>
     * プーリングサイズを取得します.
     * <BR>
     * @return int プーリングサイズが返されます.
     */
    public synchronized int size() {
        return ( pool == null ) ? -1 : pool.length ;
    }
    
    private void waitTime() {
        try {
            Thread.sleep( 30L ) ;
        } catch( Exception e ) {
        }
    }
}

