From: Marcelo V. <va...@us...> - 2006-04-08 23:18:12
|
Update of /cvsroot/jedit/plugins/CommonControls/common/threads In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9411/common/threads Modified Files: WorkerThreadPool.java WorkRequest.java Log Message: - add new "runRequests()" method to thread pool (for those who don't want to wait for an idle thread) - some fixes in WorkRequest to avoid deadlocks. Index: WorkerThreadPool.java =================================================================== RCS file: /cvsroot/jedit/plugins/CommonControls/common/threads/WorkerThreadPool.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- WorkerThreadPool.java 12 Dec 2005 04:26:01 -0000 1.1 +++ WorkerThreadPool.java 8 Apr 2006 23:18:03 -0000 1.2 @@ -95,19 +95,50 @@ public WorkRequest[] addRequests(Runnable[] reqs) { ensureCapacity(reqs.length); - List wreqs = new LinkedList(); - for (int i = 0; i < reqs.length; i++) - wreqs.add(new WorkRequest(reqs[i])); + WorkRequest[] wreqs = toWorkRequest(reqs); synchronized (lock) { - requests.addAll(wreqs); + for (int i = 0; i < wreqs.length; i++) + requests.add(wreqs[i]); lock.notifyAll(); } - return (WorkRequest[]) wreqs.toArray(new WorkRequest[wreqs.size()]); + return wreqs; } /** - * Ensures that at least <code>size</code> threads are avaiable to + * Immediately runs the given requests. If not enough worker threads + * are free to handle all the requests, new threads are created to + * be able to handle the new requests. + * + * @since CC 0.9.1 + */ + public WorkRequest[] runRequests(Runnable[] reqs) + { + WorkRequest[] wreqs = toWorkRequest(reqs); + ensureCapacity(wreqs.length); + synchronized (lock) { + int curr = 0; + for (Iterator i = threads.iterator(); + curr < wreqs.length && i.hasNext(); ) + { + WorkerThread wt = (WorkerThread) i.next(); + if (wt.isIdle()) { + wt.setWorkload(wreqs[curr++]); + } + } + for (int i = curr; i < wreqs.length; i++) { + WorkerThread t = new WorkerThread(); + t.setWorkload(wreqs[i]); + t.start(); + threads.add(t); + } + lock.notifyAll(); + } + return wreqs; + } + + /** + * Ensures that at least <code>size</code> threads are available to * handle requests. */ public void ensureCapacity(int size) { @@ -142,6 +173,13 @@ } } + private WorkRequest[] toWorkRequest(Runnable[] reqs) { + WorkRequest[] wreqs = new WorkRequest[reqs.length]; + for (int i = 0; i < wreqs.length; i++) + wreqs[i] = new WorkRequest(reqs[i]); + return wreqs; + } + private static int THREAD_ID = 0; private class WorkerThread extends Thread @@ -149,17 +187,27 @@ private boolean run = true; private int idleCount = 0; + private volatile WorkRequest work = null; public WorkerThread() { super(group, "CC::Worker #" + (++THREAD_ID)); setDaemon(true); } + /** not synchronized. call while holding "lock". */ + public void setWorkload(WorkRequest work) { + this.work = work; + } + + /** not synchronized. call while holding "lock". */ + public boolean isIdle() { + return (work == null); + } + public void run() { while (run) { - WorkRequest work = null; idleCount = 0; synchronized (lock) { @@ -185,6 +233,7 @@ { Log.log(Log.NOTICE, this, "Executing request: " + work.getRunnable()); work.run(); + work = null; } else if (idleCount >= 10) { Index: WorkRequest.java =================================================================== RCS file: /cvsroot/jedit/plugins/CommonControls/common/threads/WorkRequest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- WorkRequest.java 12 Dec 2005 04:26:01 -0000 1.1 +++ WorkRequest.java 8 Apr 2006 23:18:03 -0000 1.2 @@ -20,6 +20,8 @@ */ package common.threads; +import org.gjt.sp.util.Log; + /** * <p>A work request to the thread pool. Allow other threads to wait until * the "runnable" is finished.</p> @@ -30,7 +32,7 @@ public final class WorkRequest { - private boolean done; + private volatile boolean done; private Object lock; private Runnable work; @@ -48,9 +50,9 @@ return; synchronized (lock) { - if (done) - return; - lock.wait(); + while (!done) { + lock.wait(1000); + } } } @@ -63,7 +65,11 @@ protected void run() { - work.run(); + try { + work.run(); + } catch (Exception e) { + Log.log(Log.ERROR, this, e); + } synchronized (lock) { done = true; |