001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.lib;
032:
033: /**
034: * Provides very simple queued execution of Runnable objects in a background
035: * thread. The underlying queue is an HsqlDeque instance, an array-based
036: * circular queue implementation with automatic capacity expansion.
037: *
038: * @author boucherb@users
039: * @version 1.7.2
040: * @since 1.7.2
041: */
042: public class HsqlTaskQueue {
043:
044: /** The thread used to process commands */
045: protected Thread taskRunnerThread;
046:
047: /** Special queue element to signal termination */
048: protected static final Runnable SHUTDOWNTASK = new Runnable() {
049: public void run() {
050: }
051: };
052:
053: /**
054: * true if thread should shut down after processing current task.
055: *
056: * Once set true, stays true forever
057: */
058: protected volatile boolean isShutdown;
059:
060: public synchronized Thread getTaskRunnerThread() {
061: return taskRunnerThread;
062: }
063:
064: protected synchronized void clearThread() {
065: taskRunnerThread = null;
066: }
067:
068: protected final HsqlDeque queue = new HsqlDeque();
069:
070: protected class TaskRunner implements Runnable {
071:
072: public void run() {
073:
074: Runnable task;
075:
076: try {
077: while (!isShutdown) {
078: synchronized (queue) {
079: task = (Runnable) queue.getFirst();
080: }
081:
082: if (task == SHUTDOWNTASK) {
083: isShutdown = true;
084:
085: synchronized (queue) {
086: queue.clear();
087: }
088:
089: break;
090: } else if (task != null) {
091: task.run();
092:
093: task = null;
094: } else {
095: break;
096: }
097: }
098: } finally {
099: clearThread();
100: }
101: }
102: }
103:
104: protected final TaskRunner taskRunner = new TaskRunner();
105:
106: public HsqlTaskQueue() {
107: }
108:
109: public boolean isShutdown() {
110: return isShutdown;
111: }
112:
113: public synchronized void restart() {
114:
115: if (taskRunnerThread == null && !isShutdown) {
116: taskRunnerThread = new Thread(taskRunner);
117:
118: taskRunnerThread.start();
119: }
120: }
121:
122: public void execute(Runnable command) throws RuntimeException {
123:
124: if (!isShutdown) {
125: synchronized (queue) {
126: queue.addLast(command);
127: }
128:
129: restart();
130: }
131: }
132:
133: public synchronized void shutdownAfterQueued() {
134:
135: if (!isShutdown) {
136: synchronized (queue) {
137: queue.addLast(SHUTDOWNTASK);
138: }
139: }
140: }
141:
142: public synchronized void shutdownAfterCurrent() {
143:
144: isShutdown = true;
145:
146: synchronized (queue) {
147: queue.clear();
148: queue.addLast(SHUTDOWNTASK);
149: }
150: }
151:
152: public synchronized void shutdownImmediately() {
153:
154: isShutdown = true;
155:
156: if (taskRunnerThread != null) {
157: taskRunnerThread.interrupt();
158: }
159:
160: synchronized (queue) {
161: queue.clear();
162: queue.addLast(SHUTDOWNTASK);
163: }
164: }
165: }
|