/*
* ClientsPool.java
*
* Created on June 14, 2001, 2:53 PM
*/
package context.arch.comm.clients;
import context.arch.comm.CommunicationsObject;
import context.arch.util.SynchFIFO;
/**
* This class defines a pool of threads that can handle a communication.
* When a BaseObject wants to send an asynchronous message to another CTK object,
* it creates the RequestObject, added it to a IndependentCommunication object,
* which is the parameter of the BaseObject.independentUserRequest() call.
* This IndependentCommunication is added to a synchronized FIFO vector (SynchFIFO
* object) from which the ClientsPool get the request to send.
*
* Then, as soon as a IndependentCommunication is added to the SynchFIFO, the ClientsPool object
* removes it to give it to a thread (Client object) from the pool.
* When a Client object is asked to handle an IndependentCommunication, it is
* also removed from the pool.
* The Client object sends the request to the given CTK object, and get the
* reply and the exceptions.
*
* In order for the BaseObject to get the reply, the IndependentCommunication contains
* also 2 useful attributes : the DataObject reply and the Vector exceptions.
* Then the Client object adds the reply to the same object it gets as well as
* the exception it could have caught.
* After updating the IndependentCommunication object, the Client calls the
* BaseObject handleIndependentReply method with the parameter an object containing
* the same IndependentCommunication object.
*
* At the end of the communication, the IndependentCommunication object contains
* the original request, the reply (if any) and the exceptions that occured (if any);
* and is sent back to the BaseObject, that does nothing by default.
* If a widget or server or interpreter wants to handle the reply, it overrides the
* BaseObject handleIndependentReply method, and may check the reply for each
* request it has sent.
*
* In order to group a bunch of requests (for example, a widget sends many PINGs to
* its subscribers) we define a IndependentCommunications object to help handling
* the replies.
* Before sending the requests, the widget creates an IndependentCommunications
* object in which all IndependentCommunication objects will be added by the Client
* thread at the end of the communication.
* The IndependentCommunications object is specified while calling the
* BaseObject independentUserRequest. If it is null, the Client thread will create
* a new one, add the IndependentCommunication object in it, and send it to
* the BaseObject handleIndependentReply method.
*
* @author Agathe
* @see context.arch.comm.clients.Client
* @see context.arch.util.SynchFIFO
*/
public class ClientsPool extends Thread {
/** Debug flag*/
public static boolean DEBUG = false;
/**
* The synchronized vector of threads
*/
protected static SynchFIFO threads = new SynchFIFO();
/**
* The number of authorized clients
*/
public static int clientsNumber;
/**
* The default number of clients
*/
public static int DEFAULT_CLIENTS_NUMBER = 6;
/**
* The Communications object
*/
public CommunicationsObject comm;
/**
* This FIFO object contains the IndependentCommunication object that
* contain the RequestObject to send
*/
protected SynchFIFO fifo;
/**
* Creates a generic ClientsPool. It creates the pool of numberOfClients threads.
*
* @param numberOfClients The number of available clients in the pool
* @param baseObject The base object
*/
public ClientsPool (int numberOfClients, CommunicationsObject commObject) {
clientsNumber = Math.max (1,numberOfClients);
comm = commObject;
// if (DEBUG) commObject.println("ClientsPool constructor nb th=" + clientsNumber);
fifo = new SynchFIFO();
// start clients
for (int i = 0; i < clientsNumber; i++) {
Client c = new Client(comm, "client#" + i);
threads.put(c);
c.start ();
}
}
/**
* Creates a ClientsPool with the default number of threads in the pool of
* threads.
*
* @param baseObject The base object
*/
public ClientsPool (CommunicationsObject commObject){
this(ClientsPool.DEFAULT_CLIENTS_NUMBER, commObject);
}
/**
* Creates a new empty ClientsPool.
*/
public ClientsPool (){
fifo = null;
comm = null;
}
/**
* The run method called to start the thread.
* The ClientsPool waits for a new IndependentCommunication object in the
* fifo object.
* As soon as a new one is added, the ClientsPool waits for the next available
* Client to handle the request.
*
* @see context.arch.util.SynchFIFO
* @see context.arch.comm.clients.Client
*/
public void run(){
while (true){
// Get the next request or is blocked waiting for the next
IndependentCommunication request = (IndependentCommunication) fifo.getNext ();
// The client that will be in charge of the request
Client c = null;
c = (Client) threads.getNext();
// String clientId = c.id; // not being used
c.setRequest(request);
}
}
/**
* This method is called to add an IndependentCommunication object containing
* the RequestObject to send, to the fifo object.
*
* @param request The IndependentCommunication object containing the RequestObject
* @see context.arch.util.SynchFIFO
*/
public synchronized void addRequest(IndependentCommunication request) {
fifo.put (request);
}
/**
*
*/
public void stopAllIdleClients (){
Object [] obj = threads.removeAll ();
for (int i = 0 ; i < obj.length ; i++){
((Client) obj[i]).interrupt ();
}
}
/**
* to finish : add an array of the working Clients to interrupt them
*/
/*public void stopAllClients(){
stopAllIdleClients ();
// Give the threads a quick chance to die
try {
Thread.sleep(1000);
}
catch (InterruptedException ie){}
//Stop all remaining Clients
synchronized (this.threads){
for (
}
}*/
}//end