117 * compatibility across versions.
118 *
119 * Implementations of non-core methods are mostly the same as in
120 * SplittableRandom, that were in part derived from a previous
121 * version of this class.
122 *
123 * The nextLocalGaussian ThreadLocal supports the very rarely used
124 * nextGaussian method by providing a holder for the second of a
125 * pair of them. As is true for the base class version of this
126 * method, this time/space tradeoff is probably never worthwhile,
127 * but we provide identical statistical properties.
128 */
129
130 /** Generates per-thread initialization/probe field */
131 private static final AtomicInteger probeGenerator =
132 new AtomicInteger();
133
134 /**
135 * The next seed for default constructors.
136 */
137 private static final AtomicLong seeder = new AtomicLong(initialSeed());
138
139 private static long initialSeed() {
140 String pp = java.security.AccessController.doPrivileged(
141 new sun.security.action.GetPropertyAction(
142 "java.util.secureRandomSeed"));
143 if (pp != null && pp.equalsIgnoreCase("true")) {
144 byte[] seedBytes = java.security.SecureRandom.getSeed(8);
145 long s = (long)(seedBytes[0]) & 0xffL;
146 for (int i = 1; i < 8; ++i)
147 s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
148 return s;
149 }
150 long h = 0L;
151 try {
152 Enumeration<NetworkInterface> ifcs =
153 NetworkInterface.getNetworkInterfaces();
154 boolean retry = false; // retry once if getHardwareAddress is null
155 while (ifcs.hasMoreElements()) {
156 NetworkInterface ifc = ifcs.nextElement();
157 if (!ifc.isVirtual()) { // skip fake addresses
158 byte[] bs = ifc.getHardwareAddress();
159 if (bs != null) {
160 int n = bs.length;
161 int m = Math.min(n >>> 1, 4);
162 for (int i = 0; i < m; ++i)
163 h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
164 if (m < 4)
165 h = (h << 8) ^ bs[n-1-m];
166 h = mix64(h);
167 break;
168 }
169 else if (!retry)
170 retry = true;
171 else
172 break;
173 }
174 }
175 } catch (Exception ignore) {
176 }
177 return (h ^ mix64(System.currentTimeMillis()) ^
178 mix64(System.nanoTime()));
179 }
180
181 /**
182 * The seed increment
183 */
184 private static final long GAMMA = 0x9e3779b97f4a7c15L;
185
186 /**
187 * The increment for generating probe values
188 */
189 private static final int PROBE_INCREMENT = 0x9e3779b9;
190
191 /**
192 * The increment of seeder per new instance
193 */
194 private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
195
196 // Constants from SplittableRandom
197 private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
198 private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
199
1062 * @param s the stream
1063 * @throws java.io.IOException if an I/O error occurs
1064 */
1065 private void writeObject(java.io.ObjectOutputStream s)
1066 throws java.io.IOException {
1067
1068 java.io.ObjectOutputStream.PutField fields = s.putFields();
1069 fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
1070 fields.put("initialized", true);
1071 s.writeFields();
1072 }
1073
1074 /**
1075 * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
1076 * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
1077 */
1078 private Object readResolve() {
1079 return current();
1080 }
1081
1082 // Unsafe mechanics
1083 private static final sun.misc.Unsafe UNSAFE;
1084 private static final long SEED;
1085 private static final long PROBE;
1086 private static final long SECONDARY;
1087 static {
1088 try {
1089 UNSAFE = sun.misc.Unsafe.getUnsafe();
1090 Class<?> tk = Thread.class;
1091 SEED = UNSAFE.objectFieldOffset
1092 (tk.getDeclaredField("threadLocalRandomSeed"));
1093 PROBE = UNSAFE.objectFieldOffset
1094 (tk.getDeclaredField("threadLocalRandomProbe"));
1095 SECONDARY = UNSAFE.objectFieldOffset
1096 (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
1097 } catch (Exception e) {
1098 throw new Error(e);
1099 }
1100 }
1101 }
|
117 * compatibility across versions.
118 *
119 * Implementations of non-core methods are mostly the same as in
120 * SplittableRandom, that were in part derived from a previous
121 * version of this class.
122 *
123 * The nextLocalGaussian ThreadLocal supports the very rarely used
124 * nextGaussian method by providing a holder for the second of a
125 * pair of them. As is true for the base class version of this
126 * method, this time/space tradeoff is probably never worthwhile,
127 * but we provide identical statistical properties.
128 */
129
130 /** Generates per-thread initialization/probe field */
131 private static final AtomicInteger probeGenerator =
132 new AtomicInteger();
133
134 /**
135 * The next seed for default constructors.
136 */
137 private static final AtomicLong seeder =
138 // this is just intermediate value - see static block at end of file...
139 new AtomicLong(mix64(System.currentTimeMillis()) ^
140 mix64(System.nanoTime()));
141
142 /**
143 * The seed increment
144 */
145 private static final long GAMMA = 0x9e3779b97f4a7c15L;
146
147 /**
148 * The increment for generating probe values
149 */
150 private static final int PROBE_INCREMENT = 0x9e3779b9;
151
152 /**
153 * The increment of seeder per new instance
154 */
155 private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
156
157 // Constants from SplittableRandom
158 private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53)
159 private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24)
160
1023 * @param s the stream
1024 * @throws java.io.IOException if an I/O error occurs
1025 */
1026 private void writeObject(java.io.ObjectOutputStream s)
1027 throws java.io.IOException {
1028
1029 java.io.ObjectOutputStream.PutField fields = s.putFields();
1030 fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
1031 fields.put("initialized", true);
1032 s.writeFields();
1033 }
1034
1035 /**
1036 * Returns the {@link #current() current} thread's {@code ThreadLocalRandom}.
1037 * @return the {@link #current() current} thread's {@code ThreadLocalRandom}
1038 */
1039 private Object readResolve() {
1040 return current();
1041 }
1042
1043 // Unsafe mechanics and "seeder" initialization
1044 private static final sun.misc.Unsafe UNSAFE;
1045 private static final long SEED;
1046 private static final long PROBE;
1047 private static final long SECONDARY;
1048 static {
1049 try {
1050 UNSAFE = sun.misc.Unsafe.getUnsafe();
1051 Class<?> tk = Thread.class;
1052 SEED = UNSAFE.objectFieldOffset
1053 (tk.getDeclaredField("threadLocalRandomSeed"));
1054 PROBE = UNSAFE.objectFieldOffset
1055 (tk.getDeclaredField("threadLocalRandomProbe"));
1056 SECONDARY = UNSAFE.objectFieldOffset
1057 (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
1058 } catch (Exception e) {
1059 throw new Error(e);
1060 }
1061
1062 // finish initialization of "seeder"
1063 String pp = java.security.AccessController.doPrivileged(
1064 new sun.security.action.GetPropertyAction(
1065 "java.util.secureRandomSeed"));
1066 if (pp != null && pp.equalsIgnoreCase("true")) {
1067 byte[] seedBytes = java.security.SecureRandom.getSeed(8);
1068 long s = (long)(seedBytes[0]) & 0xffL;
1069 for (int i = 1; i < 8; ++i)
1070 s = (s << 8) | ((long)(seedBytes[i]) & 0xffL);
1071 seeder.set(s);
1072 } else {
1073 try {
1074 long h = 0L;
1075 Enumeration<NetworkInterface> ifcs =
1076 NetworkInterface.getNetworkInterfaces();
1077 boolean retry = false; // retry once if getHardwareAddress is null
1078 while (ifcs.hasMoreElements()) {
1079 NetworkInterface ifc = ifcs.nextElement();
1080 if (!ifc.isVirtual()) { // skip fake addresses
1081 byte[] bs = ifc.getHardwareAddress();
1082 if (bs != null) {
1083 int n = bs.length;
1084 int m = Math.min(n >>> 1, 4);
1085 for (int i = 0; i < m; ++i)
1086 h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i];
1087 if (m < 4)
1088 h = (h << 8) ^ bs[n-1-m];
1089 h = mix64(h);
1090 break;
1091 }
1092 else if (!retry)
1093 retry = true;
1094 else
1095 break;
1096 }
1097 }
1098 seeder.set(seeder.get() ^ h);
1099 } catch (Exception ignore) {
1100 }
1101 }
1102 // trigger re-initialization of thread-local state
1103 // in case TLR has already been used in current thread
1104 UNSAFE.putInt(Thread.currentThread(), PROBE, 0);
1105 }
1106
1107 }
|