135 final FetcherInfo info = FetcherInfo.getFetcherInfo();
136 synchronized(info.waitList) {
137 ImageFetchable src = null;
138 long end = System.currentTimeMillis() + TIMEOUT;
139 while (src == null) {
140 while (info.waitList.size() == 0) {
141 long now = System.currentTimeMillis();
142 if (now >= end) {
143 return null;
144 }
145 try {
146 info.numWaiting++;
147 info.waitList.wait(end - now);
148 } catch (InterruptedException e) {
149 // A normal occurrence as an AppContext is disposed
150 return null;
151 } finally {
152 info.numWaiting--;
153 }
154 }
155 src = (ImageFetchable) info.waitList.elementAt(0);
156 info.waitList.removeElement(src);
157 }
158 return src;
159 }
160 }
161
162 /**
163 * The main run() method of an ImageFetcher Thread. Calls fetchloop()
164 * to do the work, then removes itself from the array of ImageFetchers.
165 */
166 public void run() {
167 final FetcherInfo info = FetcherInfo.getFetcherInfo();
168 try {
169 fetchloop();
170 } catch (Exception e) {
171 e.printStackTrace();
172 } finally {
173 synchronized(info.waitList) {
174 Thread me = Thread.currentThread();
175 for (int i = 0; i < info.fetchers.length; i++) {
286 // ThreadGroup. Thus, we start with the current
287 // ThreadGroup, and go up the tree until
288 // threadGroup.getParent().getParent() == null.
289 threadGroup = Thread.currentThread().getThreadGroup();
290 ThreadGroup parent = threadGroup.getParent();
291 while ((parent != null)
292 && (parent.getParent() != null)) {
293 threadGroup = parent;
294 parent = threadGroup.getParent();
295 }
296 fetcherThreadGroup = threadGroup;
297 }
298 } catch (SecurityException e) {
299 // Not allowed access to parent ThreadGroup -- just use
300 // the AppContext's ThreadGroup
301 fetcherThreadGroup = appContext.getThreadGroup();
302 }
303 final ThreadGroup fetcherGroup = fetcherThreadGroup;
304
305 java.security.AccessController.doPrivileged(
306 new java.security.PrivilegedAction() {
307 public Object run() {
308 for (int i = 0; i < info.fetchers.length; i++) {
309 if (info.fetchers[i] == null) {
310 ImageFetcher f = new ImageFetcher(
311 fetcherGroup, i);
312 try {
313 f.start();
314 info.fetchers[i] = f;
315 info.numFetchers++;
316 break;
317 } catch (Error e) {
318 }
319 }
320 }
321 return null;
322 }
323 });
324 return;
325 }
326
327 }
328
329 /**
330 * The FetcherInfo class encapsulates the per-AppContext ImageFetcher
331 * information. This includes the array of ImageFetchers, as well as
332 * the queue of ImageFetchable objects.
333 */
334 class FetcherInfo {
335 static final int MAX_NUM_FETCHERS_PER_APPCONTEXT = 4;
336
337 Thread[] fetchers;
338 int numFetchers;
339 int numWaiting;
340 Vector waitList;
341
342 private FetcherInfo() {
343 fetchers = new Thread[MAX_NUM_FETCHERS_PER_APPCONTEXT];
344 numFetchers = 0;
345 numWaiting = 0;
346 waitList = new Vector();
347 }
348
349 /* The key to put()/get() the FetcherInfo into/from the AppContext. */
350 private static final Object FETCHER_INFO_KEY =
351 new StringBuffer("FetcherInfo");
352
353 static FetcherInfo getFetcherInfo() {
354 AppContext appContext = AppContext.getAppContext();
355 synchronized(appContext) {
356 FetcherInfo info = (FetcherInfo)appContext.get(FETCHER_INFO_KEY);
357 if (info == null) {
358 info = new FetcherInfo();
359 appContext.put(FETCHER_INFO_KEY, info);
360 }
361 return info;
362 }
363 }
364 }
|
135 final FetcherInfo info = FetcherInfo.getFetcherInfo();
136 synchronized(info.waitList) {
137 ImageFetchable src = null;
138 long end = System.currentTimeMillis() + TIMEOUT;
139 while (src == null) {
140 while (info.waitList.size() == 0) {
141 long now = System.currentTimeMillis();
142 if (now >= end) {
143 return null;
144 }
145 try {
146 info.numWaiting++;
147 info.waitList.wait(end - now);
148 } catch (InterruptedException e) {
149 // A normal occurrence as an AppContext is disposed
150 return null;
151 } finally {
152 info.numWaiting--;
153 }
154 }
155 src = info.waitList.elementAt(0);
156 info.waitList.removeElement(src);
157 }
158 return src;
159 }
160 }
161
162 /**
163 * The main run() method of an ImageFetcher Thread. Calls fetchloop()
164 * to do the work, then removes itself from the array of ImageFetchers.
165 */
166 public void run() {
167 final FetcherInfo info = FetcherInfo.getFetcherInfo();
168 try {
169 fetchloop();
170 } catch (Exception e) {
171 e.printStackTrace();
172 } finally {
173 synchronized(info.waitList) {
174 Thread me = Thread.currentThread();
175 for (int i = 0; i < info.fetchers.length; i++) {
286 // ThreadGroup. Thus, we start with the current
287 // ThreadGroup, and go up the tree until
288 // threadGroup.getParent().getParent() == null.
289 threadGroup = Thread.currentThread().getThreadGroup();
290 ThreadGroup parent = threadGroup.getParent();
291 while ((parent != null)
292 && (parent.getParent() != null)) {
293 threadGroup = parent;
294 parent = threadGroup.getParent();
295 }
296 fetcherThreadGroup = threadGroup;
297 }
298 } catch (SecurityException e) {
299 // Not allowed access to parent ThreadGroup -- just use
300 // the AppContext's ThreadGroup
301 fetcherThreadGroup = appContext.getThreadGroup();
302 }
303 final ThreadGroup fetcherGroup = fetcherThreadGroup;
304
305 java.security.AccessController.doPrivileged(
306 new java.security.PrivilegedAction<Object>() {
307 public Object run() {
308 for (int i = 0; i < info.fetchers.length; i++) {
309 if (info.fetchers[i] == null) {
310 ImageFetcher f = new ImageFetcher(fetcherGroup, i);
311 try {
312 f.start();
313 info.fetchers[i] = f;
314 info.numFetchers++;
315 break;
316 } catch (Error e) {
317 }
318 }
319 }
320 return null;
321 }
322 });
323 return;
324 }
325
326 }
327
328 /**
329 * The FetcherInfo class encapsulates the per-AppContext ImageFetcher
330 * information. This includes the array of ImageFetchers, as well as
331 * the queue of ImageFetchable objects.
332 */
333 class FetcherInfo {
334 static final int MAX_NUM_FETCHERS_PER_APPCONTEXT = 4;
335
336 Thread[] fetchers;
337 int numFetchers;
338 int numWaiting;
339 Vector<ImageFetchable> waitList;
340
341 private FetcherInfo() {
342 fetchers = new Thread[MAX_NUM_FETCHERS_PER_APPCONTEXT];
343 numFetchers = 0;
344 numWaiting = 0;
345 waitList = new Vector<>();
346 }
347
348 /* The key to put()/get() the FetcherInfo into/from the AppContext. */
349 private static final Object FETCHER_INFO_KEY =
350 new StringBuffer("FetcherInfo");
351
352 static FetcherInfo getFetcherInfo() {
353 AppContext appContext = AppContext.getAppContext();
354 synchronized(appContext) {
355 FetcherInfo info = (FetcherInfo)appContext.get(FETCHER_INFO_KEY);
356 if (info == null) {
357 info = new FetcherInfo();
358 appContext.put(FETCHER_INFO_KEY, info);
359 }
360 return info;
361 }
362 }
363 }
|