alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.editor.view.spi;

import javax.swing.text.View;

/**
 * This is a layout queue similar to the {@link javax.swing.text.LayoutQueue}
 * with certain improvements.
 *
 * 

* Unlike the swing implementation this one uses a circular buffer * so it does no shifting of the runnables in the vector. * *

* The queue will shrink its size to 1/4 automatically if its size * would be lower than 1/8 of currently allocated array. * *

* Any view implementation wishing to perform asynchronous layout * may use {@link #getDefaultQueue()} or create its own queue instance. * * @author Miloslav Metelka * @version 1.00 */ public class ViewLayoutQueue { private static ViewLayoutQueue defaultQueue; private static SynchronousQueue synchronousQueue; private Runnable[] taskArray; private int startIndex; private int endIndex; private Thread worker; /** * Construct a layout queue. */ public ViewLayoutQueue() { taskArray = new Runnable[2]; // must be exactly power of 2 } /** * Get the default layout queue. */ public static ViewLayoutQueue getDefaultQueue() { if (defaultQueue == null) { defaultQueue = new ViewLayoutQueue(); } return defaultQueue; } public static ViewLayoutQueue getSynchronousQueue() { if (synchronousQueue == null) { synchronousQueue = new SynchronousQueue(); } return synchronousQueue; } public synchronized Thread getWorkerThread() { ensureWorkerInited(); return worker; } private void ensureWorkerInited() { if (worker == null) { worker = new LayoutThread(); worker.start(); } } /** * Add a task to the queue. */ public synchronized void addTask(Runnable task) { if (task != null) { // Ensure that worker thread is started ensureWorkerInited(); if (startIndex == endIndex && taskArray[startIndex] != null) { // full // new task array size must be exactly power of 2 Runnable[] newTaskArray = new Runnable[(taskArray.length << 1)]; // Copy the tasks into new array in the right order int afterStartIndexLength = taskArray.length - startIndex; System.arraycopy(taskArray, endIndex, newTaskArray, 0, afterStartIndexLength); System.arraycopy(taskArray, 0, newTaskArray, afterStartIndexLength, startIndex); startIndex = 0; endIndex = taskArray.length; // number of items in original array taskArray = newTaskArray; } taskArray[endIndex] = task; endIndex = (endIndex + 1) & (taskArray.length - 1); notify(); } } /** * Used by the worker thread to get a new task to execute */ synchronized Runnable waitForTask() { while (startIndex == endIndex && taskArray[startIndex] == null) { // empty try { wait(); } catch (InterruptedException ie) { return null; } } Runnable task = taskArray[startIndex]; taskArray[startIndex] = null; int taskArrayLength = taskArray.length; startIndex = (startIndex + 1) & (taskArrayLength - 1); // Try to shrink to 1/4 if size < 1/8 of current size if (taskArrayLength >= 128) { // shrink to no less than 32 items (size / 4) int indexDiff = (endIndex - startIndex); if (indexDiff >= 0) { // endIndex >= startIndex if (indexDiff < (taskArrayLength / 8)) { Runnable[] smallerTaskArray = new Runnable[(taskArrayLength / 4)]; System.arraycopy(taskArray, startIndex, smallerTaskArray, 0, indexDiff); taskArray = smallerTaskArray; startIndex = 0; endIndex = indexDiff; } } else { // endIndex < startIndex indexDiff = taskArrayLength + indexDiff; // size without empty space if (indexDiff < (taskArrayLength / 8)) { Runnable[] smallerTaskArray = new Runnable[(taskArrayLength / 4)]; System.arraycopy(taskArray, startIndex, smallerTaskArray, 0, taskArrayLength - startIndex); System.arraycopy(taskArray, 0, smallerTaskArray, taskArrayLength - startIndex, endIndex); taskArray = smallerTaskArray; startIndex = 0; endIndex = indexDiff; } } } return task; } /** * low priority thread to perform layout work forever */ class LayoutThread extends Thread { LayoutThread() { super("Text-Layout"); // NOI18N setPriority(Thread.MIN_PRIORITY); } public void run() { Runnable task; do { task = waitForTask(); if (task != null) { task.run(); } } while (task != null); } } /** * Testing queue that executes the tasks synchronously * that should allow possible threading issues * to be discovered. */ private static class SynchronousQueue extends ViewLayoutQueue { public void addTask(Runnable r) { r.run(); } } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 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.