KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > editor > view > spi > ViewLayoutQueue


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.editor.view.spi;
21
22 import javax.swing.text.View JavaDoc;
23
24 /**
25  * This is a layout queue similar to the {@link javax.swing.text.LayoutQueue}
26  * with certain improvements.
27  *
28  * <p>
29  * Unlike the swing implementation this one uses a circular buffer
30  * so it does no shifting of the runnables in the vector.
31  *
32  * <p>
33  * The queue will shrink its size to 1/4 automatically if its size
34  * would be lower than 1/8 of currently allocated array.
35  *
36  * <p>
37  * Any view implementation wishing to perform asynchronous layout
38  * may use {@link #getDefaultQueue()} or create its own queue instance.
39  *
40  * @author Miloslav Metelka
41  * @version 1.00
42  */

43
44 public class ViewLayoutQueue {
45     
46     private static ViewLayoutQueue defaultQueue;
47     
48     private static SynchronousQueue synchronousQueue;
49
50     private Runnable JavaDoc[] taskArray;
51
52     private int startIndex;
53     
54     private int endIndex;
55     
56     private Thread JavaDoc worker;
57     
58     /**
59      * Construct a layout queue.
60      */

61     public ViewLayoutQueue() {
62     taskArray = new Runnable JavaDoc[2]; // must be exactly power of 2
63
}
64
65     /**
66      * Get the default layout queue.
67      */

68     public static ViewLayoutQueue getDefaultQueue() {
69     if (defaultQueue == null) {
70         defaultQueue = new ViewLayoutQueue();
71     }
72     return defaultQueue;
73     }
74
75     public static ViewLayoutQueue getSynchronousQueue() {
76     if (synchronousQueue == null) {
77         synchronousQueue = new SynchronousQueue();
78     }
79     return synchronousQueue;
80     }
81
82     public synchronized Thread JavaDoc getWorkerThread() {
83         ensureWorkerInited();
84
85         return worker;
86     }
87     
88     private void ensureWorkerInited() {
89         if (worker == null) {
90             worker = new LayoutThread();
91             worker.start();
92         }
93     }
94
95     /**
96      * Add a task to the queue.
97      */

98     public synchronized void addTask(Runnable JavaDoc task) {
99         if (task != null) {
100             
101             // Ensure that worker thread is started
102
ensureWorkerInited();
103
104             if (startIndex == endIndex && taskArray[startIndex] != null) { // full
105
// new task array size must be exactly power of 2
106
Runnable JavaDoc[] newTaskArray = new Runnable JavaDoc[(taskArray.length << 1)];
107                 
108                 // Copy the tasks into new array in the right order
109
int afterStartIndexLength = taskArray.length - startIndex;
110                 System.arraycopy(taskArray, endIndex, newTaskArray, 0,
111                     afterStartIndexLength);
112                 
113                 System.arraycopy(taskArray, 0, newTaskArray, afterStartIndexLength,
114                     startIndex);
115                 
116                 startIndex = 0;
117                 endIndex = taskArray.length; // number of items in original array
118
taskArray = newTaskArray;
119             }
120             
121             taskArray[endIndex] = task;
122             endIndex = (endIndex + 1) & (taskArray.length - 1);
123
124             notify();
125         }
126     }
127
128     /**
129      * Used by the worker thread to get a new task to execute
130      */

131     synchronized Runnable JavaDoc waitForTask() {
132     while (startIndex == endIndex && taskArray[startIndex] == null) { // empty
133
try {
134         wait();
135         } catch (InterruptedException JavaDoc ie) {
136         return null;
137         }
138     }
139
140         Runnable JavaDoc task = taskArray[startIndex];
141         taskArray[startIndex] = null;
142         int taskArrayLength = taskArray.length;
143         startIndex = (startIndex + 1) & (taskArrayLength - 1);
144         
145         // Try to shrink to 1/4 if size < 1/8 of current size
146
if (taskArrayLength >= 128) { // shrink to no less than 32 items (size / 4)
147
int indexDiff = (endIndex - startIndex);
148             if (indexDiff >= 0) { // endIndex >= startIndex
149
if (indexDiff < (taskArrayLength / 8)) {
150                     Runnable JavaDoc[] smallerTaskArray = new Runnable JavaDoc[(taskArrayLength / 4)];
151                     System.arraycopy(taskArray, startIndex, smallerTaskArray, 0, indexDiff);
152                     taskArray = smallerTaskArray;
153                     startIndex = 0;
154                     endIndex = indexDiff;
155                 }
156                 
157             } else { // endIndex < startIndex
158
indexDiff = taskArrayLength + indexDiff; // size without empty space
159
if (indexDiff < (taskArrayLength / 8)) {
160                     Runnable JavaDoc[] smallerTaskArray = new Runnable JavaDoc[(taskArrayLength / 4)];
161                     System.arraycopy(taskArray, startIndex, smallerTaskArray, 0,
162                         taskArrayLength - startIndex);
163                     System.arraycopy(taskArray, 0, smallerTaskArray,
164                         taskArrayLength - startIndex, endIndex);
165                     taskArray = smallerTaskArray;
166                     startIndex = 0;
167                     endIndex = indexDiff;
168                 }
169             }
170         }
171                     
172     return task;
173     }
174
175     /**
176      * low priority thread to perform layout work forever
177      */

178     class LayoutThread extends Thread JavaDoc {
179     
180     LayoutThread() {
181         super("Text-Layout"); // NOI18N
182
setPriority(Thread.MIN_PRIORITY);
183     }
184     
185         public void run() {
186         Runnable JavaDoc task;
187         do {
188         task = waitForTask();
189         if (task != null) {
190             task.run();
191         }
192         } while (task != null);
193     }
194
195
196     }
197
198     /**
199      * Testing queue that executes the tasks synchronously
200      * that should allow possible threading issues
201      * to be discovered.
202      */

203     private static class SynchronousQueue extends ViewLayoutQueue {
204         
205         public void addTask(Runnable JavaDoc r) {
206             r.run();
207         }
208         
209     }
210
211 }
212
Popular Tags