RFR: 8248862: Implement Enhanced Pseudo-Random Number Generators [v3]
Paul Sandoz
psandoz at openjdk.java.net
Wed Nov 18 00:54:18 UTC 2020
On Tue, 17 Nov 2020 22:21:18 GMT, Jim Laskey <jlaskey at openjdk.org> wrote:
>> This PR is to introduce a new random number API for the JDK. The primary API is found in RandomGenerator and RandomGeneratorFactory. Further description can be found in the JEP https://openjdk.java.net/jeps/356 .
>
> Jim Laskey has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 40 commits:
>
> - Merge branch 'master' into 8248862
> - 8248862: Implement Enhanced Pseudo-Random Number Generators
>
> Update package-info.java
> - 8248862: Implement Enhanced Pseudo-Random Number Generators
>
> Updated RandomGeneratorFactory javadoc.
> - 8248862: Implement Enhanced Pseudo-Random Number Generators
>
> Updated documentation for RandomGeneratorFactory.
> - Merge branch 'master' into 8248862
> - Merge branch 'master' into 8248862
> - 8248862: Implement Enhanced Pseudo-Random Number Generators
>
> Move RandomGeneratorProperty
> - Merge branch 'master' into 8248862
> - 8248862: Implement Enhanced Pseudo-Random Number Generators
>
> Clear up javadoc
> - 8248862; Implement Enhanced Pseudo-Random Number Generators
>
> remove RandomGeneratorProperty from API
> - ... and 30 more: https://git.openjdk.java.net/jdk/compare/f7517386...6fe94c68
I am unsure if the intent is also to support external libraries providing `RandomGenerator` implementations. Currently there is an implicit contract for properties (reflectively invoking a method returning a map with a set of entries with known keys). Since the service provider implementation is the `RandomGenerator` itself, rather than `RandomGeneratorFactory` it is harder expose the meta-data with a clearer contract.
src/java.base/share/classes/java/util/Random.java line 592:
> 590:
> 591: @Override
> 592: public Spliterator.OfInt makeIntsSpliterator(long index, long fence, int origin, int bound) {
Unsure if this and the other two methods are intended to be public or not, since they are at the end of the class and override methods of a module private class. In principle there is nothing wrong with such `Spliterator` factories, but wonder if they are really needed given the `Stream` returning methods. The arrangement of classes makes it awkward to hide these methods.
src/java.base/share/classes/java/util/SplittableRandom.java line 171:
> 169: * RandomGenerator properties.
> 170: */
> 171: static Map<RandomGeneratorProperty, Object> getProperties() {
With records exiting preview in 16 this map of properties could i think be represented as a record instance, with better type safety, where `RandomSupport.RandomGeneratorProperty` enum values become typed fields declared on the record class. Something to consider after integration perhaps?
src/java.base/share/classes/java/util/SplittableRandom.java line 211:
> 209: * http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
> 210: */
> 211: private static long mix64(long z) {
Usages be replaced with calls to `RandomSupport.mixStafford13`?
src/java.base/share/classes/module-info.java line 250:
> 248: exports jdk.internal.util.xml.impl to
> 249: jdk.jfr;
> 250: exports jdk.internal.util.random;
Unqualified export, should this be `to jdk.random`?
src/jdk.random/share/classes/module-info.java line 50:
> 48: */
> 49: module jdk.random {
> 50: uses java.util.random.RandomGenerator;
Are these `uses` declarations needed? `ServiceLoader` is not used by this module, and `RandomSupport` is not a service interface.
src/jdk.random/share/classes/module-info.java line 53:
> 51: uses RandomSupport;
> 52:
> 53: exports jdk.random to
Why is this needed?
src/java.base/share/classes/java/util/random/package-info.java line 50:
> 48: * given its name.
> 49: *
> 50: * <p> The principal supporting class is {@link RandomGenertatorFactor}. This
s/RandomGenertatorFactor/RandomGenertatorFactory
src/java.base/share/classes/java/util/random/package-info.java line 140:
> 138: *
> 139: * <p> For applications with no special requirements,
> 140: * "L64X128MixRandom" has a good balance among speed, space,
The documentation assumes that the `jdk.random` module is present in the JDK image. Perhaps we need to spit the specifics to `jdk.random`?
src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java line 1211:
> 1209: Udiff = -Udiff;
> 1210: U2 = U1;
> 1211: U1 -= Udiff;
Updated `U1` never used (recommend running the code through a checker e.g. use IntelliJ)
src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java line 331:
> 329: }
> 330: // Finally, we need to make sure the last z words are not all zero.
> 331: search: {
Nice! a rarely used feature :-)
src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java line 1157:
> 1155: /*
> 1156: * The tables themselves, as well as a number of associated parameters, are
> 1157: * defined in class java.util.DoubleZigguratTables, which is automatically
`DoubleZigguratTables` is an inner class of `RandomSupport`
src/java.base/share/classes/jdk/internal/util/random/RandomSupport.java line 2895:
> 2893: * distribution: 0.0330
> 2894: */
> 2895: static class DoubleZigguratTables {
make `final`
src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java line 167:
> 165: * Return the properties map for the specified provider.
> 166: *
> 167: * @param provider provider to locate.
Method has no such parameter
src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java line 173:
> 171: @SuppressWarnings("unchecked")
> 172: private Map<RandomGeneratorProperty, Object> getProperties() {
> 173: if (properties == null) {
`properties` needs to be marked volatile, and it needs to be assigned at line 182 or line 184.
src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java line 148:
> 146: */
> 147: private static Map<String, Provider<? extends RandomGenerator>> getFactoryMap() {
> 148: if (factoryMap == null) {
`factoryMap` needs to be marked volatile when using the double checked locking idiom.
src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java line 320:
> 318: }
> 319: }
> 320: }
Add an `assert` statement that `ctor`, `ctorLong` and `ctorBytes` are all non-null?
src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java line 331:
> 329: */
> 330: private void ensureConstructors() {
> 331: if (ctor == null) {
This check occurs outside of the synchronized block, field may need to be marked volatile. Unsure about the other dependent fields. Might need to store values from loop in `getConstructors` in locals and then assign in appropriate order, assigning the volatile field last.
-------------
PR: https://git.openjdk.java.net/jdk/pull/1273
More information about the build-dev
mailing list