jdk/src/share/classes/sun/awt/image/ImageFetcher.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 1995-2003 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.awt.image;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.util.Vector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import sun.awt.AppContext;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
  * An ImageFetcher is a thread used to fetch ImageFetchable objects.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
  * Once an ImageFetchable object has been fetched, the ImageFetcher
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
  * thread may also be used to animate it if necessary, via the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
  * startingAnimation() / stoppingAnimation() methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
  *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
  * There can be up to FetcherInfo.MAX_NUM_FETCHERS_PER_APPCONTEXT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
  * ImageFetcher threads for each AppContext.  A per-AppContext queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
  * of ImageFetchables is used to track objects to fetch.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
  *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
  * @author Jim Graham
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
  * @author Fred Ecks
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
  */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
class ImageFetcher extends Thread {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    static final int HIGH_PRIORITY = 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    static final int LOW_PRIORITY = 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
    static final int ANIM_PRIORITY = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
    static final int TIMEOUT = 5000; // Time in milliseconds to wait for an
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
                                     // ImageFetchable to be added to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
                                     // queue before an ImageFetcher dies
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
      * Constructor for ImageFetcher -- only called by add() below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
    private ImageFetcher(ThreadGroup threadGroup, int index) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
        super(threadGroup, "Image Fetcher " + index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
        setDaemon(true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
      * Adds an ImageFetchable to the queue of items to fetch.  Instantiates
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
      * a new ImageFetcher if it's reasonable to do so.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    public static void add(ImageFetchable src) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
        synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
            if (!info.waitList.contains(src)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
                info.waitList.addElement(src);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
                if (info.numWaiting == 0 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
                            info.numFetchers < info.fetchers.length) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
                    createFetchers(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
                info.waitList.notify();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
      * Removes an ImageFetchable from the queue of items to fetch.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    public static void remove(ImageFetchable src) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
            if (info.waitList.contains(src)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
                info.waitList.removeElement(src);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
      * Checks to see if the given thread is one of the ImageFetchers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    public static boolean isFetcher(Thread t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
            for (int i = 0; i < info.fetchers.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
                if (info.fetchers[i] == t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
      * Checks to see if the current thread is one of the ImageFetchers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    public static boolean amFetcher() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        return isFetcher(Thread.currentThread());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
      * Returns the next ImageFetchable to be processed.  If TIMEOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
      * elapses in the mean time, or if the ImageFetcher is interrupted,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
      * null is returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    private static ImageFetchable nextImage() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
            ImageFetchable src = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
            long end = System.currentTimeMillis() + TIMEOUT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
            while (src == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
                while (info.waitList.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
                    long now = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
                    if (now >= end) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
                    try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
                        info.numWaiting++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
                        info.waitList.wait(end - now);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                    } catch (InterruptedException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
                        // A normal occurrence as an AppContext is disposed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
                    } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                        info.numWaiting--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                src = (ImageFetchable) info.waitList.elementAt(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
                info.waitList.removeElement(src);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            return src;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
      * The main run() method of an ImageFetcher Thread.  Calls fetchloop()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
      * to do the work, then removes itself from the array of ImageFetchers.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    public void run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            fetchloop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            e.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                Thread me = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
                for (int i = 0; i < info.fetchers.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                    if (info.fetchers[i] == me) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
                        info.fetchers[i] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                        info.numFetchers--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
      * The main ImageFetcher loop.  Repeatedly calls nextImage(), and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
      * fetches the returned ImageFetchable objects until nextImage()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
      * returns null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    private void fetchloop() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        Thread me = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        while (isFetcher(me)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
            // we're ignoring the return value and just clearing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            // the interrupted flag, instead of bailing out if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
            // the fetcher was interrupted, as we used to,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            // because there may be other images waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
            // to be fetched (see 4789067)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
            me.interrupted();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
            me.setPriority(HIGH_PRIORITY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
            ImageFetchable src = nextImage();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
            if (src == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                src.doFetch();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                System.err.println("Uncaught error fetching image:");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                e.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            stoppingAnimation(me);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
      * Recycles this ImageFetcher thread as an image animator thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
      * Removes this ImageFetcher from the array of ImageFetchers, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
      * resets the thread name to "ImageAnimator".
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    static void startingAnimation() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        Thread me = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
            for (int i = 0; i < info.fetchers.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                if (info.fetchers[i] == me) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                    info.fetchers[i] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                    info.numFetchers--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                    me.setName("Image Animator " + i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                    if(info.waitList.size() > info.numWaiting) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                       createFetchers(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        me.setPriority(ANIM_PRIORITY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        me.setName("Image Animator");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
      * Returns this image animator thread back to service as an ImageFetcher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
      * if possible.  Puts it back into the array of ImageFetchers and sets
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
      * the thread name back to "Image Fetcher".  If there are already the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
      * maximum number of ImageFetchers, this method simply returns, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
      * fetchloop() will drop out when it sees that this thread isn't one of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
      * the ImageFetchers, and this thread will die.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
    private static void stoppingAnimation(Thread me) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        final FetcherInfo info = FetcherInfo.getFetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
        synchronized(info.waitList) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
            int index = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
            for (int i = 0; i < info.fetchers.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                if (info.fetchers[i] == me) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                if (info.fetchers[i] == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                    index = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
            if (index >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                info.fetchers[index] = me;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                info.numFetchers++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                me.setName("Image Fetcher " + index);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
      * Create and start ImageFetcher threads in the appropriate ThreadGroup.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
      */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    private static void createFetchers(final FetcherInfo info) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
       // We need to instantiate a new ImageFetcher thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
       // First, figure out which ThreadGroup we'll put the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
       // new ImageFetcher into
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
       final AppContext appContext = AppContext.getAppContext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
       ThreadGroup threadGroup = appContext.getThreadGroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
       ThreadGroup fetcherThreadGroup;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
       try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
          if (threadGroup.getParent() != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
             // threadGroup is not the root, so we proceed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
             fetcherThreadGroup = threadGroup;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
          } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
             // threadGroup is the root ("system") ThreadGroup.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
             // We instead want to use its child: the "main"
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
             // ThreadGroup.  Thus, we start with the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
             // ThreadGroup, and go up the tree until
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
             // threadGroup.getParent().getParent() == null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
             threadGroup = Thread.currentThread().getThreadGroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
             ThreadGroup parent = threadGroup.getParent();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
             while ((parent != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                  && (parent.getParent() != null)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
                  threadGroup = parent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
                  parent = threadGroup.getParent();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
             }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
             fetcherThreadGroup = threadGroup;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
       } catch (SecurityException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
         // Not allowed access to parent ThreadGroup -- just use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
         // the AppContext's ThreadGroup
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
         fetcherThreadGroup = appContext.getThreadGroup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
       }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
       final ThreadGroup fetcherGroup = fetcherThreadGroup;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
       java.security.AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
         new java.security.PrivilegedAction() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
         public Object run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
             for (int i = 0; i < info.fetchers.length; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
               if (info.fetchers[i] == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                   info.fetchers[i] = new ImageFetcher(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                           fetcherGroup, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                   info.fetchers[i].start();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                   info.numFetchers++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
                   break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
               }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
             }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
          return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
       });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
      return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
  * The FetcherInfo class encapsulates the per-AppContext ImageFetcher
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
  * information.  This includes the array of ImageFetchers, as well as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
  * the queue of ImageFetchable objects.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
  */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
class FetcherInfo {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    static final int MAX_NUM_FETCHERS_PER_APPCONTEXT = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
    Thread[] fetchers;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    int numFetchers;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    int numWaiting;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    Vector waitList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
    private FetcherInfo() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        fetchers = new Thread[MAX_NUM_FETCHERS_PER_APPCONTEXT];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        numFetchers = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        numWaiting = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
        waitList = new Vector();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    /* The key to put()/get() the FetcherInfo into/from the AppContext. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    private static final Object FETCHER_INFO_KEY =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
                                        new StringBuffer("FetcherInfo");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    static FetcherInfo getFetcherInfo() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        AppContext appContext = AppContext.getAppContext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        synchronized(appContext) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            FetcherInfo info = (FetcherInfo)appContext.get(FETCHER_INFO_KEY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            if (info == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                info = new FetcherInfo();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                appContext.put(FETCHER_INFO_KEY, info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
            return info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
}