/* gnu.java.rmi.server.ConnectionRunnerPool
   Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.java.rmi.server;

import java.util.ArrayList;
import java.util.Arrays;

//Should I generalize this class?

class ConnectionRunnerPool
{

  public static
    class ConnectionRunner extends Thread{
      private UnicastConnection conn;
      private volatile boolean exiting = false;

      public ConnectionRunner(ThreadGroup group, String id){
        super(group, id);
      }

      public synchronized void run(){
        while(!exiting){
          if(conn == null)
            try{
              wait();
            }catch(InterruptedException e){
              continue;
            }
          else{
            conn.run();
            conn = null;
            synchronized(ConnectionRunnerPool.class){
              freelist.add(this);
              if(freelist.size() == 1)
                ConnectionRunnerPool.class.notifyAll();
            }
          }
        }
      }

      public synchronized void dispatch(UnicastConnection conn){
        this.conn = conn;
        notify();
      }

      void exit(){
        exiting = true;
        if(conn != null)
          try{
            join(500);
          }catch(InterruptedException e){}
        interrupt();
      }

    }

  // Should this value equal to number of CPU?
  private static int size = 5;
  private static int max_size = 10;

  // Package-private to avoid a trampoline.
  static ArrayList freelist;

  private static ThreadGroup group = new ThreadGroup("pool");

  static {
    ConnectionRunner[] pools = new ConnectionRunner[size];
    for(int i = 0; i < pools.length; i++){
      pools[i] = new ConnectionRunner(group, Integer.toString(i));
      pools[i].setContextClassLoader(Thread.currentThread().getContextClassLoader());
      pools[i].start();
    }
    freelist = new ArrayList(Arrays.asList(pools));
  }

  public static void setSize(int size_){
    size = size_;
  }

  public static void setMaxSize(int size){
    max_size = size;
  }

  private static synchronized ConnectionRunner getConnectionRunner()
  {
    if(freelist.size() == 0){
      if(size < max_size){
        ++size;
        ConnectionRunner a = new ConnectionRunner(group, Integer.toString(size));
        a.start();
        freelist.add(a);
      }else
        while(freelist.size() == 0)
          try{
            ConnectionRunnerPool.class.wait();
          }catch(InterruptedException e){}
    }

    // always let the first in pool most busy or other scheduling plan??
    ConnectionRunner a = (ConnectionRunner)freelist.get(0);
    freelist.remove(a);
    return a;
  }

  public static void dispatchConnection(UnicastConnection conn)
  {
    ConnectionRunner r = getConnectionRunner();
    r.dispatch(conn);
  }

  public static void exit()
  {
    Thread[] list = new Thread[group.activeCount()];
    group.enumerate(list);
    for(int i = 0; i < list.length; i++)
      ((ConnectionRunner)list[i]).exit();
  }

}
