package gcb; import java.util.LinkedList; import java.util.Queue; public class ConnectWorkerPool { //this worker pool facilitates connecting to Garena rooms on startup //rather than connecting to each room sequentially, the worker pool // is used so that we can connect to multiple rooms at the same time Main main; Queue<ConnectJob> connectQueue; boolean exit = false; Integer numActiveWorkers; //number of workers that are connecting class ConnectJob { int type; //0 for main, 1 for room GarenaInterface garena; public ConnectJob(int type, GarenaInterface garena) { this.type = type; this.garena = garena; } } public ConnectWorkerPool(Main main) { this.main = main; connectQueue = new LinkedList<ConnectJob>(); numActiveWorkers = 0; for(int i = 0; i < GCBConfig.configuration.getInt("gcb_connectworkers", 8); i++) { new ConnectWorker().start(); } } //add a new connection job public void push(int type, GarenaInterface garena) { synchronized(connectQueue) { connectQueue.add(new ConnectJob(type, garena)); connectQueue.notify(); } } //wait until all jobs are finished //the caller should be in the same thread as caller of push to avoid synchronization issues public void waitFor() { synchronized(connectQueue) { while(!connectQueue.isEmpty() || numActiveWorkers > 0) { try { connectQueue.wait(100); //we won't be notified (less overhead), so need to set timeout } catch(InterruptedException e) {} } } } //close all worker threads public void close() { exit = true; synchronized(connectQueue) { connectQueue.notifyAll(); } } class ConnectWorker extends Thread { public void run() { while(!exit) { ConnectJob job = null; synchronized(connectQueue) { while(connectQueue.isEmpty()) { try { connectQueue.wait(); } catch(InterruptedException ie) {} } //we quit the thread if exit flag is set // (that would indicate we woke up through close notifyAll) if(exit || connectQueue.isEmpty()) { break; } else { job = connectQueue.poll(); synchronized(numActiveWorkers) { numActiveWorkers++; } } } //this should never happen if(job == null) { synchronized(numActiveWorkers) { numActiveWorkers--; } continue; } if(job.type == 0) { if(!main.initGarena(job.garena, false)) { //startup failed, so restart at a later time job.garena.disconnected(GarenaInterface.GARENA_MAIN, true); } } else { if(!main.initRoom(job.garena, false)) { job.garena.disconnected(GarenaInterface.GARENA_ROOM, true); } } synchronized(numActiveWorkers) { numActiveWorkers--; } } } } }