001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.links;
028:
029: import com.sun.cldc.isolate.Isolate;
030:
031: /**
032: * This class provides foreign methods of the Isolate class. (For discussion
033: * of foreign methods, see Fowler, _Refactoring_, "Introduce Foreign Method",
034: * p. 162.)
035: *
036: * The technique for passing links between isolates is implemented as a
037: * separate class in order to avoid short term dependencies on the
038: * implementation of the Isolate class in CLDC. These functions will
039: * eventually be moved to the Isolate class of CLDC.
040: *
041: * IMPL_NOTE
042: *
043: * The current arrangement is highly problematic and therefore should be
044: * considered only as a temporary solution. The portal keeps track of links by
045: * isolate ID. However, an isolate ID is only assigned after the isolate has
046: * been started. Therefore, getLinks() must block until the parent isolate has
047: * had a chance to call setLinks(). The sender and receiver must agree to pass
048: * this initial set of links. This is pretty fragile, but it's only necessary
049: * for passing the initial set of links. Any additional links can be passed
050: * via the initial set of links.
051: *
052: * If an isolate dies before it gets its links, they'll be stranded in the
053: * portal. The parent isolate can overwrite them, though, and they should be
054: * collected. Worse, if an isolate dies and another isolate is created and
055: * gets the same IDs, it can get the links that were destined for the first.
056: * This requires the parent isolate to be responsible for cleaning up any
057: * unused links passed to its children, which could be difficult in general.
058: */
059: public class LinkPortal {
060:
061: /**
062: * Gets the links for this isolate that had been set by its creator. If
063: * links are available, this returns immediately. If no links are
064: * available, this method will block until the creator sets them. This
065: * requires close cooperation between the creator isolate and the newly
066: * created isolate. The typical usage is that the creator creates the new
067: * isolate and passes one set of links to it, and the first thing the new
068: * new isolate does is to get this initial set of links. Any subsequent
069: * links should be passed through the initial set of links.
070: */
071: public synchronized static Link[] getLinks() {
072: int count = getLinkCount0();
073:
074: Link[] la = new Link[count];
075:
076: for (int i = 0; i < count; i++) {
077: la[i] = new Link();
078: }
079:
080: /*
081: * IMPL_NOTE - race condition
082: * The creator could change the number of links between the call to
083: * getCount0() and the call to getLinks0().
084: */
085:
086: getLinks0(la);
087: return la;
088: }
089:
090: /**
091: * Sets the array of links for the given isolate. Once set, the array of
092: * links can be retrieved by the designated isolate using the getLinks()
093: * method.
094: *
095: * Setting of links should be done after the isolate is started and before
096: * it terminates, so that a valid id is available. However, this
097: * introduces a race condition between the starting of the isolate, the
098: * call to setLinks(), and the new isolate calling getLinks(). This means
099: * that the new isolate code will need to call getLinks() until it gets
100: * the array of links it expects.
101: *
102: * The linkarray parameter may be null, in which case it removes any links
103: * that had been previously set for isolate. If getLinks() is called at
104: * this point, it will block until a non-null array is set. Passing a
105: * null linkarray to setLinks() differs from passing a zero-length array,
106: * which will satisfy a call to getLinks() and cause it to return a
107: * zero-length array.
108: *
109: * If linkarray is an array whose length is greater than zero, every entry
110: * must be a valid (non-null) Link object.
111: *
112: * @throws NullPointerException if isolate is null
113: * @throws NullPointerException if any entry in linkarray is null
114: * @throws IllegalArgumentException if any link in linkarray is closed
115: * @throws IllegalStateException if isolate hasn't been started or has
116: * been terminated
117: */
118: public static void setLinks(Isolate isolate, Link[] linkarray) {
119: if (isolate == null) {
120: throw new NullPointerException();
121: }
122:
123: if (linkarray != null) {
124: for (int i = 0; i < linkarray.length; i++) {
125: if (linkarray[i] == null) {
126: throw new NullPointerException();
127: }
128: }
129: }
130:
131: int id = isolate.id();
132: if (id == -1 || isolate.isTerminated()) {
133: throw new IllegalStateException();
134: }
135:
136: /*
137: * IMPL_NOTE - race conditions
138: * The array could change between these checks and the call to
139: * setLinks0(). The state of the isolate could also change.
140: */
141:
142: setLinks0(id, linkarray);
143: }
144:
145: /**
146: * Prevents construction of any instances.
147: */
148: private LinkPortal() {
149: }
150:
151: private static native int getLinkCount0();
152:
153: private static native void getLinks0(Link[] linkarray);
154:
155: private static native void setLinks0(int isolateid, Link[] linkarray);
156: }
|