001: /*
002: * IdleThread.java
003: *
004: * Copyright (C) 1998-2003 Peter Graves
005: * $Id: IdleThread.java,v 1.4 2003/06/19 17:38:25 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.util.Vector;
025: import javax.swing.SwingUtilities;
026:
027: public class IdleThread extends Thread {
028: private Vector tasks = new Vector();
029:
030: private static IdleThread idleThread;
031:
032: private IdleThread() {
033: super ("idle");
034: }
035:
036: public static synchronized IdleThread getInstance() {
037: if (idleThread == null)
038: startIdleThread();
039: return idleThread;
040: }
041:
042: public static synchronized void startIdleThread() {
043: if (idleThread == null) {
044: idleThread = new IdleThread();
045: idleThread.init();
046: idleThread.setPriority(Thread.MIN_PRIORITY);
047: idleThread.setDaemon(true);
048: idleThread.start();
049: }
050: }
051:
052: public static synchronized void runFollowContextTask(
053: IdleThreadTask task) {
054: if (followContextTask == null) {
055: followContextTask = task;
056: followContextTask.run();
057: if (idleThread != null)
058: idleThread.addTask(followContextTask);
059: }
060: }
061:
062: public static synchronized void killFollowContextTask() {
063: if (followContextTask != null) {
064: if (idleThread != null)
065: idleThread.removeTask(followContextTask);
066: followContextTask = null;
067: }
068: }
069:
070: private synchronized void init() {
071: addTask(parseBuffersTask);
072: addTask(updateHorizontalScrollBarsTask);
073: addTask(updateSidebarTask);
074: addTask(gcTask);
075: addTask(autosaveTask);
076: addTask(saveStateTask);
077: addTask(tagCurrentDirectoryTask);
078: if (Editor.isDebugEnabled())
079: addListThreadsTask();
080: }
081:
082: private synchronized IdleThreadTask getTask(int index) {
083: if (index < 0 || index >= tasks.size())
084: return null;
085: return (IdleThreadTask) tasks.get(index);
086: }
087:
088: private synchronized void addTask(IdleThreadTask task) {
089: tasks.add(task);
090: }
091:
092: public synchronized void maybeAddTask(IdleThreadTask task) {
093: for (int i = tasks.size(); i-- > 0;) {
094: if (tasks.get(i) == task)
095: return; // Already added.
096: }
097: tasks.add(task);
098: }
099:
100: private synchronized void removeTask(IdleThreadTask task) {
101: tasks.remove(task);
102: }
103:
104: public void run() {
105: while (true) {
106: try {
107: Thread.sleep(500);
108: } catch (InterruptedException e) {
109: }
110: final long lastEventMillis = Dispatcher
111: .getLastEventMillis();
112: final long idle = System.currentTimeMillis()
113: - lastEventMillis;
114: if (idle > 500) {
115: int i = 0;
116: IdleThreadTask task;
117: while ((task = getTask(i++)) != null) {
118: if (task.getIdle() == 0)
119: ;
120: else if (idle > task.getIdle())
121: task.run();
122: if (Dispatcher.getLastEventMillis() != lastEventMillis)
123: break; // User has done something.
124: }
125: }
126: }
127: }
128:
129: private Runnable updateSidebarRunnable = new Runnable() {
130: public void run() {
131: Sidebar.refreshSidebarInAllFrames();
132: }
133: };
134:
135: private IdleThreadTask updateSidebarTask = new IdleThreadTask(
136: updateSidebarRunnable, 500, true);
137:
138: private Runnable parseBuffersRunnable = new Runnable() {
139: public void run() {
140: synchronized (Editor.getBufferList()) {
141: for (BufferIterator iter = new BufferIterator(); iter
142: .hasNext();) {
143: Buffer buf = iter.nextBuffer();
144: if (!buf.needsParsing())
145: continue;
146: boolean changed = false;
147: try {
148: buf.lockRead();
149: } catch (InterruptedException e) {
150: Log.error(e);
151: return;
152: }
153: try {
154: changed = buf.getFormatter().parseBuffer();
155: } finally {
156: buf.unlockRead();
157: }
158: if (changed)
159: buf.repaint();
160: }
161: }
162: }
163: };
164:
165: private IdleThreadTask parseBuffersTask = new IdleThreadTask(
166: parseBuffersRunnable, 500, false);
167:
168: private Runnable updateHorizontalScrollBarsRunnable = new Runnable() {
169: public void run() {
170: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
171: Editor ed = it.nextEditor();
172: Buffer buf = ed.getBuffer();
173: if (buf != null) {
174: if (buf.validateMaximumColumns())
175: ed.updateHorizontalScrollBar();
176: }
177: }
178: }
179: };
180:
181: private IdleThreadTask updateHorizontalScrollBarsTask = new IdleThreadTask(
182: updateHorizontalScrollBarsRunnable, 500, true);
183:
184: private Runnable autosaveRunnable = new Runnable() {
185: public void run() {
186: Editor editor = Editor.currentEditor();
187: if (editor == null)
188: return;
189: Buffer buffer = editor.getBuffer();
190: if (buffer != null)
191: buffer.autosave();
192: }
193: };
194:
195: private IdleThreadTask autosaveTask = new IdleThreadTask(
196: autosaveRunnable, 2000, false);
197:
198: private Runnable saveStateRunnable = new Runnable() {
199: private long lastRun = 0;
200:
201: public void run() {
202: Debug.assertTrue(SwingUtilities.isEventDispatchThread());
203: if (Dispatcher.getLastEventMillis() > lastRun) {
204: Editor editor = Editor.currentEditor();
205: if (editor != null)
206: editor.saveState();
207: RecentFiles.getInstance().save();
208: lastRun = System.currentTimeMillis();
209: }
210: }
211: };
212:
213: private IdleThreadTask saveStateTask = new IdleThreadTask(
214: saveStateRunnable, 5000, true);
215:
216: private IdleThreadTask gcTask = new GarbageCollectionTask();
217:
218: private IdleThreadTask tagCurrentDirectoryTask = new TagCurrentDirectoryTask();
219:
220: private static IdleThreadTask followContextTask;
221:
222: private void addListThreadsTask() {
223: Runnable listThreadsRunnable = new Runnable() {
224: private long lastRun = 0;
225:
226: public void run() {
227: int minutes = Editor.preferences().getIntegerProperty(
228: Property.LIST_THREADS);
229: if (minutes > 0) {
230: long millis = minutes * 60000;
231: if (System.currentTimeMillis() - lastRun > millis) {
232: Debug.listThreads();
233: lastRun = System.currentTimeMillis();
234: }
235: }
236: }
237: };
238: addTask(new IdleThreadTask(listThreadsRunnable, 10000, true));
239: }
240: }
|