001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Oleg V. Khaschansky
019: * @version $Revision$
020: */package org.apache.harmony.awt.gl.image;
021:
022: import java.security.AccessController;
023: import java.security.PrivilegedAction;
024: import java.util.ArrayList;
025: import java.util.LinkedList;
026: import java.util.List;
027:
028: /**
029: * This class provides functionality for simultaneous loading of
030: * several images and running animation.
031: */
032: public class ImageLoader extends Thread {
033: // Contains ImageLoader objects
034: // and queue of image sources waiting to be loaded
035: static class ImageLoadersStorage {
036: private static final int MAX_THREADS = 5;
037: private static final int TIMEOUT = 4000;
038: static ImageLoadersStorage instance;
039:
040: List<DecodingImageSource> queue = new LinkedList<DecodingImageSource>();
041: List<Thread> loaders = new ArrayList<Thread>(MAX_THREADS);
042:
043: private int freeLoaders;
044:
045: private ImageLoadersStorage() {
046: }
047:
048: static ImageLoadersStorage getStorage() {
049: if (instance == null) {
050: instance = new ImageLoadersStorage();
051: }
052:
053: return instance;
054: }
055: }
056:
057: ImageLoader() {
058: super ();
059: setDaemon(true);
060: }
061:
062: /**
063: * This method creates a new thread which is able to load an image
064: * or run animation (if the number of existing loader threads does not
065: * exceed the limit).
066: */
067: private static void createLoader() {
068: final ImageLoadersStorage storage = ImageLoadersStorage
069: .getStorage();
070:
071: synchronized (storage.loaders) {
072: if (storage.loaders.size() < ImageLoadersStorage.MAX_THREADS) {
073: AccessController
074: .doPrivileged(new PrivilegedAction<Void>() {
075: public Void run() {
076: ImageLoader loader = new ImageLoader();
077: storage.loaders.add(loader);
078: loader.start();
079: return null;
080: }
081: });
082: }
083: }
084: }
085:
086: /**
087: * Adds a new image source to the queue and starts a new loader
088: * thread if required
089: * @param imgSrc - image source
090: */
091: public static void addImageSource(DecodingImageSource imgSrc) {
092: ImageLoadersStorage storage = ImageLoadersStorage.getStorage();
093: synchronized (storage.queue) {
094: if (!storage.queue.contains(imgSrc)) {
095: storage.queue.add(imgSrc);
096: }
097: if (storage.freeLoaders == 0) {
098: createLoader();
099: }
100:
101: storage.queue.notify();
102: }
103: }
104:
105: /**
106: * Waits for a new ImageSource until timout expires.
107: * Loader thread will terminate after returning from this method
108: * if timeout expired and image source was not picked up from the queue.
109: * @return image source picked up from the queue or null if timeout expired
110: */
111: private static DecodingImageSource getWaitingImageSource() {
112: ImageLoadersStorage storage = ImageLoadersStorage.getStorage();
113:
114: synchronized (storage.queue) {
115: DecodingImageSource isrc = null;
116:
117: if (storage.queue.size() == 0) {
118: try {
119: storage.freeLoaders++;
120: storage.queue.wait(ImageLoadersStorage.TIMEOUT);
121: } catch (InterruptedException e) {
122: return null;
123: } finally {
124: storage.freeLoaders--;
125: }
126: }
127:
128: if (storage.queue.size() > 0) {
129: isrc = storage.queue.get(0);
130: storage.queue.remove(0);
131: }
132:
133: return isrc;
134: }
135: }
136:
137: /**
138: * Entry point of the loader thread. Picks up image sources and
139: * runs decoders for them while there are available image sources in the queue.
140: * If there are no and timeout expires it terminates.
141: */
142: @Override
143: public void run() {
144: ImageLoadersStorage storage = ImageLoadersStorage.getStorage();
145:
146: try {
147: while (storage.loaders.contains(this )) {
148: DecodingImageSource isrc = getWaitingImageSource();
149: if (isrc != null) {
150: try {
151: isrc.load();
152: } catch (Exception e) {
153: e.printStackTrace();
154: }
155: } else {
156: break; // Don't wait if timeout expired - terminate loader
157: }
158: }
159: } catch (Exception e) {
160: e.printStackTrace();
161: } finally {
162: synchronized (storage.loaders) {
163: storage.loaders.remove(Thread.currentThread());
164: }
165: }
166: }
167:
168: /**
169: * Removes current thread from loaders (so we are able
170: * to create more loaders) and decreases its priority.
171: */
172: static void beginAnimation() {
173: ImageLoadersStorage storage = ImageLoadersStorage.getStorage();
174: Thread currThread = Thread.currentThread();
175:
176: synchronized (storage) {
177: storage.loaders.remove(currThread);
178:
179: if (storage.freeLoaders < storage.queue.size()) {
180: createLoader();
181: }
182: }
183:
184: currThread.setPriority(Thread.MIN_PRIORITY);
185: }
186:
187: /**
188: * Sends the current thread to wait for the new images to load
189: * if there are free placeholders for loaders
190: */
191: static void endAnimation() {
192: ImageLoadersStorage storage = ImageLoadersStorage.getStorage();
193: Thread currThread = Thread.currentThread();
194:
195: synchronized (storage) {
196: if (storage.loaders.size() < ImageLoadersStorage.MAX_THREADS
197: && !storage.loaders.contains(currThread)) {
198: storage.loaders.add(currThread);
199: }
200: }
201:
202: currThread.setPriority(Thread.NORM_PRIORITY);
203: }
204: }
|