|
What this is
Other links
The source code/* * WorkThreadPool.java - Background thread pool that does stuff * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 2000 Slava Pestov * * This program 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 * of the License, or any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.gjt.sp.util; //{{{ Imports import javax.swing.event.EventListenerList; import javax.swing.SwingUtilities; //}}} /** * A pool of work threads. * @author Slava Pestov * @version $Id: WorkThreadPool.java,v 1.8 2004/05/29 01:55:26 spestov Exp $ * @see org.gjt.sp.util.WorkThread * @since jEdit 2.6pre1 */ public class WorkThreadPool { //{{{ WorkThreadPool constructor /** * Creates a new work thread pool with the specified number of * work threads. * @param name The thread name prefix * @param count The number of work threads */ public WorkThreadPool(String name, int count) { listenerList = new EventListenerList(); if(count != 0) { threadGroup = new ThreadGroup(name); threads = new WorkThread[count]; for(int i = 0; i < threads.length; i++) { threads[i] = new WorkThread(this,threadGroup,name + " #" + (i+1)); } } else Log.log(Log.WARNING,this,"Async I/O disabled"); } //}}} //{{{ start() method /** * Starts all the threads in this thread pool. */ public void start() { /* not really needed since threads don't start until after */ synchronized(lock) { started = true; if(awtRequestCount != 0 && requestCount == 0) queueAWTRunner(); } if(threads != null) { for(int i = 0; i < threads.length; i++) { threads[i].start(); } } } //}}} //{{{ addWorkRequest() method /** * Adds a work request to the queue. * @param run The runnable * @param inAWT If true, will be executed in AWT thread. Otherwise, * will be executed in work thread */ public void addWorkRequest(Runnable run, boolean inAWT) { if(threads == null) { run.run(); return; } synchronized(lock) { //{{{ if there are no requests, execute AWT requests immediately if(started && inAWT && requestCount == 0 && awtRequestCount == 0) { // Log.log(Log.DEBUG,this,"AWT immediate: " + run); if(SwingUtilities.isEventDispatchThread()) run.run(); else SwingUtilities.invokeLater(run); return; } //}}} Request request = new Request(run); //{{{ Add to AWT queue... if(inAWT) { if(firstAWTRequest == null && lastAWTRequest == null) firstAWTRequest = lastAWTRequest = request; else { lastAWTRequest.next = request; lastAWTRequest = request; } awtRequestCount++; // if no requests are running, requestDone() // will not be called, so we must queue the // AWT runner ourselves. if(started && requestCount == 0) queueAWTRunner(); } //}}} //{{{ Add to work thread queue... else { if(firstRequest == null && lastRequest == null) firstRequest = lastRequest = request; else { lastRequest.next = request; lastRequest = request; } requestCount++; } //}}} lock.notifyAll(); } } //}}} //{{{ waitForRequests() method /** * Waits until all requests are complete. */ public void waitForRequests() { if(threads == null) return; synchronized(waitForAllLock) { while(requestCount != 0) { try { waitForAllLock.wait(); } catch(InterruptedException ie) { Log.log(Log.ERROR,this,ie); } } } if(SwingUtilities.isEventDispatchThread()) { // do any queued AWT runnables doAWTRequests(); } else { try { SwingUtilities.invokeAndWait(new RunRequestsInAWTThread()); } catch(Exception e) { Log.log(Log.ERROR,this,e); } } } //}}} //{{{ getRequestCount() method /** * Returns the number of pending requests. */ public int getRequestCount() { return requestCount; } //}}} //{{{ getThreadCount() method /** * Returns the number of threads in this pool. */ public int getThreadCount() { if(threads == null) return 0; else return threads.length; } //}}} //{{{ getThread() method /** * Returns the specified thread. * @param index The index of the thread */ public WorkThread getThread(int index) { return threads[index]; } //}}} //{{{ addProgressListener() method /** * Adds a progress listener to this thread pool. * @param listener The listener */ public void addProgressListener(WorkThreadProgressListener listener) { listenerList.add(WorkThreadProgressListener.class,listener); } //}}} //{{{ removeProgressListener() method /** * Removes a progress listener from this thread pool. * @param listener The listener */ public void removeProgressListener(WorkThreadProgressListener listener) { listenerList.remove(WorkThreadProgressListener.class,listener); } //}}} //{{{ Package-private members Object lock = new Object(); Object waitForAllLock = new Object(); //{{{ fireStatusChanged() method void fireStatusChanged(WorkThread thread) { final Object[] listeners = listenerList.getListenerList(); if(listeners.length != 0) { int index = 0; for(int i = 0; i < threads.length; i++) { if(threads[i] == thread) { index = i; break; } } for(int i = listeners.length - 2; i >= 0; i--) { if(listeners[i] == WorkThreadProgressListener.class) { ((WorkThreadProgressListener)listeners[i+1]) .statusUpdate(WorkThreadPool.this,index); } } } } //}}} //{{{ fireProgressChanged() method void fireProgressChanged(WorkThread thread) { final Object[] listeners = listenerList.getListenerList(); if(listeners.length != 0) { int index = 0; for(int i = 0; i < threads.length; i++) { if(threads[i] == thread) { index = i; break; } } for(int i = listeners.length - 2; i >= 0; i--) { if(listeners[i] == WorkThreadProgressListener.class) { ((WorkThreadProgressListener)listeners[i+1]) .progressUpdate(WorkThreadPool.this,index); } } } } //}}} //{{{ requestDone() method void requestDone() { synchronized(lock) { requestCount--; if(requestCount == 0 && firstAWTRequest != null) queueAWTRunner(); } } //}}} //{{{ getNextRequest() method Request getNextRequest() { synchronized(lock) { Request request = firstRequest; if(request == null) return null; firstRequest = firstRequest.next; if(firstRequest == null) lastRequest = null; if(request.alreadyRun) throw new InternalError("AIEE!!! Request run twice!!! " + request.run); request.alreadyRun = true; /* StringBuffer buf = new StringBuffer("request queue is now: "); Request _request = request.next; while(_request != null) { buf.append(_request.id); if(_request.next != null) buf.append(","); _request = _request.next; } Log.log(Log.DEBUG,this,buf.toString()); */ return request; } } //}}} //}}} //{{{ Private members //{{{ Instance variables private boolean started; private ThreadGroup threadGroup; private WorkThread[] threads; // Request queue private Request firstRequest; private Request lastRequest; private int requestCount; // AWT thread magic private boolean awtRunnerQueued; private Request firstAWTRequest; private Request lastAWTRequest; private int awtRequestCount; private EventListenerList listenerList; //}}} //{{{ doAWTRequests() method /** Must always be called with the lock held. */ private void doAWTRequests() { while(requestCount == 0 && firstAWTRequest != null) { doAWTRequest(getNextAWTRequest()); } } //}}} //{{{ doAWTRequest() method /** Must always be called with the lock held. */ private void doAWTRequest(Request request) { // Log.log(Log.DEBUG,this,"Running in AWT thread: " + request); try { request.run.run(); } catch(Throwable t) { Log.log(Log.ERROR,WorkThread.class,"Exception " + "in AWT thread:"); Log.log(Log.ERROR,WorkThread.class,t); } awtRequestCount--; } //}}} //{{{ queueAWTRunner() method /** Must always be called with the lock held. */ private void queueAWTRunner() { if(!awtRunnerQueued) { awtRunnerQueued = true; SwingUtilities.invokeLater(new RunRequestsInAWTThread()); // Log.log(Log.DEBUG,this,"AWT runner queued"); } } //}}} //{{{ getNextAWTRequest() method private Request getNextAWTRequest() { Request request = firstAWTRequest; firstAWTRequest = firstAWTRequest.next; if(firstAWTRequest == null) lastAWTRequest = null; if(request.alreadyRun) throw new InternalError("AIEE!!! Request run twice!!! " + request.run); request.alreadyRun = true; /* StringBuffer buf = new StringBuffer("AWT request queue is now: "); Request _request = request.next; while(_request != null) { buf.append(_request.id); if(_request.next != null) buf.append(","); _request = _request.next; } Log.log(Log.DEBUG,this,buf.toString()); */ return request; } //}}} //}}} static int ID; //{{{ Request class static class Request { int id = ++ID; Runnable run; boolean alreadyRun; Request next; Request(Runnable run) { this.run = run; } public String toString() { return "[id=" + id + ",run=" + run + "]"; } } //}}} //{{{ RunRequestsInAWTThread class class RunRequestsInAWTThread implements Runnable { public void run() { synchronized(lock) { awtRunnerQueued = false; if(requestCount == 0) doAWTRequests(); } } } //}}} } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.