From: <ls...@us...> - 2007-01-27 21:52:49
|
Revision: 3095 http://jnode.svn.sourceforge.net/jnode/?rev=3095&view=rev Author: lsantha Date: 2007-01-27 13:52:45 -0800 (Sat, 27 Jan 2007) Log Message: ----------- Classpath patches. Modified Paths: -------------- trunk/core/src/classpath/java/java/lang/Compiler.java trunk/core/src/classpath/java/java/lang/Math.java trunk/core/src/classpath/java/java/lang/SecurityManager.java trunk/core/src/classpath/java/java/lang/StrictMath.java trunk/core/src/classpath/java/java/lang/ThreadGroup.java trunk/core/src/classpath/vm/java/lang/Thread.java Added Paths: ----------- trunk/core/src/classpath/vm/java/lang/VMMath.java Modified: trunk/core/src/classpath/java/java/lang/Compiler.java =================================================================== --- trunk/core/src/classpath/java/java/lang/Compiler.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/Compiler.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -74,7 +74,7 @@ * compilation failed, <code>true</code> if compilation succeeded * @throws NullPointerException if oneClass is null */ - public static boolean compileClass(Class oneClass) + public static boolean compileClass(Class<?> oneClass) { return VMCompiler.compileClass(oneClass); } Modified: trunk/core/src/classpath/java/java/lang/Math.java =================================================================== --- trunk/core/src/classpath/java/java/lang/Math.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/Math.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,5 +1,5 @@ -/* java.lang.Math -- common mathematical functions, native allowed - Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. +/* java.lang.Math -- common mathematical functions, native allowed (VMMath) + Copyright (C) 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,6 +38,8 @@ package java.lang; +import gnu.classpath.Configuration; + import java.util.Random; /** @@ -50,10 +52,26 @@ * @author Paul Fisher * @author John Keiser * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) * @since 1.0 */ public final class Math { + + // FIXME - This is here because we need to load the "javalang" system + // library somewhere late in the bootstrap cycle. We cannot do this + // from VMSystem or VMRuntime since those are used to actually load + // the library. This is mainly here because historically Math was + // late enough in the bootstrap cycle to start using System after it + // was initialized (called from the java.util classes). + static + { + if (Configuration.INIT_LOAD_LIBRARY) + { + System.loadLibrary("javalang"); + } + } + /** * Math is non-instantiable */ @@ -288,11 +306,10 @@ * @param a the angle (in radians) * @return sin(a) */ - // @classpath-bugfix-22918 - public static double sin(double a) { - return StrictMath.sin(a); + public static double sin(double a) + { + return VMMath.sin(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>cos</em>. The cosine of NaN or infinity is @@ -301,11 +318,10 @@ * @param a the angle (in radians) * @return cos(a) */ - // @classpath-bugfix-22918 - public static double cos(double a) { - return StrictMath.cos(a); + public static double cos(double a) + { + return VMMath.cos(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>tan</em>. The tangent of NaN or infinity @@ -315,11 +331,10 @@ * @param a the angle (in radians) * @return tan(a) */ - // @classpath-bugfix-22918 - public static double tan(double a) { - return StrictMath.tan(a); + public static double tan(double a) + { + return VMMath.tan(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>arcsin</em>. The range of angles returned @@ -330,11 +345,10 @@ * @param a the sin to turn back into an angle * @return arcsin(a) */ - // @classpath-bugfix-22918 - public static double asin(double a) { - return StrictMath.asin(a); + public static double asin(double a) + { + return VMMath.asin(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>arccos</em>. The range of angles returned @@ -345,11 +359,10 @@ * @param a the cos to turn back into an angle * @return arccos(a) */ - // @classpath-bugfix-22918 - public static double acos(double a) { - return StrictMath.acos(a); + public static double acos(double a) + { + return VMMath.acos(a); } - // @classpath-bugfix-end /** * The trigonometric function <em>arcsin</em>. The range of angles returned @@ -361,11 +374,10 @@ * @return arcsin(a) * @see #atan2(double, double) */ - // @classpath-bugfix-22918 - public static double atan(double a) { - return StrictMath.atan(a); + public static double atan(double a) + { + return VMMath.atan(a); } - // @classpath-bugfix-end /** * A special version of the trigonometric function <em>arctan</em>, for @@ -414,11 +426,10 @@ * @return <em>theta</em> in the conversion of (x, y) to (r, theta) * @see #atan(double) */ - // @classpath-bugfix-22918 - public static double atan2(double y, double x) { - return StrictMath.atan2(y, x); + public static double atan2(double y, double x) + { + return VMMath.atan2(y,x); } - // @classpath-bugfix-end /** * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the @@ -432,11 +443,10 @@ * @see #log(double) * @see #pow(double, double) */ - // @classpath-bugfix-22918 - public static double exp(double a) { - return StrictMath.exp(a); + public static double exp(double a) + { + return VMMath.exp(a); } - // @classpath-bugfix-end /** * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the @@ -452,11 +462,10 @@ * @return the natural log of <code>a</code> * @see #exp(double) */ - // @classpath-bugfix-22918 - public static double log(double a) { - return StrictMath.log(a); + public static double log(double a) + { + return VMMath.log(a); } - // @classpath-bugfix-end /** * Take a square root. If the argument is NaN or negative, the result is @@ -464,17 +473,18 @@ * infinity; and if the result is either zero, the result is the same. * This is accurate within the limits of doubles. * - * <p>For other roots, use pow(a, 1 / rootNumber). + * <p>For a cube root, use <code>cbrt</code>. For other roots, use + * <code>pow(a, 1 / rootNumber)</code>.</p> * * @param a the numeric argument * @return the square root of the argument + * @see #cbrt(double) * @see #pow(double, double) */ - // @classpath-bugfix-22918 - public static double sqrt(double a) { - return StrictMath.sqrt(a); + public static double sqrt(double a) + { + return VMMath.sqrt(a); } - // @classpath-bugfix-end /** * Raise a number to a power. Special cases:<ul> @@ -544,11 +554,10 @@ * @param b the power to raise it to * @return a<sup>b</sup> */ - // @classpath-bugfix-22918 - public static double pow(double a, double b) { - return StrictMath.pow(a, b); + public static double pow(double a, double b) + { + return VMMath.pow(a,b); } - // @classpath-bugfix-end /** * Get the IEEE 754 floating point remainder on two numbers. This is the @@ -564,11 +573,10 @@ * @return the IEEE 754-defined floating point remainder of x/y * @see #rint(double) */ - // @classpath-bugfix-22918 - public static double IEEEremainder(double x, double y) { - return StrictMath.IEEEremainder(x, y); + public static double IEEEremainder(double x, double y) + { + return VMMath.IEEEremainder(x,y); } - // @classpath-bugfix-end /** * Take the nearest integer that is that is greater than or equal to the @@ -579,11 +587,10 @@ * @param a the value to act upon * @return the nearest integer >= <code>a</code> */ - // @classpath-bugfix-22918 - public static double ceil(double a) { - return StrictMath.ceil(a); + public static double ceil(double a) + { + return VMMath.ceil(a); } - // @classpath-bugfix-end /** * Take the nearest integer that is that is less than or equal to the @@ -593,11 +600,10 @@ * @param a the value to act upon * @return the nearest integer <= <code>a</code> */ - // @classpath-bugfix-22918 - public static double floor(double a) { - return StrictMath.floor(a); + public static double floor(double a) + { + return VMMath.floor(a); } - // @classpath-bugfix-end /** * Take the nearest integer to the argument. If it is exactly between @@ -607,12 +613,10 @@ * @param a the value to act upon * @return the nearest integer to <code>a</code> */ - // @classpath-bugfix-22918 public static double rint(double a) { - return StrictMath.rint(a); + return VMMath.rint(a); } - // @classpath-bugfix-end /** * Take the nearest integer to the argument. This is equivalent to @@ -701,6 +705,99 @@ /** * <p> + * Take a cube root. If the argument is <code>NaN</code>, an infinity or + * zero, then the original value is returned. The returned result is + * within 1 ulp of the exact result. For a finite value, <code>x</code>, + * the cube root of <code>-x</code> is equal to the negation of the cube root + * of <code>x</code>. + * </p> + * <p> + * For a square root, use <code>sqrt</code>. For other roots, use + * <code>pow(a, 1 / rootNumber)</code>. + * </p> + * + * @param a the numeric argument + * @return the cube root of the argument + * @see #sqrt(double) + * @see #pow(double, double) + * @since 1.5 + */ + public static double cbrt(double a) + { + return VMMath.cbrt(a); + } + + /** + * <p> + * Returns the hyperbolic cosine of the given value. For a value, + * <code>x</code>, the hyperbolic cosine is <code>(e<sup>x</sup> + + * e<sup>-x</sup>)/2</code> + * with <code>e</code> being <a href="#E">Euler's number</a>. The returned + * result is within 2.5 ulps of the exact result. + * </p> + * <p> + * If the supplied value is <code>NaN</code>, then the original value is + * returned. For either infinity, positive infinity is returned. + * The hyperbolic cosine of zero is 1.0. + * </p> + * + * @param a the numeric argument + * @return the hyperbolic cosine of <code>a</code>. + * @since 1.5 + */ + public static double cosh(double a) + { + return VMMath.cosh(a); + } + + /** + * <p> + * Returns <code>e<sup>a</sup> - 1. For values close to 0, the + * result of <code>expm1(a) + 1</code> tend to be much closer to the + * exact result than simply <code>exp(x)</code>. The result is within + * 1 ulp of the exact result, and results are semi-monotonic. For finite + * inputs, the returned value is greater than or equal to -1.0. Once + * a result enters within half a ulp of this limit, the limit is returned. + * </p> + * <p> + * For <code>NaN</code>, positive infinity and zero, the original value + * is returned. Negative infinity returns a result of -1.0 (the limit). + * </p> + * + * @param a the numeric argument + * @return <code>e<sup>a</sup> - 1</code> + * @since 1.5 + */ + public static double expm1(double a) + { + return VMMath.expm1(a); + } + + /** + * <p> + * Returns the hypotenuse, <code>a<sup>2</sup> + b<sup>2</sup></code>, + * without intermediate overflow or underflow. The returned result is + * within 1 ulp of the exact result. If one parameter is held constant, + * then the result in the other parameter is semi-monotonic. + * </p> + * <p> + * If either of the arguments is an infinity, then the returned result + * is positive infinity. Otherwise, if either argument is <code>NaN</code>, + * then <code>NaN</code> is returned. + * </p> + * + * @param a the first parameter. + * @param b the second parameter. + * @return the hypotenuse matching the supplied parameters. + * @since 1.5 + */ + public static double hypot(double a, double b) + { + return VMMath.hypot(a,b); + } + + /** + * <p> * Returns the base 10 logarithm of the supplied value. The returned * result is within 1 ulp of the exact result, and the results are * semi-monotonic. @@ -719,7 +816,7 @@ */ public static double log10(double a) { - return log(a)/log(10); + return VMMath.log10(a); } /** @@ -744,7 +841,7 @@ */ public static double log1p(double a) { - return log(a + 1); + return VMMath.log1p(a); } /** @@ -800,7 +897,58 @@ return -1.0f; return a; } + /** + * <p> + * Returns the hyperbolic sine of the given value. For a value, + * <code>x</code>, the hyperbolic sine is <code>(e<sup>x</sup> - + * e<sup>-x</sup>)/2</code> + * with <code>e</code> being <a href="#E">Euler's number</a>. The returned + * result is within 2.5 ulps of the exact result. + * </p> + * <p> + * If the supplied value is <code>NaN</code>, an infinity or a zero, then the + * original value is returned. + * </p> + * + * @param a the numeric argument + * @return the hyperbolic sine of <code>a</code>. + * @since 1.5 + */ + public static double sinh(double a) + { + return VMMath.sinh(a); + } + + /** + * <p> + * Returns the hyperbolic tangent of the given value. For a value, + * <code>x</code>, the hyperbolic tangent is <code>(e<sup>x</sup> - + * e<sup>-x</sup>)/(e<sup>x</sup> + e<sup>-x</sup>)</code> + * (i.e. <code>sinh(a)/cosh(a)</code>) + * with <code>e</code> being <a href="#E">Euler's number</a>. The returned + * result is within 2.5 ulps of the exact result. The absolute value + * of the exact result is always less than 1. Computed results are thus + * less than or equal to 1 for finite arguments, with results within + * half a ulp of either positive or negative 1 returning the appropriate + * limit value (i.e. as if the argument was an infinity). + * </p> + * <p> + * If the supplied value is <code>NaN</code> or zero, then the original + * value is returned. Positive infinity returns +1.0 and negative infinity + * returns -1.0. + * </p> + * + * @param a the numeric argument + * @return the hyperbolic tangent of <code>a</code>. + * @since 1.5 + */ + public static double tanh(double a) + { + return VMMath.tanh(a); + } + + /** * Return the ulp for the given double argument. The ulp is the * difference between the argument and the next larger double. Note * that the sign of the double argument is ignored, that is, Modified: trunk/core/src/classpath/java/java/lang/SecurityManager.java =================================================================== --- trunk/core/src/classpath/java/java/lang/SecurityManager.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/SecurityManager.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,5 +1,5 @@ /* SecurityManager.java -- security checks for privileged actions - Copyright (C) 1998, 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -240,7 +240,7 @@ * @return the most recent non-system Class on the execution stack * @deprecated use {@link #checkPermission(Permission)} instead */ - protected Class currentLoadedClass() + protected Class<?> currentLoadedClass() { int i = classLoaderDepth(); return i >= 0 ? getClassContext()[i] : null; @@ -421,7 +421,7 @@ public void checkAccess(Thread thread) { if (thread.getThreadGroup() != null - && thread.getThreadGroup().getParent() == null) + && thread.getThreadGroup().parent == null) checkPermission(new RuntimePermission("modifyThread")); } @@ -454,7 +454,7 @@ */ public void checkAccess(ThreadGroup g) { - if (g.getParent() == null) + if (g.parent == null) checkPermission(new RuntimePermission("modifyThreadGroup")); } @@ -983,7 +983,7 @@ * @see Member#PUBLIC * @since 1.1 */ - public void checkMemberAccess(Class c, int memberType) + public void checkMemberAccess(Class<?> c, int memberType) { if (c == null) throw new NullPointerException(); Modified: trunk/core/src/classpath/java/java/lang/StrictMath.java =================================================================== --- trunk/core/src/classpath/java/java/lang/StrictMath.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/StrictMath.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,5 +1,5 @@ /* java.lang.StrictMath -- common mathematical functions, strict Java - Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1998, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -633,6 +633,381 @@ } /** + * Returns the hyperbolic sine of <code>x</code> which is defined as + * (exp(x) - exp(-x)) / 2. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is negative + * infinity.</li> + * <li>If the argument is zero, the result is zero.</li> + * </ul> + * + * @param x the argument to <em>sinh</em> + * @return the hyperbolic sine of <code>x</code> + * + * @since 1.5 + */ + public static double sinh(double x) + { + // Method : + // mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 + // 1. Replace x by |x| (sinh(-x) = -sinh(x)). + // 2. + // E + E/(E+1) + // 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) + // 2 + // + // 22 <= x <= lnovft : sinh(x) := exp(x)/2 + // lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) + // ln2ovft < x : sinh(x) := +inf (overflow) + + double t, w, h; + + long bits; + long h_bits; + long l_bits; + + // handle special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.NEGATIVE_INFINITY; + + if (x < 0) + h = - 0.5; + else + h = 0.5; + + bits = Double.doubleToLongBits(x); + h_bits = getHighDWord(bits) & 0x7fffffffL; // ignore sign + l_bits = getLowDWord(bits); + + // |x| in [0, 22], return sign(x) * 0.5 * (E+E/(E+1)) + if (h_bits < 0x40360000L) // |x| < 22 + { + if (h_bits < 0x3e300000L) // |x| < 2^-28 + return x; // for tiny arguments return x + + t = expm1(abs(x)); + + if (h_bits < 0x3ff00000L) + return h * (2.0 * t - t * t / (t + 1.0)); + + return h * (t + t / (t + 1.0)); + } + + // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|) + if (h_bits < 0x40862e42L) + return h * exp(abs(x)); + + // |x| in [log(Double.MAX_VALUE), overflowthreshold] + if ((h_bits < 0x408633ceL) + || ((h_bits == 0x408633ceL) && (l_bits <= 0x8fb9f87dL))) + { + w = exp(0.5 * abs(x)); + t = h * w; + + return t * w; + } + + // |x| > overflowthershold + return h * Double.POSITIVE_INFINITY; + } + + /** + * Returns the hyperbolic cosine of <code>x</code>, which is defined as + * (exp(x) + exp(-x)) / 2. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is positive + * infinity.</li> + * <li>If the argument is zero, the result is one.</li> + * </ul> + * + * @param x the argument to <em>cosh</em> + * @return the hyperbolic cosine of <code>x</code> + * + * @since 1.5 + */ + public static double cosh(double x) + { + // Method : + // mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 + // 1. Replace x by |x| (cosh(x) = cosh(-x)). + // 2. + // [ exp(x) - 1 ]^2 + // 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- + // 2*exp(x) + // + // exp(x) + 1/exp(x) + // ln2/2 <= x <= 22 : cosh(x) := ------------------ + // 2 + // 22 <= x <= lnovft : cosh(x) := exp(x)/2 + // lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) + // ln2ovft < x : cosh(x) := +inf (overflow) + + double t, w; + long bits; + long hx; + long lx; + + // handle special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.POSITIVE_INFINITY; + + bits = Double.doubleToLongBits(x); + hx = getHighDWord(bits) & 0x7fffffffL; // ignore sign + lx = getLowDWord(bits); + + // |x| in [0, 0.5 * ln(2)], return 1 + expm1(|x|)^2 / (2 * exp(|x|)) + if (hx < 0x3fd62e43L) + { + t = expm1(abs(x)); + w = 1.0 + t; + + // for tiny arguments return 1. + if (hx < 0x3c800000L) + return w; + + return 1.0 + (t * t) / (w + w); + } + + // |x| in [0.5 * ln(2), 22], return exp(|x|)/2 + 1 / (2 * exp(|x|)) + if (hx < 0x40360000L) + { + t = exp(abs(x)); + + return 0.5 * t + 0.5 / t; + } + + // |x| in [22, log(Double.MAX_VALUE)], return 0.5 * exp(|x|) + if (hx < 0x40862e42L) + return 0.5 * exp(abs(x)); + + // |x| in [log(Double.MAX_VALUE), overflowthreshold], + // return exp(x/2)/2 * exp(x/2) + if ((hx < 0x408633ceL) + || ((hx == 0x408633ceL) && (lx <= 0x8fb9f87dL))) + { + w = exp(0.5 * abs(x)); + t = 0.5 * w; + + return t * w; + } + + // |x| > overflowthreshold + return Double.POSITIVE_INFINITY; + } + + /** + * Returns the hyperbolic tangent of <code>x</code>, which is defined as + * (exp(x) - exp(-x)) / (exp(x) + exp(-x)), i.e. sinh(x) / cosh(x). + * + Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is 1.</li> + * <li>If the argument is negative infinity, the result is -1.</li> + * <li>If the argument is zero, the result is zero.</li> + * </ul> + * + * @param x the argument to <em>tanh</em> + * @return the hyperbolic tagent of <code>x</code> + * + * @since 1.5 + */ + public static double tanh(double x) + { + // Method : + // 0. tanh(x) is defined to be (exp(x) - exp(-x)) / (exp(x) + exp(-x)) + // 1. reduce x to non-negative by tanh(-x) = -tanh(x). + // 2. 0 <= x <= 2^-55 : tanh(x) := x * (1.0 + x) + // -t + // 2^-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) + // t + 2 + // 2 + // 1 <= x <= 22.0 : tanh(x) := 1 - ----- ; t=expm1(2x) + // t + 2 + // 22.0 < x <= INF : tanh(x) := 1. + + double t, z; + + long bits; + long h_bits; + + // handle special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return 1.0; + if (x == Double.NEGATIVE_INFINITY) + return -1.0; + + bits = Double.doubleToLongBits(x); + h_bits = getHighDWord(bits) & 0x7fffffffL; // ingnore sign + + if (h_bits < 0x40360000L) // |x| < 22 + { + if (h_bits < 0x3c800000L) // |x| < 2^-55 + return x * (1.0 + x); + + if (h_bits >= 0x3ff00000L) // |x| >= 1 + { + t = expm1(2.0 * abs(x)); + z = 1.0 - 2.0 / (t + 2.0); + } + else // |x| < 1 + { + t = expm1(-2.0 * abs(x)); + z = -t / (t + 2.0); + } + } + else // |x| >= 22 + z = 1.0; + + return (x >= 0) ? z : -z; + } + + /** + * Returns the lower two words of a long. This is intended to be + * used like this: + * <code>getLowDWord(Double.doubleToLongBits(x))</code>. + */ + private static long getLowDWord(long x) + { + return x & 0x00000000ffffffffL; + } + + /** + * Returns the higher two words of a long. This is intended to be + * used like this: + * <code>getHighDWord(Double.doubleToLongBits(x))</code>. + */ + private static long getHighDWord(long x) + { + return (x & 0xffffffff00000000L) >> 32; + } + + /** + * Returns a double with the IEEE754 bit pattern given in the lower + * and higher two words <code>lowDWord</code> and <code>highDWord</code>. + */ + private static double buildDouble(long lowDWord, long highDWord) + { + return Double.longBitsToDouble(((highDWord & 0xffffffffL) << 32) + | (lowDWord & 0xffffffffL)); + } + + /** + * Returns the cube root of <code>x</code>. The sign of the cube root + * is equal to the sign of <code>x</code>. + * + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN</li> + * <li>If the argument is positive infinity, the result is positive + * infinity.</li> + * <li>If the argument is negative infinity, the result is negative + * infinity.</li> + * <li>If the argument is zero, the result is zero with the same + * sign as the argument.</li> + * </ul> + * + * @param x the number to take the cube root of + * @return the cube root of <code>x</code> + * @see #sqrt(double) + * + * @since 1.5 + */ + public static double cbrt(double x) + { + boolean negative = (x < 0); + double r; + double s; + double t; + double w; + + long bits; + long l; + long h; + + // handle the special cases + if (x != x) + return x; + if (x == Double.POSITIVE_INFINITY) + return Double.POSITIVE_INFINITY; + if (x == Double.NEGATIVE_INFINITY) + return Double.NEGATIVE_INFINITY; + if (x == 0) + return x; + + x = abs(x); + bits = Double.doubleToLongBits(x); + + if (bits < 0x0010000000000000L) // subnormal number + { + t = TWO_54; + t *= x; + + // __HI(t)=__HI(t)/3+B2; + bits = Double.doubleToLongBits(t); + h = getHighDWord(bits); + l = getLowDWord(bits); + + h = h / 3 + CBRT_B2; + + t = buildDouble(l, h); + } + else + { + // __HI(t)=__HI(x)/3+B1; + h = getHighDWord(bits); + l = 0; + + h = h / 3 + CBRT_B1; + t = buildDouble(l, h); + } + + // new cbrt to 23 bits + r = t * t / x; + s = CBRT_C + r * t; + t *= CBRT_G + CBRT_F / (s + CBRT_E + CBRT_D / s); + + // chopped to 20 bits and make it larger than cbrt(x) + bits = Double.doubleToLongBits(t); + h = getHighDWord(bits); + + // __LO(t)=0; + // __HI(t)+=0x00000001; + l = 0; + h += 1; + t = buildDouble(l, h); + + // one step newton iteration to 53 bits with error less than 0.667 ulps + s = t * t; // t * t is exact + r = x / s; + w = t + t; + r = (r - t) / (w + r); // r - t is exact + t = t + t * r; + + return negative ? -t : t; + } + + /** * Take <em>e</em><sup>a</sup>. The opposite of <code>log()</code>. If the * argument is NaN, the result is NaN; if the argument is positive infinity, * the result is positive infinity; and if the argument is negative @@ -694,6 +1069,254 @@ } /** + * Returns <em>e</em><sup>x</sup> - 1. + * Special cases: + * <ul> + * <li>If the argument is NaN, the result is NaN.</li> + * <li>If the argument is positive infinity, the result is positive + * infinity</li> + * <li>If the argument is negative infinity, the result is -1.</li> + * <li>If the argument is zero, the result is zero.</li> + * </ul> + * + * @param x the argument to <em>e</em><sup>x</sup> - 1. + * @return <em>e</em> raised to the power <code>x</code> minus one. + * @see #exp(double) + */ + public static double expm1(double x) + { + // Method + // 1. Argument reduction: + // Given x, find r and integer k such that + // + // x = k * ln(2) + r, |r| <= 0.5 * ln(2) + // + // Here a correction term c will be computed to compensate + // the error in r when rounded to a floating-point number. + // + // 2. Approximating expm1(r) by a special rational function on + // the interval [0, 0.5 * ln(2)]: + // Since + // r*(exp(r)+1)/(exp(r)-1) = 2 + r^2/6 - r^4/360 + ... + // we define R1(r*r) by + // r*(exp(r)+1)/(exp(r)-1) = 2 + r^2/6 * R1(r*r) + // That is, + // R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + // = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + // = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + // We use a special Remes algorithm on [0, 0.347] to generate + // a polynomial of degree 5 in r*r to approximate R1. The + // maximum error of this polynomial approximation is bounded + // by 2**-61. In other words, + // R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + // where Q1 = -1.6666666666666567384E-2, + // Q2 = 3.9682539681370365873E-4, + // Q3 = -9.9206344733435987357E-6, + // Q4 = 2.5051361420808517002E-7, + // Q5 = -6.2843505682382617102E-9; + // (where z=r*r, and Q1 to Q5 are called EXPM1_Qx in the source) + // with error bounded by + // | 5 | -61 + // | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + // | | + // + // expm1(r) = exp(r)-1 is then computed by the following + // specific way which minimize the accumulation rounding error: + // 2 3 + // r r [ 3 - (R1 + R1*r/2) ] + // expm1(r) = r + --- + --- * [--------------------] + // 2 2 [ 6 - r*(3 - R1*r/2) ] + // + // To compensate the error in the argument reduction, we use + // expm1(r+c) = expm1(r) + c + expm1(r)*c + // ~ expm1(r) + c + r*c + // Thus c+r*c will be added in as the correction terms for + // expm1(r+c). Now rearrange the term to avoid optimization + // screw up: + // ( 2 2 ) + // ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + // expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + // ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + // ( ) + // + // = r - E + // 3. Scale back to obtain expm1(x): + // From step 1, we have + // expm1(x) = either 2^k*[expm1(r)+1] - 1 + // = or 2^k*[expm1(r) + (1-2^-k)] + // 4. Implementation notes: + // (A). To save one multiplication, we scale the coefficient Qi + // to Qi*2^i, and replace z by (x^2)/2. + // (B). To achieve maximum accuracy, we compute expm1(x) by + // (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + // (ii) if k=0, return r-E + // (iii) if k=-1, return 0.5*(r-E)-0.5 + // (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + // else return 1.0+2.0*(r-E); + // (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + // (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + // (vii) return 2^k(1-((E+2^-k)-r)) + + boolean negative = (x < 0); + double y, hi, lo, c, t, e, hxs, hfx, r1; + int k; + + long bits; + long h_bits; + long l_bits; + + c = 0.0; + y = abs(x); + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + // handle special cases and large arguments + if (h_bits >= 0x4043687aL) // if |x| >= 56 * ln(2) + { + if (h_bits >= 0x40862e42L) // if |x| >= EXP_LIMIT_H + { + if (h_bits >= 0x7ff00000L) + { + if (((h_bits & 0x000fffffL) | (l_bits & 0xffffffffL)) != 0) + return x; // exp(NaN) = NaN + else + return negative ? -1.0 : x; // exp({+-inf}) = {+inf, -1} + } + + if (x > EXP_LIMIT_H) + return Double.POSITIVE_INFINITY; // overflow + } + + if (negative) // x <= -56 * ln(2) + return -1.0; + } + + // argument reduction + if (h_bits > 0x3fd62e42L) // |x| > 0.5 * ln(2) + { + if (h_bits < 0x3ff0a2b2L) // |x| < 1.5 * ln(2) + { + if (negative) + { + hi = x + LN2_H; + lo = -LN2_L; + k = -1; + } + else + { + hi = x - LN2_H; + lo = LN2_L; + k = 1; + } + } + else + { + k = (int) (INV_LN2 * x + (negative ? - 0.5 : 0.5)); + t = k; + hi = x - t * LN2_H; + lo = t * LN2_L; + } + + x = hi - lo; + c = (hi - x) - lo; + + } + else if (h_bits < 0x3c900000L) // |x| < 2^-54 return x + return x; + else + k = 0; + + // x is now in primary range + hfx = 0.5 * x; + hxs = x * hfx; + r1 = 1.0 + hxs * (EXPM1_Q1 + + hxs * (EXPM1_Q2 + + hxs * (EXPM1_Q3 + + hxs * (EXPM1_Q4 + + hxs * EXPM1_Q5)))); + t = 3.0 - r1 * hfx; + e = hxs * ((r1 - t) / (6.0 - x * t)); + + if (k == 0) + { + return x - (x * e - hxs); // c == 0 + } + else + { + e = x * (e - c) - c; + e -= hxs; + + if (k == -1) + return 0.5 * (x - e) - 0.5; + + if (k == 1) + { + if (x < - 0.25) + return -2.0 * (e - (x + 0.5)); + else + return 1.0 + 2.0 * (x - e); + } + + if (k <= -2 || k > 56) // sufficient to return exp(x) - 1 + { + y = 1.0 - (e - x); + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + h_bits += (k << 20); // add k to y's exponent + + y = buildDouble(l_bits, h_bits); + + return y - 1.0; + } + + t = 1.0; + if (k < 20) + { + bits = Double.doubleToLongBits(t); + h_bits = 0x3ff00000L - (0x00200000L >> k); + l_bits = getLowDWord(bits); + + t = buildDouble(l_bits, h_bits); // t = 1 - 2^(-k) + y = t - (e - x); + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + h_bits += (k << 20); // add k to y's exponent + + y = buildDouble(l_bits, h_bits); + } + else + { + bits = Double.doubleToLongBits(t); + h_bits = (0x000003ffL - k) << 20; + l_bits = getLowDWord(bits); + + t = buildDouble(l_bits, h_bits); // t = 2^(-k) + + y = x - (e + t); + y += 1.0; + + bits = Double.doubleToLongBits(y); + h_bits = getHighDWord(bits); + l_bits = getLowDWord(bits); + + h_bits += (k << 20); // add k to y's exponent + + y = buildDouble(l_bits, h_bits); + } + } + + return y; + } + + /** * Take ln(a) (the natural log). The opposite of <code>exp()</code>. If the * argument is NaN or negative, the result is NaN; if the argument is * positive infinity, the result is positive infinity; and if the argument @@ -1429,6 +2052,33 @@ AT10 = 0.016285820115365782; // Long bits 0x3f90ad3ae322da11L. /** + * Constants for computing {@link #cbrt(double)}. + */ + private static final int + CBRT_B1 = 715094163, // B1 = (682-0.03306235651)*2**20 + CBRT_B2 = 696219795; // B2 = (664-0.03306235651)*2**20 + + /** + * Constants for computing {@link #cbrt(double)}. + */ + private static final double + CBRT_C = 5.42857142857142815906e-01, // Long bits 0x3fe15f15f15f15f1L + CBRT_D = -7.05306122448979611050e-01, // Long bits 0xbfe691de2532c834L + CBRT_E = 1.41428571428571436819e+00, // Long bits 0x3ff6a0ea0ea0ea0fL + CBRT_F = 1.60714285714285720630e+00, // Long bits 0x3ff9b6db6db6db6eL + CBRT_G = 3.57142857142857150787e-01; // Long bits 0x3fd6db6db6db6db7L + + /** + * Constants for computing {@link #expm1(double)} + */ + private static final double + EXPM1_Q1 = -3.33333333333331316428e-02, // Long bits 0xbfa11111111110f4L + EXPM1_Q2 = 1.58730158725481460165e-03, // Long bits 0x3f5a01a019fe5585L + EXPM1_Q3 = -7.93650757867487942473e-05, // Long bits 0xbf14ce199eaadbb7L + EXPM1_Q4 = 4.00821782732936239552e-06, // Long bits 0x3ed0cfca86e65239L + EXPM1_Q5 = -2.01099218183624371326e-07; // Long bits 0xbe8afdb76e09c32dL + + /** * Helper function for reducing an angle to a multiple of pi/2 within * [-pi/4, pi/4]. * @@ -1628,8 +2278,9 @@ j |= iq[i]; if (j == 0) // Need recomputation. { - int k; - for (k = 1; iq[jk - k] == 0; k++); // k = no. of terms needed. + int k; // k = no. of terms needed. + for (k = 1; iq[jk - k] == 0; k++) + ; for (i = jz + 1; i <= jz + k; i++) // Add q[jz+1] to q[jz+k]. { @@ -1841,4 +2492,84 @@ double t = (float) a; return t + a * (1 + t * z + t * v); } + + /** + * <p> + * Returns the sign of the argument as follows: + * </p> + * <ul> + * <li>If <code>a</code> is greater than zero, the result is 1.0.</li> + * <li>If <code>a</code> is less than zero, the result is -1.0.</li> + * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>. + * <li>If <code>a</code> is positive or negative zero, the result is the + * same.</li> + * </ul> + * + * @param a the numeric argument. + * @return the sign of the argument. + * @since 1.5. + */ + public static double signum(double a) + { + // There's no difference. + return Math.signum(a); } + + /** + * <p> + * Returns the sign of the argument as follows: + * </p> + * <ul> + * <li>If <code>a</code> is greater than zero, the result is 1.0f.</li> + * <li>If <code>a</code> is less than zero, the result is -1.0f.</li> + * <li>If <code>a</code> is <code>NaN</code>, the result is <code>NaN</code>. + * <li>If <code>a</code> is positive or negative zero, the result is the + * same.</li> + * </ul> + * + * @param a the numeric argument. + * @return the sign of the argument. + * @since 1.5. + */ + public static float signum(float a) + { + // There's no difference. + return Math.signum(a); + } + + /** + * Return the ulp for the given double argument. The ulp is the + * difference between the argument and the next larger double. Note + * that the sign of the double argument is ignored, that is, + * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. + * If the argument is an infinity, then +Inf is returned. If the + * argument is zero (either positive or negative), then + * {@link Double#MIN_VALUE} is returned. + * @param d the double whose ulp should be returned + * @return the difference between the argument and the next larger double + * @since 1.5 + */ + public static double ulp(double d) + { + // There's no difference. + return Math.ulp(d); + } + + /** + * Return the ulp for the given float argument. The ulp is the + * difference between the argument and the next larger float. Note + * that the sign of the float argument is ignored, that is, + * ulp(x) == ulp(-x). If the argument is a NaN, then NaN is returned. + * If the argument is an infinity, then +Inf is returned. If the + * argument is zero (either positive or negative), then + * {@link Float#MIN_VALUE} is returned. + * @param f the float whose ulp should be returned + * @return the difference between the argument and the next larger float + * @since 1.5 + */ + public static float ulp(float f) + { + // There's no difference. + return Math.ulp(f); + } +} Modified: trunk/core/src/classpath/java/java/lang/ThreadGroup.java =================================================================== --- trunk/core/src/classpath/java/java/lang/ThreadGroup.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/java/java/lang/ThreadGroup.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -37,6 +37,7 @@ package java.lang; +import java.lang.Thread.UncaughtExceptionHandler; import java.util.Vector; /** @@ -53,7 +54,7 @@ * @since 1.0 * @status updated to 1.4 */ -public class ThreadGroup +public class ThreadGroup implements UncaughtExceptionHandler { /** The Initial, top-level ThreadGroup. */ static ThreadGroup root = new ThreadGroup(); @@ -65,7 +66,7 @@ static boolean had_uncaught_exception; /** The parent thread group. */ - private final ThreadGroup parent; + final ThreadGroup parent; /** The group name, non-null. */ final String name; @@ -545,6 +546,8 @@ { if (parent != null) parent.uncaughtException(thread, t); + else if (Thread.getDefaultUncaughtExceptionHandler() != null) + Thread.getDefaultUncaughtExceptionHandler().uncaughtException(thread, t); else if (! (t instanceof ThreadDeath)) { if (t == null) @@ -746,4 +749,43 @@ parent.removeGroup(this); } } + + /* + * Helper method for the VM. Find a Thread by its Id. + * + * @param id The Thread Id. + * @return Thread object or null if thread doesn't exist. + */ + static Thread getThreadFromId(long id) + { + return root.getThreadFromIdImpl(id); + } + + private Thread getThreadFromIdImpl(long id) + { + synchronized (threads) + { + for (int i = 0; i < threads.size(); i++) + { + Thread t = (Thread) threads.get(i); + if (t.getId() == id) + return t; + } + } + Vector groups = this.groups; + if (groups != null) + { + synchronized (groups) + { + for (int i = 0; i < groups.size(); i++) + { + ThreadGroup g = (ThreadGroup) groups.get(i); + Thread t = g.getThreadFromIdImpl(id); + if (t != null) + return t; + } + } + } + return null; + } } // class ThreadGroup Modified: trunk/core/src/classpath/vm/java/lang/Thread.java =================================================================== --- trunk/core/src/classpath/vm/java/lang/Thread.java 2007-01-27 21:37:48 UTC (rev 3094) +++ trunk/core/src/classpath/vm/java/lang/Thread.java 2007-01-27 21:52:45 UTC (rev 3095) @@ -1,21 +1,41 @@ /* Thread -- an independent thread of executable code Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; If not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ + Free Software Foundation +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + package java.lang; import java.util.Map; @@ -32,205 +52,270 @@ import org.jnode.vm.scheduler.VmProcessor; import org.jnode.vm.scheduler.VmThread; + +/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 + * "The Java Language Specification", ISBN 0-201-63451-1 + * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. + * Status: Believed complete to version 1.4, with caveats. We do not + * implement the deprecated (and dangerous) stop, suspend, and resume + * methods. Security implementation is not complete. + */ + /** - * Kore implementation of the <code>java.lang.Thread</code> class. - * <p> - * All native methods are indirected through <code>java.lang.NativeLang</code>. - * - * @version Kore 0.0.3, June 1997 - * @author Glynn Clements <a href="mailto:gl...@se...">gl...@se... - * </a> - * @author E. Prangsma (connection to JNode) + * Thread represents a single thread of execution in the VM. When an + * application VM starts up, it creates a non-daemon Thread which calls the + * main() method of a particular class. There may be other Threads running, + * such as the garbage collection thread. + * + * <p>Threads have names to identify them. These names are not necessarily + * unique. Every Thread has a priority, as well, which tells the VM which + * Threads should get more running time. New threads inherit the priority + * and daemon status of the parent thread, by default. + * + * <p>There are two methods of creating a Thread: you may subclass Thread and + * implement the <code>run()</code> method, at which point you may start the + * Thread by calling its <code>start()</code> method, or you may implement + * <code>Runnable</code> in the class you want to use and then call new + * <code>Thread(your_obj).start()</code>. + * + * <p>The virtual machine runs until all non-daemon threads have died (either + * by returning from the run() method as invoked by start(), or by throwing + * an uncaught exception); or until <code>System.exit</code> is called with + * adequate permissions. + * + * <p>It is unclear at what point a Thread should be added to a ThreadGroup, + * and at what point it should be removed. Should it be inserted when it + * starts, or when it is created? Should it be removed when it is suspended + * or interrupted? The only thing that is clear is that the Thread should be + * removed when it is stopped. + * + * @author Tom Tromey + * @author John Keiser + * @author Eric Blake (eb...@em...) + * @author Andrew John Hughes (gnu...@me...) + * @see Runnable + * @see Runtime#exit(int) + * @see #run() + * @see #start() + * @see ThreadLocal + * @since 1.0 + * @status updated to 1.4 */ -public class Thread implements Runnable { +public class Thread implements Runnable +{ + /** The minimum priority for a Thread. */ + public static final int MIN_PRIORITY = 1; - /** - * Number of threads created. Used only for generating "unique" names. - * - * @see java.lang.Thread#autoName() + /** The priority a Thread gets by default. */ + public static final int NORM_PRIORITY = 5; + + /** The maximum priority for a Thread. */ + public static final int MAX_PRIORITY = 10; + + /** The VM thread implementing this thread */ + private final VmThread vmThread; + + /** The group this thread belongs to. + * */ - private static int count = 0; + ThreadGroup group; - private static final JNodePermission GETVMTHREAD_PERM = new JNodePermission( - "getVmThread"); + /** The object to run(), null if this is the target. */ + final Runnable runnable; - public final static int MAX_PRIORITY = 10; + /** The name of this thread */ + String name; - public final static int MIN_PRIORITY = 1; + /** Is this a daemon thread? */ + private boolean daemon; - public final static int NORM_PRIORITY = 5; + /** The context classloader of this thread */ + private ClassLoader contextClassLoader; + /** The thread in which I was created */ + private final Thread parent; + + /** The default exception handler. */ + private static UncaughtExceptionHandler defaultHandler; + /** Thread local storage. Package accessible for use by * InheritableThreadLocal. */ WeakHashMap locals; - /** - * Gets the active number of threads in the current thread's thread group. - * - * @return the active number of threads in the current thread's thread - * group. - */ - public static int activeCount() { - return currentThread().getThreadGroup().activeCount(); - } + /** The uncaught exception handler. */ + UncaughtExceptionHandler exceptionHandler; /** - * Generate a "unique" default name for a thread. + * Number of threads created. Used only for generating "unique" names. + * + * @see java.lang.Thread#autoName() */ - private static synchronized String autoName() { - return "Thread-" + (++count); - } + private static int count = 0; - /** - * Gets the current thread. - * - * @return - */ - public static Thread currentThread() { - VmThread current = VmThread.currentThread(); - if (current != null) { - return current.asThread(); - } else { - return null; - } - } + private static final JNodePermission GETVMTHREAD_PERM = new JNodePermission( + "getVmThread"); /** - * Prints a stack trace of the current thread. - */ - public static void dumpStack() { - new Exception("Stack trace").printStackTrace(); + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null,</code> + * <i>gname</i><code>)</code>, where <b><i>gname</i></b> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * <p> + * Threads created this way must have overridden their + * <code>run()</code> method to actually do anything. An example + * illustrating this method being used follows: + * <p><blockquote><pre> + * import java.lang.*; + * + * class plain01 implements Runnable { + * String name; + * plain01() { + * name = null; + * } + * plain01(String s) { + * name = s; + * } + * public void run() { + * if (name == null) + * System.out.println("A new thread created"); + * else + * System.out.println("A new thread with name " + name + + * " created"); + * } + * } + * class threadtest01 { + * public static void main(String args[] ) { + * int failed = 0 ; + * + * <b>Thread t1 = new Thread();</b> + * if (t1 != null) + * System.out.println("new Thread() succeed"); + * else { + * System.out.println("new Thread() failed"); + * failed++; + * } + * } + * } + * </pre></blockquote> + * + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) + */ + public Thread() + { + this(null, null, autoName()); } - public static int enumerate(Thread[] threads) { - return currentThread().getThreadGroup().enumerate(threads); - } - /** - * Checks whether the current thread holds the monitor on a given object. - * This allows you to do <code>assert Thread.holdsLock(obj)</code>. + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. * - * @param obj - * the object to test lock ownership on. - * @return true if the current thread is currently synchronized on obj - * @throws NullPointerException - * if obj is null - * @since 1.4 + * @param target the object whose <code>run</code> method is called. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) */ - public static boolean holdsLock(Object obj) { - return MonitorManager.holdsLock(obj); + public Thread(Runnable target) + { + this(null, target, autoName()); } /** - * Has the current thread been interrupted. - * The interrupted flag is cleared. - * @return + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, null, name)</code>. + * + * @param name the name of the new thread. + * @see java.lang.Thread#Thread(java.lang.ThreadGroup, + * java.lang.Runnable, java.lang.String) */ - public static boolean interrupted() { - VmThread current = VmThread.currentThread(); - if (current != null) { - return current.isInterrupted(true); - } else { - return false; - } + public Thread(String name) + { + this(null, null, name); } - public static void sleep(long millis) throws InterruptedException { - sleep(millis, 0); - } - /** - * XXX needs to be synchronized to avoid losing interrupts? it checks and - * sets state, which should be protected... + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, target,</code> + * <i>gname</i><code>)</code>, where <i>gname</i> is + * a newly generated name. Automatically generated names are of the + * form <code>"Thread-"+</code><i>n</i>, where <i>n</i> is an integer. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) */ - public static void sleep(long millis, int nanos) - throws InterruptedException { - VmThread.currentThread().sleep(millis, nanos); + public Thread(ThreadGroup group, Runnable target) + { + this(group, target, autoName()); } - public static void yield() { - VmThread.yield(); - } - - /** The context classloader of this thread */ - private ClassLoader contextClassLoader; - - /** Is this a daemon thread? */ - private boolean daemon; - - /** The group this thread belongs to */ - ThreadGroup group; - - /** The name of this thread */ - String name; - - /** The thread in which I was created */ - private final Thread parent; - - /** A runnable target (if any) */ - private final Runnable target; - - /** The VM thread implementing this thread */ - private final VmThread vmThread; - /** - * Create a new default instance - * - * @see java.lang.Object#Object() + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(group, null, name)</code> + * + * @param group the group to put the Thread into + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see #Thread(ThreadGroup, Runnable, String) */ - public Thread() { - this(null, null, autoName()); + public Thread(ThreadGroup group, String name) + { + this(group, null, name); } /** - * Create a new instance with a runnable as thread runner. + * Allocates a new <code>Thread</code> object. This constructor has + * the same effect as <code>Thread(null, target, name)</code>. * - * @param target + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @see #Thread(ThreadGroup, Runnable, String) */ - public Thread(Runnable target) { - this(null, target, autoName()); - } - - /** - * Create a new instance with a runnable as thread runner and a given name. - * - * @param target - * @param name - */ - public Thread(Runnable target, String name) { + public Thread(Runnable target, String name) + { this(null, target, name); } /** - * Create a new instance with a given name. + * Allocate a new Thread object, with the specified ThreadGroup and name, and + * using the specified Runnable object's <code>run()</code> method to + * execute. If the Runnable object is null, <code>this</code> (which is + * a Runnable) is used instead. * - * @param name + * <p>If the ThreadGroup is null, the security manager is checked. If a + * manager exists and returns a non-null object for + * <code>getThreadGroup</code>, that group is used; otherwise the group + * of the creating thread is used. Note that the security manager calls + * <code>checkAccess</code> if the ThreadGroup is not null. + * + * <p>The new Thread will inherit its creator's priority and daemon status. + * These can be changed with <code>setPriority</code> and + * <code>setDaemon</code>. + * + * @param group the group to put the Thread into + * @param target the Runnable object to execute + * @param name the name for the Thread + * @throws NullPointerException if name is null + * @throws SecurityException if this thread cannot access <code>group</code> + * @throws IllegalThreadStateException if group is destroyed + * @see Runnable#run() + * @see #run() + * @see #setDaemon(boolean) + * @see #setPriority(int) + * @see SecurityManager#checkAccess(ThreadGroup) + * @see ThreadGroup#checkAccess() */ - public Thread(String name) { - this(null, null, name); - } - - /** - * Create a new instance with a given group as containing group and a - * runnable as thread runner. - * - * @param group - * @param target - */ - public Thread(ThreadGroup group, Runnable target) { - this(group, target, autoName()); - } - - /** - * Create a new instance with a given group as containing group, a runnable - * as thread runner and a given name. - * - * @param group - * @param target - * @param name - */ - public Thread(ThreadGroup group, Runnable target, String name) { + public Thread(ThreadGroup group, Runnable target, String name) + { Thread current = currentThread(); if (group != null) { @@ -246,7 +331,7 @@ group.addThread(this); this.group = group; - this.target = target; + this.runnable = target; this.name = name; this.parent = current; @@ -296,7 +381,7 @@ group.addThread(this); this.group = group; - this.target = target; + this.runnable = target; this.name = name; this.parent = current; @@ -328,7 +413,7 @@ group.addThread(this); ... [truncated message content] |