--- a/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -328,3 +328,4 @@
f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83
51b2db2fa04c16d767b66113dbf08c5349ce382a jdk9-b84
8392405ab038b22e69a3728e17dbdd9e3d3a22ed jdk9-b85
+7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86
--- a/.hgtags-top-repo Tue Oct 13 14:59:44 2015 +0300
+++ b/.hgtags-top-repo Tue Oct 20 08:24:37 2015 -0700
@@ -328,3 +328,4 @@
ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
1c8134475511ffe6726677e1418a89a7a45e92d6 jdk9-b84
1f345217c9bab05f192d00cf1665b3286c49ccdb jdk9-b85
+2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86
--- a/corba/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/corba/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -328,3 +328,4 @@
ca8a1719588424f6e04e943790c7fcb7cb0b8c8f jdk9-b83
df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
3ec06af1368924469f7ce60a00324bac55eaeecc jdk9-b85
+0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
--- a/hotspot/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/hotspot/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -488,3 +488,4 @@
3ed0df2c553a80e0e26b91a6ce08806ea17a066a jdk9-b83
184c4328444974edd6b3b490b9d0177ace7e331c jdk9-b84
03845376ea9dbf9690b6a9cfb4ed63f8cc0541c0 jdk9-b85
+1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
--- a/jaxp/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/jaxp/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -328,3 +328,4 @@
497bc2654e11684b11de46744227883d7e760f35 jdk9-b83
91795d86744f3074d1e59b1e75d9c851c098688f jdk9-b84
1d9850c1b35c74e8b5c17970ed5d46dc0fc33f06 jdk9-b85
+88d9b1f6b73e0c46fcb5ccabe1231a30ce758a22 jdk9-b86
--- a/jaxws/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/jaxws/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -331,3 +331,4 @@
d7ee8157f4feced67924e421225c6f844079a03d jdk9-b83
51729143f8fe038f52cf55720c4c1f89267f5948 jdk9-b84
67b626ec730d2601d95ef036d06be34b37fa9ce6 jdk9-b85
+5289646179079394890a34a898a8ab70fcde0331 jdk9-b86
--- a/jdk/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -328,3 +328,4 @@
d11f25ce3c545823f53bb978d454a4d2901abac3 jdk9-b83
757ef7f6d0042934edea3e0bf616fad2c1a22789 jdk9-b84
fe40b31c0e526d357cf5b62044fea006e43b53a5 jdk9-b85
+e8a66c0b05d786a282a7ff1d7eb4989afa30c891 jdk9-b86
--- a/jdk/make/data/characterdata/CharacterData00.java.template Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/characterdata/CharacterData00.java.template Tue Oct 20 08:24:37 2015 -0700
@@ -136,101 +136,179 @@
if ((val & $$maskLowerCase) != 0) {
if ((val & $$maskCaseOffset) == $$maskCaseOffset) {
switch(ch) {
- // map the offset overflow chars
- case 0x0130 : mapChar = 0x0069; break;
- case 0x2126 : mapChar = 0x03C9; break;
- case 0x212A : mapChar = 0x006B; break;
- case 0x212B : mapChar = 0x00E5; break;
- // map the titlecase chars with both a 1:M uppercase map
- // and a lowercase map
- case 0x1F88 : mapChar = 0x1F80; break;
- case 0x1F89 : mapChar = 0x1F81; break;
- case 0x1F8A : mapChar = 0x1F82; break;
- case 0x1F8B : mapChar = 0x1F83; break;
- case 0x1F8C : mapChar = 0x1F84; break;
- case 0x1F8D : mapChar = 0x1F85; break;
- case 0x1F8E : mapChar = 0x1F86; break;
- case 0x1F8F : mapChar = 0x1F87; break;
- case 0x1F98 : mapChar = 0x1F90; break;
- case 0x1F99 : mapChar = 0x1F91; break;
- case 0x1F9A : mapChar = 0x1F92; break;
- case 0x1F9B : mapChar = 0x1F93; break;
- case 0x1F9C : mapChar = 0x1F94; break;
- case 0x1F9D : mapChar = 0x1F95; break;
- case 0x1F9E : mapChar = 0x1F96; break;
- case 0x1F9F : mapChar = 0x1F97; break;
- case 0x1FA8 : mapChar = 0x1FA0; break;
- case 0x1FA9 : mapChar = 0x1FA1; break;
- case 0x1FAA : mapChar = 0x1FA2; break;
- case 0x1FAB : mapChar = 0x1FA3; break;
- case 0x1FAC : mapChar = 0x1FA4; break;
- case 0x1FAD : mapChar = 0x1FA5; break;
- case 0x1FAE : mapChar = 0x1FA6; break;
- case 0x1FAF : mapChar = 0x1FA7; break;
- case 0x1FBC : mapChar = 0x1FB3; break;
- case 0x1FCC : mapChar = 0x1FC3; break;
- case 0x1FFC : mapChar = 0x1FF3; break;
-
- case 0x023A : mapChar = 0x2C65; break;
- case 0x023E : mapChar = 0x2C66; break;
- case 0x10A0 : mapChar = 0x2D00; break;
- case 0x10A1 : mapChar = 0x2D01; break;
- case 0x10A2 : mapChar = 0x2D02; break;
- case 0x10A3 : mapChar = 0x2D03; break;
- case 0x10A4 : mapChar = 0x2D04; break;
- case 0x10A5 : mapChar = 0x2D05; break;
- case 0x10A6 : mapChar = 0x2D06; break;
- case 0x10A7 : mapChar = 0x2D07; break;
- case 0x10A8 : mapChar = 0x2D08; break;
- case 0x10A9 : mapChar = 0x2D09; break;
- case 0x10AA : mapChar = 0x2D0A; break;
- case 0x10AB : mapChar = 0x2D0B; break;
- case 0x10AC : mapChar = 0x2D0C; break;
- case 0x10AD : mapChar = 0x2D0D; break;
- case 0x10AE : mapChar = 0x2D0E; break;
- case 0x10AF : mapChar = 0x2D0F; break;
- case 0x10B0 : mapChar = 0x2D10; break;
- case 0x10B1 : mapChar = 0x2D11; break;
- case 0x10B2 : mapChar = 0x2D12; break;
- case 0x10B3 : mapChar = 0x2D13; break;
- case 0x10B4 : mapChar = 0x2D14; break;
- case 0x10B5 : mapChar = 0x2D15; break;
- case 0x10B6 : mapChar = 0x2D16; break;
- case 0x10B7 : mapChar = 0x2D17; break;
- case 0x10B8 : mapChar = 0x2D18; break;
- case 0x10B9 : mapChar = 0x2D19; break;
- case 0x10BA : mapChar = 0x2D1A; break;
- case 0x10BB : mapChar = 0x2D1B; break;
- case 0x10BC : mapChar = 0x2D1C; break;
- case 0x10BD : mapChar = 0x2D1D; break;
- case 0x10BE : mapChar = 0x2D1E; break;
- case 0x10BF : mapChar = 0x2D1F; break;
- case 0x10C0 : mapChar = 0x2D20; break;
- case 0x10C1 : mapChar = 0x2D21; break;
- case 0x10C2 : mapChar = 0x2D22; break;
- case 0x10C3 : mapChar = 0x2D23; break;
- case 0x10C4 : mapChar = 0x2D24; break;
- case 0x10C5 : mapChar = 0x2D25; break;
- case 0x10C7 : mapChar = 0x2D27; break;
- case 0x10CD : mapChar = 0x2D2D; break;
- case 0x1E9E : mapChar = 0x00DF; break;
- case 0x2C62 : mapChar = 0x026B; break;
- case 0x2C63 : mapChar = 0x1D7D; break;
- case 0x2C64 : mapChar = 0x027D; break;
- case 0x2C6D : mapChar = 0x0251; break;
- case 0x2C6E : mapChar = 0x0271; break;
- case 0x2C6F : mapChar = 0x0250; break;
- case 0x2C70 : mapChar = 0x0252; break;
- case 0x2C7E : mapChar = 0x023F; break;
- case 0x2C7F : mapChar = 0x0240; break;
- case 0xA77D : mapChar = 0x1D79; break;
- case 0xA78D : mapChar = 0x0265; break;
- case 0xA7AA : mapChar = 0x0266; break;
- case 0xA7AB : mapChar = 0x025C; break;
- case 0xA7AC : mapChar = 0x0261; break;
- case 0xA7AD : mapChar = 0x026C; break;
- case 0xA7B0 : mapChar = 0x029E; break;
- case 0xA7B1 : mapChar = 0x0287; break;
+ case 0x0130: mapChar = 0x0069; break;
+ case 0x023A: mapChar = 0x2C65; break;
+ case 0x023E: mapChar = 0x2C66; break;
+ case 0x10A0: mapChar = 0x2D00; break;
+ case 0x10A1: mapChar = 0x2D01; break;
+ case 0x10A2: mapChar = 0x2D02; break;
+ case 0x10A3: mapChar = 0x2D03; break;
+ case 0x10A4: mapChar = 0x2D04; break;
+ case 0x10A5: mapChar = 0x2D05; break;
+ case 0x10A6: mapChar = 0x2D06; break;
+ case 0x10A7: mapChar = 0x2D07; break;
+ case 0x10A8: mapChar = 0x2D08; break;
+ case 0x10A9: mapChar = 0x2D09; break;
+ case 0x10AA: mapChar = 0x2D0A; break;
+ case 0x10AB: mapChar = 0x2D0B; break;
+ case 0x10AC: mapChar = 0x2D0C; break;
+ case 0x10AD: mapChar = 0x2D0D; break;
+ case 0x10AE: mapChar = 0x2D0E; break;
+ case 0x10AF: mapChar = 0x2D0F; break;
+ case 0x10B0: mapChar = 0x2D10; break;
+ case 0x10B1: mapChar = 0x2D11; break;
+ case 0x10B2: mapChar = 0x2D12; break;
+ case 0x10B3: mapChar = 0x2D13; break;
+ case 0x10B4: mapChar = 0x2D14; break;
+ case 0x10B5: mapChar = 0x2D15; break;
+ case 0x10B6: mapChar = 0x2D16; break;
+ case 0x10B7: mapChar = 0x2D17; break;
+ case 0x10B8: mapChar = 0x2D18; break;
+ case 0x10B9: mapChar = 0x2D19; break;
+ case 0x10BA: mapChar = 0x2D1A; break;
+ case 0x10BB: mapChar = 0x2D1B; break;
+ case 0x10BC: mapChar = 0x2D1C; break;
+ case 0x10BD: mapChar = 0x2D1D; break;
+ case 0x10BE: mapChar = 0x2D1E; break;
+ case 0x10BF: mapChar = 0x2D1F; break;
+ case 0x10C0: mapChar = 0x2D20; break;
+ case 0x10C1: mapChar = 0x2D21; break;
+ case 0x10C2: mapChar = 0x2D22; break;
+ case 0x10C3: mapChar = 0x2D23; break;
+ case 0x10C4: mapChar = 0x2D24; break;
+ case 0x10C5: mapChar = 0x2D25; break;
+ case 0x10C7: mapChar = 0x2D27; break;
+ case 0x10CD: mapChar = 0x2D2D; break;
+ case 0x13A0: mapChar = 0xAB70; break;
+ case 0x13A1: mapChar = 0xAB71; break;
+ case 0x13A2: mapChar = 0xAB72; break;
+ case 0x13A3: mapChar = 0xAB73; break;
+ case 0x13A4: mapChar = 0xAB74; break;
+ case 0x13A5: mapChar = 0xAB75; break;
+ case 0x13A6: mapChar = 0xAB76; break;
+ case 0x13A7: mapChar = 0xAB77; break;
+ case 0x13A8: mapChar = 0xAB78; break;
+ case 0x13A9: mapChar = 0xAB79; break;
+ case 0x13AA: mapChar = 0xAB7A; break;
+ case 0x13AB: mapChar = 0xAB7B; break;
+ case 0x13AC: mapChar = 0xAB7C; break;
+ case 0x13AD: mapChar = 0xAB7D; break;
+ case 0x13AE: mapChar = 0xAB7E; break;
+ case 0x13AF: mapChar = 0xAB7F; break;
+ case 0x13B0: mapChar = 0xAB80; break;
+ case 0x13B1: mapChar = 0xAB81; break;
+ case 0x13B2: mapChar = 0xAB82; break;
+ case 0x13B3: mapChar = 0xAB83; break;
+ case 0x13B4: mapChar = 0xAB84; break;
+ case 0x13B5: mapChar = 0xAB85; break;
+ case 0x13B6: mapChar = 0xAB86; break;
+ case 0x13B7: mapChar = 0xAB87; break;
+ case 0x13B8: mapChar = 0xAB88; break;
+ case 0x13B9: mapChar = 0xAB89; break;
+ case 0x13BA: mapChar = 0xAB8A; break;
+ case 0x13BB: mapChar = 0xAB8B; break;
+ case 0x13BC: mapChar = 0xAB8C; break;
+ case 0x13BD: mapChar = 0xAB8D; break;
+ case 0x13BE: mapChar = 0xAB8E; break;
+ case 0x13BF: mapChar = 0xAB8F; break;
+ case 0x13C0: mapChar = 0xAB90; break;
+ case 0x13C1: mapChar = 0xAB91; break;
+ case 0x13C2: mapChar = 0xAB92; break;
+ case 0x13C3: mapChar = 0xAB93; break;
+ case 0x13C4: mapChar = 0xAB94; break;
+ case 0x13C5: mapChar = 0xAB95; break;
+ case 0x13C6: mapChar = 0xAB96; break;
+ case 0x13C7: mapChar = 0xAB97; break;
+ case 0x13C8: mapChar = 0xAB98; break;
+ case 0x13C9: mapChar = 0xAB99; break;
+ case 0x13CA: mapChar = 0xAB9A; break;
+ case 0x13CB: mapChar = 0xAB9B; break;
+ case 0x13CC: mapChar = 0xAB9C; break;
+ case 0x13CD: mapChar = 0xAB9D; break;
+ case 0x13CE: mapChar = 0xAB9E; break;
+ case 0x13CF: mapChar = 0xAB9F; break;
+ case 0x13D0: mapChar = 0xABA0; break;
+ case 0x13D1: mapChar = 0xABA1; break;
+ case 0x13D2: mapChar = 0xABA2; break;
+ case 0x13D3: mapChar = 0xABA3; break;
+ case 0x13D4: mapChar = 0xABA4; break;
+ case 0x13D5: mapChar = 0xABA5; break;
+ case 0x13D6: mapChar = 0xABA6; break;
+ case 0x13D7: mapChar = 0xABA7; break;
+ case 0x13D8: mapChar = 0xABA8; break;
+ case 0x13D9: mapChar = 0xABA9; break;
+ case 0x13DA: mapChar = 0xABAA; break;
+ case 0x13DB: mapChar = 0xABAB; break;
+ case 0x13DC: mapChar = 0xABAC; break;
+ case 0x13DD: mapChar = 0xABAD; break;
+ case 0x13DE: mapChar = 0xABAE; break;
+ case 0x13DF: mapChar = 0xABAF; break;
+ case 0x13E0: mapChar = 0xABB0; break;
+ case 0x13E1: mapChar = 0xABB1; break;
+ case 0x13E2: mapChar = 0xABB2; break;
+ case 0x13E3: mapChar = 0xABB3; break;
+ case 0x13E4: mapChar = 0xABB4; break;
+ case 0x13E5: mapChar = 0xABB5; break;
+ case 0x13E6: mapChar = 0xABB6; break;
+ case 0x13E7: mapChar = 0xABB7; break;
+ case 0x13E8: mapChar = 0xABB8; break;
+ case 0x13E9: mapChar = 0xABB9; break;
+ case 0x13EA: mapChar = 0xABBA; break;
+ case 0x13EB: mapChar = 0xABBB; break;
+ case 0x13EC: mapChar = 0xABBC; break;
+ case 0x13ED: mapChar = 0xABBD; break;
+ case 0x13EE: mapChar = 0xABBE; break;
+ case 0x13EF: mapChar = 0xABBF; break;
+ case 0x1E9E: mapChar = 0x00DF; break;
+ case 0x1F88: mapChar = 0x1F80; break;
+ case 0x1F89: mapChar = 0x1F81; break;
+ case 0x1F8A: mapChar = 0x1F82; break;
+ case 0x1F8B: mapChar = 0x1F83; break;
+ case 0x1F8C: mapChar = 0x1F84; break;
+ case 0x1F8D: mapChar = 0x1F85; break;
+ case 0x1F8E: mapChar = 0x1F86; break;
+ case 0x1F8F: mapChar = 0x1F87; break;
+ case 0x1F98: mapChar = 0x1F90; break;
+ case 0x1F99: mapChar = 0x1F91; break;
+ case 0x1F9A: mapChar = 0x1F92; break;
+ case 0x1F9B: mapChar = 0x1F93; break;
+ case 0x1F9C: mapChar = 0x1F94; break;
+ case 0x1F9D: mapChar = 0x1F95; break;
+ case 0x1F9E: mapChar = 0x1F96; break;
+ case 0x1F9F: mapChar = 0x1F97; break;
+ case 0x1FA8: mapChar = 0x1FA0; break;
+ case 0x1FA9: mapChar = 0x1FA1; break;
+ case 0x1FAA: mapChar = 0x1FA2; break;
+ case 0x1FAB: mapChar = 0x1FA3; break;
+ case 0x1FAC: mapChar = 0x1FA4; break;
+ case 0x1FAD: mapChar = 0x1FA5; break;
+ case 0x1FAE: mapChar = 0x1FA6; break;
+ case 0x1FAF: mapChar = 0x1FA7; break;
+ case 0x1FBC: mapChar = 0x1FB3; break;
+ case 0x1FCC: mapChar = 0x1FC3; break;
+ case 0x1FFC: mapChar = 0x1FF3; break;
+ case 0x2126: mapChar = 0x03C9; break;
+ case 0x212A: mapChar = 0x006B; break;
+ case 0x212B: mapChar = 0x00E5; break;
+ case 0x2C62: mapChar = 0x026B; break;
+ case 0x2C63: mapChar = 0x1D7D; break;
+ case 0x2C64: mapChar = 0x027D; break;
+ case 0x2C6D: mapChar = 0x0251; break;
+ case 0x2C6E: mapChar = 0x0271; break;
+ case 0x2C6F: mapChar = 0x0250; break;
+ case 0x2C70: mapChar = 0x0252; break;
+ case 0x2C7E: mapChar = 0x023F; break;
+ case 0x2C7F: mapChar = 0x0240; break;
+ case 0xA77D: mapChar = 0x1D79; break;
+ case 0xA78D: mapChar = 0x0265; break;
+ case 0xA7AA: mapChar = 0x0266; break;
+ case 0xA7AB: mapChar = 0x025C; break;
+ case 0xA7AC: mapChar = 0x0261; break;
+ case 0xA7AD: mapChar = 0x026C; break;
+ case 0xA7B0: mapChar = 0x029E; break;
+ case 0xA7B1: mapChar = 0x0287; break;
+ case 0xA7B2: mapChar = 0x029D; break;
+ case 0xA7B3: mapChar = 0xAB53; break;
// default mapChar is already set, so no
// need to redo it here.
// default : mapChar = ch;
@@ -251,98 +329,176 @@
if ((val & $$maskUpperCase) != 0) {
if ((val & $$maskCaseOffset) == $$maskCaseOffset) {
switch(ch) {
- // map chars with overflow offsets
- case 0x00B5 : mapChar = 0x039C; break;
- case 0x017F : mapChar = 0x0053; break;
- case 0x1FBE : mapChar = 0x0399; break;
- // map char that have both a 1:1 and 1:M map
- case 0x1F80 : mapChar = 0x1F88; break;
- case 0x1F81 : mapChar = 0x1F89; break;
- case 0x1F82 : mapChar = 0x1F8A; break;
- case 0x1F83 : mapChar = 0x1F8B; break;
- case 0x1F84 : mapChar = 0x1F8C; break;
- case 0x1F85 : mapChar = 0x1F8D; break;
- case 0x1F86 : mapChar = 0x1F8E; break;
- case 0x1F87 : mapChar = 0x1F8F; break;
- case 0x1F90 : mapChar = 0x1F98; break;
- case 0x1F91 : mapChar = 0x1F99; break;
- case 0x1F92 : mapChar = 0x1F9A; break;
- case 0x1F93 : mapChar = 0x1F9B; break;
- case 0x1F94 : mapChar = 0x1F9C; break;
- case 0x1F95 : mapChar = 0x1F9D; break;
- case 0x1F96 : mapChar = 0x1F9E; break;
- case 0x1F97 : mapChar = 0x1F9F; break;
- case 0x1FA0 : mapChar = 0x1FA8; break;
- case 0x1FA1 : mapChar = 0x1FA9; break;
- case 0x1FA2 : mapChar = 0x1FAA; break;
- case 0x1FA3 : mapChar = 0x1FAB; break;
- case 0x1FA4 : mapChar = 0x1FAC; break;
- case 0x1FA5 : mapChar = 0x1FAD; break;
- case 0x1FA6 : mapChar = 0x1FAE; break;
- case 0x1FA7 : mapChar = 0x1FAF; break;
- case 0x1FB3 : mapChar = 0x1FBC; break;
- case 0x1FC3 : mapChar = 0x1FCC; break;
- case 0x1FF3 : mapChar = 0x1FFC; break;
-
- case 0x023F : mapChar = 0x2C7E; break;
- case 0x0240 : mapChar = 0x2C7F; break;
- case 0x0250 : mapChar = 0x2C6F; break;
- case 0x0251 : mapChar = 0x2C6D; break;
- case 0x0252 : mapChar = 0x2C70; break;
- case 0x025C : mapChar = 0xA7AB; break;
- case 0x0261 : mapChar = 0xA7AC; break;
- case 0x0265 : mapChar = 0xA78D; break;
- case 0x0266 : mapChar = 0xA7AA; break;
- case 0x026B : mapChar = 0x2C62; break;
- case 0x026C : mapChar = 0xA7AD; break;
- case 0x0271 : mapChar = 0x2C6E; break;
- case 0x0287 : mapChar = 0xA7B1; break;
- case 0x029E : mapChar = 0xA7B0; break;
- case 0x027D : mapChar = 0x2C64; break;
- case 0x1D79 : mapChar = 0xA77D; break;
- case 0x1D7D : mapChar = 0x2C63; break;
- case 0x2C65 : mapChar = 0x023A; break;
- case 0x2C66 : mapChar = 0x023E; break;
- case 0x2D00 : mapChar = 0x10A0; break;
- case 0x2D01 : mapChar = 0x10A1; break;
- case 0x2D02 : mapChar = 0x10A2; break;
- case 0x2D03 : mapChar = 0x10A3; break;
- case 0x2D04 : mapChar = 0x10A4; break;
- case 0x2D05 : mapChar = 0x10A5; break;
- case 0x2D06 : mapChar = 0x10A6; break;
- case 0x2D07 : mapChar = 0x10A7; break;
- case 0x2D08 : mapChar = 0x10A8; break;
- case 0x2D09 : mapChar = 0x10A9; break;
- case 0x2D0A : mapChar = 0x10AA; break;
- case 0x2D0B : mapChar = 0x10AB; break;
- case 0x2D0C : mapChar = 0x10AC; break;
- case 0x2D0D : mapChar = 0x10AD; break;
- case 0x2D0E : mapChar = 0x10AE; break;
- case 0x2D0F : mapChar = 0x10AF; break;
- case 0x2D10 : mapChar = 0x10B0; break;
- case 0x2D11 : mapChar = 0x10B1; break;
- case 0x2D12 : mapChar = 0x10B2; break;
- case 0x2D13 : mapChar = 0x10B3; break;
- case 0x2D14 : mapChar = 0x10B4; break;
- case 0x2D15 : mapChar = 0x10B5; break;
- case 0x2D16 : mapChar = 0x10B6; break;
- case 0x2D17 : mapChar = 0x10B7; break;
- case 0x2D18 : mapChar = 0x10B8; break;
- case 0x2D19 : mapChar = 0x10B9; break;
- case 0x2D1A : mapChar = 0x10BA; break;
- case 0x2D1B : mapChar = 0x10BB; break;
- case 0x2D1C : mapChar = 0x10BC; break;
- case 0x2D1D : mapChar = 0x10BD; break;
- case 0x2D1E : mapChar = 0x10BE; break;
- case 0x2D1F : mapChar = 0x10BF; break;
- case 0x2D20 : mapChar = 0x10C0; break;
- case 0x2D21 : mapChar = 0x10C1; break;
- case 0x2D22 : mapChar = 0x10C2; break;
- case 0x2D23 : mapChar = 0x10C3; break;
- case 0x2D24 : mapChar = 0x10C4; break;
- case 0x2D25 : mapChar = 0x10C5; break;
- case 0x2D27 : mapChar = 0x10C7; break;
- case 0x2D2D : mapChar = 0x10CD; break;
+ case 0x017F: mapChar = 0x0053; break;
+ case 0x023F: mapChar = 0x2C7E; break;
+ case 0x0240: mapChar = 0x2C7F; break;
+ case 0x0250: mapChar = 0x2C6F; break;
+ case 0x0251: mapChar = 0x2C6D; break;
+ case 0x0252: mapChar = 0x2C70; break;
+ case 0x025C: mapChar = 0xA7AB; break;
+ case 0x0261: mapChar = 0xA7AC; break;
+ case 0x0265: mapChar = 0xA78D; break;
+ case 0x0266: mapChar = 0xA7AA; break;
+ case 0x026B: mapChar = 0x2C62; break;
+ case 0x026C: mapChar = 0xA7AD; break;
+ case 0x0271: mapChar = 0x2C6E; break;
+ case 0x027D: mapChar = 0x2C64; break;
+ case 0x0287: mapChar = 0xA7B1; break;
+ case 0x029D: mapChar = 0xA7B2; break;
+ case 0x029E: mapChar = 0xA7B0; break;
+ case 0x1D79: mapChar = 0xA77D; break;
+ case 0x1D7D: mapChar = 0x2C63; break;
+ case 0x1F80: mapChar = 0x1F88; break;
+ case 0x1F81: mapChar = 0x1F89; break;
+ case 0x1F82: mapChar = 0x1F8A; break;
+ case 0x1F83: mapChar = 0x1F8B; break;
+ case 0x1F84: mapChar = 0x1F8C; break;
+ case 0x1F85: mapChar = 0x1F8D; break;
+ case 0x1F86: mapChar = 0x1F8E; break;
+ case 0x1F87: mapChar = 0x1F8F; break;
+ case 0x1F90: mapChar = 0x1F98; break;
+ case 0x1F91: mapChar = 0x1F99; break;
+ case 0x1F92: mapChar = 0x1F9A; break;
+ case 0x1F93: mapChar = 0x1F9B; break;
+ case 0x1F94: mapChar = 0x1F9C; break;
+ case 0x1F95: mapChar = 0x1F9D; break;
+ case 0x1F96: mapChar = 0x1F9E; break;
+ case 0x1F97: mapChar = 0x1F9F; break;
+ case 0x1FA0: mapChar = 0x1FA8; break;
+ case 0x1FA1: mapChar = 0x1FA9; break;
+ case 0x1FA2: mapChar = 0x1FAA; break;
+ case 0x1FA3: mapChar = 0x1FAB; break;
+ case 0x1FA4: mapChar = 0x1FAC; break;
+ case 0x1FA5: mapChar = 0x1FAD; break;
+ case 0x1FA6: mapChar = 0x1FAE; break;
+ case 0x1FA7: mapChar = 0x1FAF; break;
+ case 0x1FB3: mapChar = 0x1FBC; break;
+ case 0x1FBE: mapChar = 0x0399; break;
+ case 0x1FC3: mapChar = 0x1FCC; break;
+ case 0x1FF3: mapChar = 0x1FFC; break;
+ case 0x2C65: mapChar = 0x023A; break;
+ case 0x2C66: mapChar = 0x023E; break;
+ case 0x2D00: mapChar = 0x10A0; break;
+ case 0x2D01: mapChar = 0x10A1; break;
+ case 0x2D02: mapChar = 0x10A2; break;
+ case 0x2D03: mapChar = 0x10A3; break;
+ case 0x2D04: mapChar = 0x10A4; break;
+ case 0x2D05: mapChar = 0x10A5; break;
+ case 0x2D06: mapChar = 0x10A6; break;
+ case 0x2D07: mapChar = 0x10A7; break;
+ case 0x2D08: mapChar = 0x10A8; break;
+ case 0x2D09: mapChar = 0x10A9; break;
+ case 0x2D0A: mapChar = 0x10AA; break;
+ case 0x2D0B: mapChar = 0x10AB; break;
+ case 0x2D0C: mapChar = 0x10AC; break;
+ case 0x2D0D: mapChar = 0x10AD; break;
+ case 0x2D0E: mapChar = 0x10AE; break;
+ case 0x2D0F: mapChar = 0x10AF; break;
+ case 0x2D10: mapChar = 0x10B0; break;
+ case 0x2D11: mapChar = 0x10B1; break;
+ case 0x2D12: mapChar = 0x10B2; break;
+ case 0x2D13: mapChar = 0x10B3; break;
+ case 0x2D14: mapChar = 0x10B4; break;
+ case 0x2D15: mapChar = 0x10B5; break;
+ case 0x2D16: mapChar = 0x10B6; break;
+ case 0x2D17: mapChar = 0x10B7; break;
+ case 0x2D18: mapChar = 0x10B8; break;
+ case 0x2D19: mapChar = 0x10B9; break;
+ case 0x2D1A: mapChar = 0x10BA; break;
+ case 0x2D1B: mapChar = 0x10BB; break;
+ case 0x2D1C: mapChar = 0x10BC; break;
+ case 0x2D1D: mapChar = 0x10BD; break;
+ case 0x2D1E: mapChar = 0x10BE; break;
+ case 0x2D1F: mapChar = 0x10BF; break;
+ case 0x2D20: mapChar = 0x10C0; break;
+ case 0x2D21: mapChar = 0x10C1; break;
+ case 0x2D22: mapChar = 0x10C2; break;
+ case 0x2D23: mapChar = 0x10C3; break;
+ case 0x2D24: mapChar = 0x10C4; break;
+ case 0x2D25: mapChar = 0x10C5; break;
+ case 0x2D27: mapChar = 0x10C7; break;
+ case 0x2D2D: mapChar = 0x10CD; break;
+ case 0xAB53: mapChar = 0xA7B3; break;
+ case 0xAB70: mapChar = 0x13A0; break;
+ case 0xAB71: mapChar = 0x13A1; break;
+ case 0xAB72: mapChar = 0x13A2; break;
+ case 0xAB73: mapChar = 0x13A3; break;
+ case 0xAB74: mapChar = 0x13A4; break;
+ case 0xAB75: mapChar = 0x13A5; break;
+ case 0xAB76: mapChar = 0x13A6; break;
+ case 0xAB77: mapChar = 0x13A7; break;
+ case 0xAB78: mapChar = 0x13A8; break;
+ case 0xAB79: mapChar = 0x13A9; break;
+ case 0xAB7A: mapChar = 0x13AA; break;
+ case 0xAB7B: mapChar = 0x13AB; break;
+ case 0xAB7C: mapChar = 0x13AC; break;
+ case 0xAB7D: mapChar = 0x13AD; break;
+ case 0xAB7E: mapChar = 0x13AE; break;
+ case 0xAB7F: mapChar = 0x13AF; break;
+ case 0xAB80: mapChar = 0x13B0; break;
+ case 0xAB81: mapChar = 0x13B1; break;
+ case 0xAB82: mapChar = 0x13B2; break;
+ case 0xAB83: mapChar = 0x13B3; break;
+ case 0xAB84: mapChar = 0x13B4; break;
+ case 0xAB85: mapChar = 0x13B5; break;
+ case 0xAB86: mapChar = 0x13B6; break;
+ case 0xAB87: mapChar = 0x13B7; break;
+ case 0xAB88: mapChar = 0x13B8; break;
+ case 0xAB89: mapChar = 0x13B9; break;
+ case 0xAB8A: mapChar = 0x13BA; break;
+ case 0xAB8B: mapChar = 0x13BB; break;
+ case 0xAB8C: mapChar = 0x13BC; break;
+ case 0xAB8D: mapChar = 0x13BD; break;
+ case 0xAB8E: mapChar = 0x13BE; break;
+ case 0xAB8F: mapChar = 0x13BF; break;
+ case 0xAB90: mapChar = 0x13C0; break;
+ case 0xAB91: mapChar = 0x13C1; break;
+ case 0xAB92: mapChar = 0x13C2; break;
+ case 0xAB93: mapChar = 0x13C3; break;
+ case 0xAB94: mapChar = 0x13C4; break;
+ case 0xAB95: mapChar = 0x13C5; break;
+ case 0xAB96: mapChar = 0x13C6; break;
+ case 0xAB97: mapChar = 0x13C7; break;
+ case 0xAB98: mapChar = 0x13C8; break;
+ case 0xAB99: mapChar = 0x13C9; break;
+ case 0xAB9A: mapChar = 0x13CA; break;
+ case 0xAB9B: mapChar = 0x13CB; break;
+ case 0xAB9C: mapChar = 0x13CC; break;
+ case 0xAB9D: mapChar = 0x13CD; break;
+ case 0xAB9E: mapChar = 0x13CE; break;
+ case 0xAB9F: mapChar = 0x13CF; break;
+ case 0xABA0: mapChar = 0x13D0; break;
+ case 0xABA1: mapChar = 0x13D1; break;
+ case 0xABA2: mapChar = 0x13D2; break;
+ case 0xABA3: mapChar = 0x13D3; break;
+ case 0xABA4: mapChar = 0x13D4; break;
+ case 0xABA5: mapChar = 0x13D5; break;
+ case 0xABA6: mapChar = 0x13D6; break;
+ case 0xABA7: mapChar = 0x13D7; break;
+ case 0xABA8: mapChar = 0x13D8; break;
+ case 0xABA9: mapChar = 0x13D9; break;
+ case 0xABAA: mapChar = 0x13DA; break;
+ case 0xABAB: mapChar = 0x13DB; break;
+ case 0xABAC: mapChar = 0x13DC; break;
+ case 0xABAD: mapChar = 0x13DD; break;
+ case 0xABAE: mapChar = 0x13DE; break;
+ case 0xABAF: mapChar = 0x13DF; break;
+ case 0xABB0: mapChar = 0x13E0; break;
+ case 0xABB1: mapChar = 0x13E1; break;
+ case 0xABB2: mapChar = 0x13E2; break;
+ case 0xABB3: mapChar = 0x13E3; break;
+ case 0xABB4: mapChar = 0x13E4; break;
+ case 0xABB5: mapChar = 0x13E5; break;
+ case 0xABB6: mapChar = 0x13E6; break;
+ case 0xABB7: mapChar = 0x13E7; break;
+ case 0xABB8: mapChar = 0x13E8; break;
+ case 0xABB9: mapChar = 0x13E9; break;
+ case 0xABBA: mapChar = 0x13EA; break;
+ case 0xABBB: mapChar = 0x13EB; break;
+ case 0xABBC: mapChar = 0x13EC; break;
+ case 0xABBD: mapChar = 0x13ED; break;
+ case 0xABBE: mapChar = 0x13EE; break;
+ case 0xABBF: mapChar = 0x13EF; break;
// ch must have a 1:M case mapping, but we
// can't handle it here. Return ch.
// since mapChar is already set, no need
@@ -420,6 +576,8 @@
switch (ch) {
case 0x0BF1: retval = 100; break; // TAMIL NUMBER ONE HUNDRED
case 0x0BF2: retval = 1000; break; // TAMIL NUMBER ONE THOUSAND
+ case 0x0D71: retval = 100; break; // MALAYALAM NUMBER ONE HUNDRED
+ case 0x0D72: retval = 1000; break; // MALAYALAM NUMBER ONE THOUSAND
case 0x1375: retval = 40; break; // ETHIOPIC NUMBER FORTY
case 0x1376: retval = 50; break; // ETHIOPIC NUMBER FIFTY
case 0x1377: retval = 60; break; // ETHIOPIC NUMBER SIXTY
@@ -440,14 +598,15 @@
case 0x2180: retval = 1000; break; // ROMAN NUMERAL ONE THOUSAND C D
case 0x2181: retval = 5000; break; // ROMAN NUMERAL FIVE THOUSAND
case 0x2182: retval = 10000; break; // ROMAN NUMERAL TEN THOUSAND
-
- case 0x324B: retval = 40; break;
- case 0x324C: retval = 50; break;
- case 0x324D: retval = 60; break;
- case 0x324E: retval = 70; break;
- case 0x324F: retval = 80; break;
- case 0x325C: retval = 32; break;
-
+ case 0x2186: retval = 50; break; // ROMAN NUMERAL FIFTY EARLY FORM
+ case 0x2187: retval = 50000; break; // ROMAN NUMERAL FIFTY THOUSAND
+ case 0x2188: retval = 100000; break; // ROMAN NUMERAL ONE HUNDRED THOUSAND
+ case 0x324B: retval = 40; break; // CIRCLED NUMBER FORTY ON BLACK SQUARE
+ case 0x324C: retval = 50; break; // CIRCLED NUMBER FIFTY ON BLACK SQUARE
+ case 0x324D: retval = 60; break; // CIRCLED NUMBER SIXTY ON BLACK SQUARE
+ case 0x324E: retval = 70; break; // CIRCLED NUMBER SEVENTY ON BLACK SQUARE
+ case 0x324F: retval = 80; break; // CIRCLED NUMBER EIGHTY ON BLACK SQUARE
+ case 0x325C: retval = 32; break; // CIRCLED NUMBER THIRTY TWO
case 0x325D: retval = 33; break; // CIRCLED NUMBER THIRTY THREE
case 0x325E: retval = 34; break; // CIRCLED NUMBER THIRTY FOUR
case 0x325F: retval = 35; break; // CIRCLED NUMBER THIRTY FIVE
@@ -466,13 +625,6 @@
case 0x32BD: retval = 48; break; // CIRCLED NUMBER FORTY EIGHT
case 0x32BE: retval = 49; break; // CIRCLED NUMBER FORTY NINE
case 0x32BF: retval = 50; break; // CIRCLED NUMBER FIFTY
-
- case 0x0D71: retval = 100; break; // MALAYALAM NUMBER ONE HUNDRED
- case 0x0D72: retval = 1000; break; // MALAYALAM NUMBER ONE THOUSAND
- case 0x2186: retval = 50; break; // ROMAN NUMERAL FIFTY EARLY FORM
- case 0x2187: retval = 50000; break; // ROMAN NUMERAL FIFTY THOUSAND
- case 0x2188: retval = 100000; break; // ROMAN NUMERAL ONE HUNDRED THOUSAND
-
default: retval = -2; break;
}
break;
@@ -553,70 +705,149 @@
}
else {
switch(ch) {
- // map overflow characters
- case 0x00B5 : mapChar = 0x039C; break;
- case 0x017F : mapChar = 0x0053; break;
- case 0x1FBE : mapChar = 0x0399; break;
-
- case 0x023F : mapChar = 0x2C7E; break;
- case 0x0240 : mapChar = 0x2C7F; break;
- case 0x0250 : mapChar = 0x2C6F; break;
- case 0x0251 : mapChar = 0x2C6D; break;
- case 0x0252 : mapChar = 0x2C70; break;
- case 0x025C : mapChar = 0xA7AB; break;
- case 0x0261 : mapChar = 0xA7AC; break;
- case 0x0265 : mapChar = 0xA78D; break;
- case 0x0266 : mapChar = 0xA7AA; break;
- case 0x026B : mapChar = 0x2C62; break;
- case 0x026C : mapChar = 0xA7AD; break;
- case 0x0271 : mapChar = 0x2C6E; break;
- case 0x027D : mapChar = 0x2C64; break;
- case 0x0287 : mapChar = 0xA7B1; break;
- case 0x029E : mapChar = 0xA7B0; break;
- case 0x1D79 : mapChar = 0xA77D; break;
- case 0x1D7D : mapChar = 0x2C63; break;
- case 0x2C65 : mapChar = 0x023A; break;
- case 0x2C66 : mapChar = 0x023E; break;
- case 0x2D00 : mapChar = 0x10A0; break;
- case 0x2D01 : mapChar = 0x10A1; break;
- case 0x2D02 : mapChar = 0x10A2; break;
- case 0x2D03 : mapChar = 0x10A3; break;
- case 0x2D04 : mapChar = 0x10A4; break;
- case 0x2D05 : mapChar = 0x10A5; break;
- case 0x2D06 : mapChar = 0x10A6; break;
- case 0x2D07 : mapChar = 0x10A7; break;
- case 0x2D08 : mapChar = 0x10A8; break;
- case 0x2D09 : mapChar = 0x10A9; break;
- case 0x2D0A : mapChar = 0x10AA; break;
- case 0x2D0B : mapChar = 0x10AB; break;
- case 0x2D0C : mapChar = 0x10AC; break;
- case 0x2D0D : mapChar = 0x10AD; break;
- case 0x2D0E : mapChar = 0x10AE; break;
- case 0x2D0F : mapChar = 0x10AF; break;
- case 0x2D10 : mapChar = 0x10B0; break;
- case 0x2D11 : mapChar = 0x10B1; break;
- case 0x2D12 : mapChar = 0x10B2; break;
- case 0x2D13 : mapChar = 0x10B3; break;
- case 0x2D14 : mapChar = 0x10B4; break;
- case 0x2D15 : mapChar = 0x10B5; break;
- case 0x2D16 : mapChar = 0x10B6; break;
- case 0x2D17 : mapChar = 0x10B7; break;
- case 0x2D18 : mapChar = 0x10B8; break;
- case 0x2D19 : mapChar = 0x10B9; break;
- case 0x2D1A : mapChar = 0x10BA; break;
- case 0x2D1B : mapChar = 0x10BB; break;
- case 0x2D1C : mapChar = 0x10BC; break;
- case 0x2D1D : mapChar = 0x10BD; break;
- case 0x2D1E : mapChar = 0x10BE; break;
- case 0x2D1F : mapChar = 0x10BF; break;
- case 0x2D20 : mapChar = 0x10C0; break;
- case 0x2D21 : mapChar = 0x10C1; break;
- case 0x2D22 : mapChar = 0x10C2; break;
- case 0x2D23 : mapChar = 0x10C3; break;
- case 0x2D24 : mapChar = 0x10C4; break;
- case 0x2D25 : mapChar = 0x10C5; break;
- case 0x2D27 : mapChar = 0x10C7; break;
- case 0x2D2D : mapChar = 0x10CD; break;
+ case 0x017F: mapChar = 0x0053; break;
+ case 0x023F: mapChar = 0x2C7E; break;
+ case 0x0240: mapChar = 0x2C7F; break;
+ case 0x0250: mapChar = 0x2C6F; break;
+ case 0x0251: mapChar = 0x2C6D; break;
+ case 0x0252: mapChar = 0x2C70; break;
+ case 0x025C: mapChar = 0xA7AB; break;
+ case 0x0261: mapChar = 0xA7AC; break;
+ case 0x0265: mapChar = 0xA78D; break;
+ case 0x0266: mapChar = 0xA7AA; break;
+ case 0x026B: mapChar = 0x2C62; break;
+ case 0x026C: mapChar = 0xA7AD; break;
+ case 0x0271: mapChar = 0x2C6E; break;
+ case 0x027D: mapChar = 0x2C64; break;
+ case 0x0287: mapChar = 0xA7B1; break;
+ case 0x029D: mapChar = 0xA7B2; break;
+ case 0x029E: mapChar = 0xA7B0; break;
+ case 0x1D79: mapChar = 0xA77D; break;
+ case 0x1D7D: mapChar = 0x2C63; break;
+ case 0x1FBE: mapChar = 0x0399; break;
+ case 0x2C65: mapChar = 0x023A; break;
+ case 0x2C66: mapChar = 0x023E; break;
+ case 0x2D00: mapChar = 0x10A0; break;
+ case 0x2D01: mapChar = 0x10A1; break;
+ case 0x2D02: mapChar = 0x10A2; break;
+ case 0x2D03: mapChar = 0x10A3; break;
+ case 0x2D04: mapChar = 0x10A4; break;
+ case 0x2D05: mapChar = 0x10A5; break;
+ case 0x2D06: mapChar = 0x10A6; break;
+ case 0x2D07: mapChar = 0x10A7; break;
+ case 0x2D08: mapChar = 0x10A8; break;
+ case 0x2D09: mapChar = 0x10A9; break;
+ case 0x2D0A: mapChar = 0x10AA; break;
+ case 0x2D0B: mapChar = 0x10AB; break;
+ case 0x2D0C: mapChar = 0x10AC; break;
+ case 0x2D0D: mapChar = 0x10AD; break;
+ case 0x2D0E: mapChar = 0x10AE; break;
+ case 0x2D0F: mapChar = 0x10AF; break;
+ case 0x2D10: mapChar = 0x10B0; break;
+ case 0x2D11: mapChar = 0x10B1; break;
+ case 0x2D12: mapChar = 0x10B2; break;
+ case 0x2D13: mapChar = 0x10B3; break;
+ case 0x2D14: mapChar = 0x10B4; break;
+ case 0x2D15: mapChar = 0x10B5; break;
+ case 0x2D16: mapChar = 0x10B6; break;
+ case 0x2D17: mapChar = 0x10B7; break;
+ case 0x2D18: mapChar = 0x10B8; break;
+ case 0x2D19: mapChar = 0x10B9; break;
+ case 0x2D1A: mapChar = 0x10BA; break;
+ case 0x2D1B: mapChar = 0x10BB; break;
+ case 0x2D1C: mapChar = 0x10BC; break;
+ case 0x2D1D: mapChar = 0x10BD; break;
+ case 0x2D1E: mapChar = 0x10BE; break;
+ case 0x2D1F: mapChar = 0x10BF; break;
+ case 0x2D20: mapChar = 0x10C0; break;
+ case 0x2D21: mapChar = 0x10C1; break;
+ case 0x2D22: mapChar = 0x10C2; break;
+ case 0x2D23: mapChar = 0x10C3; break;
+ case 0x2D24: mapChar = 0x10C4; break;
+ case 0x2D25: mapChar = 0x10C5; break;
+ case 0x2D27: mapChar = 0x10C7; break;
+ case 0x2D2D: mapChar = 0x10CD; break;
+ case 0xAB53: mapChar = 0xA7B3; break;
+ case 0xAB70: mapChar = 0x13A0; break;
+ case 0xAB71: mapChar = 0x13A1; break;
+ case 0xAB72: mapChar = 0x13A2; break;
+ case 0xAB73: mapChar = 0x13A3; break;
+ case 0xAB74: mapChar = 0x13A4; break;
+ case 0xAB75: mapChar = 0x13A5; break;
+ case 0xAB76: mapChar = 0x13A6; break;
+ case 0xAB77: mapChar = 0x13A7; break;
+ case 0xAB78: mapChar = 0x13A8; break;
+ case 0xAB79: mapChar = 0x13A9; break;
+ case 0xAB7A: mapChar = 0x13AA; break;
+ case 0xAB7B: mapChar = 0x13AB; break;
+ case 0xAB7C: mapChar = 0x13AC; break;
+ case 0xAB7D: mapChar = 0x13AD; break;
+ case 0xAB7E: mapChar = 0x13AE; break;
+ case 0xAB7F: mapChar = 0x13AF; break;
+ case 0xAB80: mapChar = 0x13B0; break;
+ case 0xAB81: mapChar = 0x13B1; break;
+ case 0xAB82: mapChar = 0x13B2; break;
+ case 0xAB83: mapChar = 0x13B3; break;
+ case 0xAB84: mapChar = 0x13B4; break;
+ case 0xAB85: mapChar = 0x13B5; break;
+ case 0xAB86: mapChar = 0x13B6; break;
+ case 0xAB87: mapChar = 0x13B7; break;
+ case 0xAB88: mapChar = 0x13B8; break;
+ case 0xAB89: mapChar = 0x13B9; break;
+ case 0xAB8A: mapChar = 0x13BA; break;
+ case 0xAB8B: mapChar = 0x13BB; break;
+ case 0xAB8C: mapChar = 0x13BC; break;
+ case 0xAB8D: mapChar = 0x13BD; break;
+ case 0xAB8E: mapChar = 0x13BE; break;
+ case 0xAB8F: mapChar = 0x13BF; break;
+ case 0xAB90: mapChar = 0x13C0; break;
+ case 0xAB91: mapChar = 0x13C1; break;
+ case 0xAB92: mapChar = 0x13C2; break;
+ case 0xAB93: mapChar = 0x13C3; break;
+ case 0xAB94: mapChar = 0x13C4; break;
+ case 0xAB95: mapChar = 0x13C5; break;
+ case 0xAB96: mapChar = 0x13C6; break;
+ case 0xAB97: mapChar = 0x13C7; break;
+ case 0xAB98: mapChar = 0x13C8; break;
+ case 0xAB99: mapChar = 0x13C9; break;
+ case 0xAB9A: mapChar = 0x13CA; break;
+ case 0xAB9B: mapChar = 0x13CB; break;
+ case 0xAB9C: mapChar = 0x13CC; break;
+ case 0xAB9D: mapChar = 0x13CD; break;
+ case 0xAB9E: mapChar = 0x13CE; break;
+ case 0xAB9F: mapChar = 0x13CF; break;
+ case 0xABA0: mapChar = 0x13D0; break;
+ case 0xABA1: mapChar = 0x13D1; break;
+ case 0xABA2: mapChar = 0x13D2; break;
+ case 0xABA3: mapChar = 0x13D3; break;
+ case 0xABA4: mapChar = 0x13D4; break;
+ case 0xABA5: mapChar = 0x13D5; break;
+ case 0xABA6: mapChar = 0x13D6; break;
+ case 0xABA7: mapChar = 0x13D7; break;
+ case 0xABA8: mapChar = 0x13D8; break;
+ case 0xABA9: mapChar = 0x13D9; break;
+ case 0xABAA: mapChar = 0x13DA; break;
+ case 0xABAB: mapChar = 0x13DB; break;
+ case 0xABAC: mapChar = 0x13DC; break;
+ case 0xABAD: mapChar = 0x13DD; break;
+ case 0xABAE: mapChar = 0x13DE; break;
+ case 0xABAF: mapChar = 0x13DF; break;
+ case 0xABB0: mapChar = 0x13E0; break;
+ case 0xABB1: mapChar = 0x13E1; break;
+ case 0xABB2: mapChar = 0x13E2; break;
+ case 0xABB3: mapChar = 0x13E3; break;
+ case 0xABB4: mapChar = 0x13E4; break;
+ case 0xABB5: mapChar = 0x13E5; break;
+ case 0xABB6: mapChar = 0x13E6; break;
+ case 0xABB7: mapChar = 0x13E7; break;
+ case 0xABB8: mapChar = 0x13E8; break;
+ case 0xABB9: mapChar = 0x13E9; break;
+ case 0xABBA: mapChar = 0x13EA; break;
+ case 0xABBB: mapChar = 0x13EB; break;
+ case 0xABBC: mapChar = 0x13EC; break;
+ case 0xABBD: mapChar = 0x13ED; break;
+ case 0xABBE: mapChar = 0x13EE; break;
+ case 0xABBF: mapChar = 0x13EF; break;
default : mapChar = Character.ERROR; break;
}
}
--- a/jdk/make/data/characterdata/CharacterData01.java.template Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/characterdata/CharacterData01.java.template Tue Oct 20 08:24:37 2015 -0700
@@ -243,36 +243,35 @@
case 0x10131: retval = 70000; break; // AEGEAN NUMBER SEVENTY THOUSAND
case 0x10132: retval = 80000; break; // AEGEAN NUMBER EIGHTY THOUSAND
case 0x10133: retval = 90000; break; // AEGEAN NUMBER NINETY THOUSAND
- case 0x10323: retval = 50; break; // OLD ITALIC NUMERAL FIFTY
- case 0x10144: retval = 50; break; // ACROPHONIC ATTIC FIFTY
- case 0x10145: retval = 500; break; // ACROPHONIC ATTIC FIVE HUNDRED
- case 0x10146: retval = 5000; break; // ACROPHONIC ATTIC FIVE THOUSAND
- case 0x10147: retval = 50000; break; // ACROPHONIC ATTIC FIFTY THOUSAND
- case 0x1014A: retval = 50; break; // ACROPHONIC ATTIC FIFTY TALENTS
- case 0x1014B: retval = 100; break; // ACROPHONIC ATTIC ONE HUNDRED TALENTS
- case 0x1014C: retval = 500; break; // ACROPHONIC ATTIC FIVE HUNDRED TALENTS
- case 0x1014D: retval = 1000; break; // ACROPHONIC ATTIC ONE THOUSAND TALENTS
- case 0x1014E: retval = 5000; break; // ACROPHONIC ATTIC FIVE THOUSAND TALENTS
- case 0x10151: retval = 50; break; // ACROPHONIC ATTIC FIFTY STATERS
- case 0x10152: retval = 100; break; // ACROPHONIC ATTIC ONE HUNDRED STATERS
- case 0x10153: retval = 500; break; // ACROPHONIC ATTIC FIVE HUNDRED STATERS
- case 0x10154: retval = 1000; break; // ACROPHONIC ATTIC ONE THOUSAND STATERS
- case 0x10155: retval = 10000; break; // ACROPHONIC ATTIC TEN THOUSAND STATERS
- case 0x10156: retval = 50000; break; // ACROPHONIC ATTIC FIFTY THOUSAND STATERS
- case 0x10166: retval = 50; break; // ACROPHONIC TROEZENIAN FIFTY
- case 0x10167: retval = 50; break; // ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM
- case 0x10168: retval = 50; break; // ACROPHONIC HERMIONIAN FIFTY
- case 0x10169: retval = 50; break; // ACROPHONIC THESPIAN FIFTY
- case 0x1016A: retval = 100; break; // ACROPHONIC THESPIAN ONE HUNDRED
- case 0x1016B: retval = 300; break; // ACROPHONIC THESPIAN THREE HUNDRED
- case 0x1016C: retval = 500; break; // ACROPHONIC EPIDAUREAN FIVE HUNDRED
- case 0x1016D: retval = 500; break; // ACROPHONIC TROEZENIAN FIVE HUNDRED
- case 0x1016E: retval = 500; break; // ACROPHONIC THESPIAN FIVE HUNDRED
- case 0x1016F: retval = 500; break; // ACROPHONIC CARYSTIAN FIVE HUNDRED
- case 0x10170: retval = 500; break; // ACROPHONIC NAXIAN FIVE HUNDRED
- case 0x10171: retval = 1000; break; // ACROPHONIC THESPIAN ONE THOUSAND
- case 0x10172: retval = 5000; break; // ACROPHONIC THESPIAN FIVE THOUSAND
- case 0x10174: retval = 50; break; // ACROPHONIC STRATIAN FIFTY MNAS
+ case 0x10144: retval = 50; break; // GREEK ACROPHONIC ATTIC FIFTY
+ case 0x10145: retval = 500; break; // GREEK ACROPHONIC ATTIC FIVE HUNDRED
+ case 0x10146: retval = 5000; break; // GREEK ACROPHONIC ATTIC FIVE THOUSAND
+ case 0x10147: retval = 50000; break; // GREEK ACROPHONIC ATTIC FIFTY THOUSAND
+ case 0x1014A: retval = 50; break; // GREEK ACROPHONIC ATTIC FIFTY TALENTS
+ case 0x1014B: retval = 100; break; // GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS
+ case 0x1014C: retval = 500; break; // GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS
+ case 0x1014D: retval = 1000; break; // GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS
+ case 0x1014E: retval = 5000; break; // GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS
+ case 0x10151: retval = 50; break; // GREEK ACROPHONIC ATTIC FIFTY STATERS
+ case 0x10152: retval = 100; break; // GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS
+ case 0x10153: retval = 500; break; // GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS
+ case 0x10154: retval = 1000; break; // GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS
+ case 0x10155: retval = 10000; break; // GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS
+ case 0x10156: retval = 50000; break; // GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS
+ case 0x10166: retval = 50; break; // GREEK ACROPHONIC TROEZENIAN FIFTY
+ case 0x10167: retval = 50; break; // GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM
+ case 0x10168: retval = 50; break; // GREEK ACROPHONIC HERMIONIAN FIFTY
+ case 0x10169: retval = 50; break; // GREEK ACROPHONIC THESPIAN FIFTY
+ case 0x1016A: retval = 100; break; // GREEK ACROPHONIC THESPIAN ONE HUNDRED
+ case 0x1016B: retval = 300; break; // GREEK ACROPHONIC THESPIAN THREE HUNDRED
+ case 0x1016C: retval = 500; break; // GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED
+ case 0x1016D: retval = 500; break; // GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED
+ case 0x1016E: retval = 500; break; // GREEK ACROPHONIC THESPIAN FIVE HUNDRED
+ case 0x1016F: retval = 500; break; // GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED
+ case 0x10170: retval = 500; break; // GREEK ACROPHONIC NAXIAN FIVE HUNDRED
+ case 0x10171: retval = 1000; break; // GREEK ACROPHONIC THESPIAN ONE THOUSAND
+ case 0x10172: retval = 5000; break; // GREEK ACROPHONIC THESPIAN FIVE THOUSAND
+ case 0x10174: retval = 50; break; // GREEK ACROPHONIC STRATIAN FIFTY MNAS
case 0x102ED: retval = 40; break; // COPTIC EPACT NUMBER FORTY
case 0x102EE: retval = 50; break; // COPTIC EPACT NUMBER FIFTY
case 0x102EF: retval = 60; break; // COPTIC EPACT NUMBER SIXTY
@@ -288,6 +287,7 @@
case 0x102F9: retval = 700; break; // COPTIC EPACT NUMBER SEVEN HUNDRED
case 0x102FA: retval = 800; break; // COPTIC EPACT NUMBER EIGHT HUNDRED
case 0x102FB: retval = 900; break; // COPTIC EPACT NUMBER NINE HUNDRED
+ case 0x10323: retval = 50; break; // OLD ITALIC NUMERAL FIFTY
case 0x10341: retval = 90; break; // GOTHIC LETTER NINETY
case 0x1034A: retval = 900; break; // GOTHIC LETTER NINE HUNDRED
case 0x103D5: retval = 100; break; // OLD PERSIAN NUMBER HUNDRED
@@ -295,7 +295,48 @@
case 0x1085E: retval = 1000; break; // IMPERIAL ARAMAIC NUMBER ONE THOUSAND
case 0x1085F: retval = 10000; break; // IMPERIAL ARAMAIC NUMBER TEN THOUSAND
case 0x108AF: retval = 100; break; // NABATAEAN NUMBER ONE HUNDRED
+ case 0x108FF: retval = 100; break; // HATRAN NUMBER ONE HUNDRED
case 0x10919: retval = 100; break; // PHOENICIAN NUMBER ONE HUNDRED
+ case 0x109CC: retval = 40; break; // MEROITIC CURSIVE NUMBER FORTY
+ case 0x109CD: retval = 50; break; // MEROITIC CURSIVE NUMBER FIFTY
+ case 0x109CE: retval = 60; break; // MEROITIC CURSIVE NUMBER SIXTY
+ case 0x109CF: retval = 70; break; // MEROITIC CURSIVE NUMBER SEVENTY
+ case 0x109D2: retval = 100; break; // MEROITIC CURSIVE NUMBER ONE HUNDRED
+ case 0x109D3: retval = 200; break; // MEROITIC CURSIVE NUMBER TWO HUNDRED
+ case 0x109D4: retval = 300; break; // MEROITIC CURSIVE NUMBER THREE HUNDRED
+ case 0x109D5: retval = 400; break; // MEROITIC CURSIVE NUMBER FOUR HUNDRED
+ case 0x109D6: retval = 500; break; // MEROITIC CURSIVE NUMBER FIVE HUNDRED
+ case 0x109D7: retval = 600; break; // MEROITIC CURSIVE NUMBER SIX HUNDRED
+ case 0x109D8: retval = 700; break; // MEROITIC CURSIVE NUMBER SEVEN HUNDRED
+ case 0x109D9: retval = 800; break; // MEROITIC CURSIVE NUMBER EIGHT HUNDRED
+ case 0x109DA: retval = 900; break; // MEROITIC CURSIVE NUMBER NINE HUNDRED
+ case 0x109DB: retval = 1000; break; // MEROITIC CURSIVE NUMBER ONE THOUSAND
+ case 0x109DC: retval = 2000; break; // MEROITIC CURSIVE NUMBER TWO THOUSAND
+ case 0x109DD: retval = 3000; break; // MEROITIC CURSIVE NUMBER THREE THOUSAND
+ case 0x109DE: retval = 4000; break; // MEROITIC CURSIVE NUMBER FOUR THOUSAND
+ case 0x109DF: retval = 5000; break; // MEROITIC CURSIVE NUMBER FIVE THOUSAND
+ case 0x109E0: retval = 6000; break; // MEROITIC CURSIVE NUMBER SIX THOUSAND
+ case 0x109E1: retval = 7000; break; // MEROITIC CURSIVE NUMBER SEVEN THOUSAND
+ case 0x109E2: retval = 8000; break; // MEROITIC CURSIVE NUMBER EIGHT THOUSAND
+ case 0x109E3: retval = 9000; break; // MEROITIC CURSIVE NUMBER NINE THOUSAND
+ case 0x109E4: retval = 10000; break; // MEROITIC CURSIVE NUMBER TEN THOUSAND
+ case 0x109E5: retval = 20000; break; // MEROITIC CURSIVE NUMBER TWENTY THOUSAND
+ case 0x109E6: retval = 30000; break; // MEROITIC CURSIVE NUMBER THIRTY THOUSAND
+ case 0x109E7: retval = 40000; break; // MEROITIC CURSIVE NUMBER FORTY THOUSAND
+ case 0x109E8: retval = 50000; break; // MEROITIC CURSIVE NUMBER FIFTY THOUSAND
+ case 0x109E9: retval = 60000; break; // MEROITIC CURSIVE NUMBER SIXTY THOUSAND
+ case 0x109EA: retval = 70000; break; // MEROITIC CURSIVE NUMBER SEVENTY THOUSAND
+ case 0x109EB: retval = 80000; break; // MEROITIC CURSIVE NUMBER EIGHTY THOUSAND
+ case 0x109EC: retval = 90000; break; // MEROITIC CURSIVE NUMBER NINETY THOUSAND
+ case 0x109ED: retval = 100000; break; // MEROITIC CURSIVE NUMBER ONE HUNDRED THOUSAND
+ case 0x109EE: retval = 200000; break; // MEROITIC CURSIVE NUMBER TWO HUNDRED THOUSAND
+ case 0x109EF: retval = 300000; break; // MEROITIC CURSIVE NUMBER THREE HUNDRED THOUSAND
+ case 0x109F0: retval = 400000; break; // MEROITIC CURSIVE NUMBER FOUR HUNDRED THOUSAND
+ case 0x109F1: retval = 500000; break; // MEROITIC CURSIVE NUMBER FIVE HUNDRED THOUSAND
+ case 0x109F2: retval = 600000; break; // MEROITIC CURSIVE NUMBER SIX HUNDRED THOUSAND
+ case 0x109F3: retval = 700000; break; // MEROITIC CURSIVE NUMBER SEVEN HUNDRED THOUSAND
+ case 0x109F4: retval = 800000; break; // MEROITIC CURSIVE NUMBER EIGHT HUNDRED THOUSAND
+ case 0x109F5: retval = 900000; break; // MEROITIC CURSIVE NUMBER NINE HUNDRED THOUSAND
case 0x10A46: retval = 100; break; // KHAROSHTHI NUMBER ONE HUNDRED
case 0x10A47: retval = 1000; break; // KHAROSHTHI NUMBER ONE THOUSAND
case 0x10A7E: retval = 50; break; // OLD SOUTH ARABIAN NUMBER FIFTY
@@ -305,6 +346,9 @@
case 0x10B7E: retval = 100; break; // INSCRIPTIONAL PAHLAVI NUMBER ONE HUNDRED
case 0x10B7F: retval = 1000; break; // INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
case 0x10BAF: retval = 100; break; // PSALTER PAHLAVI NUMBER ONE HUNDRED
+ case 0x10CFD: retval = 50; break; // OLD HUNGARIAN NUMBER FIFTY
+ case 0x10CFE: retval = 100; break; // OLD HUNGARIAN NUMBER ONE HUNDRED
+ case 0x10CFF: retval = 1000; break; // OLD HUNGARIAN NUMBER ONE THOUSAND
case 0x10E6C: retval = 40; break; // RUMI NUMBER FORTY
case 0x10E6D: retval = 50; break; // RUMI NUMBER FIFTY
case 0x10E6E: retval = 60; break; // RUMI NUMBER SIXTY
--- a/jdk/make/data/unicodedata/PropList.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/unicodedata/PropList.txt Tue Oct 20 08:24:37 2015 -0700
@@ -1,8 +1,8 @@
-# PropList-7.0.0.txt
-# Date: 2014-02-19, 15:51:26 GMT [MD]
+# PropList-8.0.0.txt
+# Date: 2015-05-16, 17:50:38 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2014 Unicode, Inc.
+# Copyright (c) 1991-2015 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
@@ -189,18 +189,22 @@
11141..11143 ; Terminal_Punctuation # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK
111C5..111C6 ; Terminal_Punctuation # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA
111CD ; Terminal_Punctuation # Po SHARADA SUTRA MARK
+111DE..111DF ; Terminal_Punctuation # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2
11238..1123C ; Terminal_Punctuation # Po [5] KHOJKI DANDA..KHOJKI DOUBLE SECTION MARK
+112A9 ; Terminal_Punctuation # Po MULTANI SECTION MARK
115C2..115C5 ; Terminal_Punctuation # Po [4] SIDDHAM DANDA..SIDDHAM SEPARATOR BAR
-115C9 ; Terminal_Punctuation # Po SIDDHAM END OF TEXT MARK
+115C9..115D7 ; Terminal_Punctuation # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; Terminal_Punctuation # Po [2] MODI DANDA..MODI DOUBLE DANDA
+1173C..1173E ; Terminal_Punctuation # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
12470..12474 ; Terminal_Punctuation # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
16A6E..16A6F ; Terminal_Punctuation # Po [2] MRO DANDA..MRO DOUBLE DANDA
16AF5 ; Terminal_Punctuation # Po BASSA VAH FULL STOP
16B37..16B39 ; Terminal_Punctuation # Po [3] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN CIM CHEEM
16B44 ; Terminal_Punctuation # Po PAHAWH HMONG SIGN XAUS
1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON
-# Total code points: 214
+# Total code points: 238
# ================================================
@@ -425,7 +429,7 @@
081B..0823 ; Other_Alphabetic # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
0825..0827 ; Other_Alphabetic # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
0829..082C ; Other_Alphabetic # Mn [4] SAMARITAN VOWEL SIGN LONG I..SAMARITAN VOWEL SIGN SUKUN
-08E4..08E9 ; Other_Alphabetic # Mn [6] ARABIC CURLY FATHA..ARABIC CURLY KASRATAN
+08E3..08E9 ; Other_Alphabetic # Mn [7] ARABIC TURNED DAMMA BELOW..ARABIC CURLY KASRATAN
08F0..0902 ; Other_Alphabetic # Mn [19] ARABIC OPEN FATHATAN..DEVANAGARI SIGN ANUSVARA
0903 ; Other_Alphabetic # Mc DEVANAGARI SIGN VISARGA
093A ; Other_Alphabetic # Mn DEVANAGARI VOWEL SIGN OE
@@ -560,8 +564,6 @@
1930..1931 ; Other_Alphabetic # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
1932 ; Other_Alphabetic # Mn LIMBU SMALL LETTER ANUSVARA
1933..1938 ; Other_Alphabetic # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
-19B0..19C0 ; Other_Alphabetic # Mc [17] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE VOWEL SIGN IY
-19C8..19C9 ; Other_Alphabetic # Mc [2] NEW TAI LUE TONE MARK-1..NEW TAI LUE TONE MARK-2
1A17..1A18 ; Other_Alphabetic # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
1A19..1A1A ; Other_Alphabetic # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
1A1B ; Other_Alphabetic # Mn BUGINESE VOWEL SIGN AE
@@ -605,7 +607,7 @@
24B6..24E9 ; Other_Alphabetic # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z
2DE0..2DFF ; Other_Alphabetic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
A674..A67B ; Other_Alphabetic # Mn [8] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC LETTER OMEGA
-A69F ; Other_Alphabetic # Mn COMBINING CYRILLIC LETTER IOTIFIED E
+A69E..A69F ; Other_Alphabetic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
A823..A824 ; Other_Alphabetic # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
A825..A826 ; Other_Alphabetic # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
A827 ; Other_Alphabetic # Mc SYLOTI NAGRI VOWEL SIGN OO
@@ -672,7 +674,7 @@
112DF ; Other_Alphabetic # Mn KHUDAWADI SIGN ANUSVARA
112E0..112E2 ; Other_Alphabetic # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
112E3..112E8 ; Other_Alphabetic # Mn [6] KHUDAWADI VOWEL SIGN U..KHUDAWADI VOWEL SIGN AU
-11301 ; Other_Alphabetic # Mn GRANTHA SIGN CANDRABINDU
+11300..11301 ; Other_Alphabetic # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
11302..11303 ; Other_Alphabetic # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
1133E..1133F ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I
11340 ; Other_Alphabetic # Mn GRANTHA VOWEL SIGN II
@@ -693,6 +695,7 @@
115B8..115BB ; Other_Alphabetic # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
115BC..115BD ; Other_Alphabetic # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
115BE ; Other_Alphabetic # Mc SIDDHAM SIGN VISARGA
+115DC..115DD ; Other_Alphabetic # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
11630..11632 ; Other_Alphabetic # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
11633..1163A ; Other_Alphabetic # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
1163B..1163C ; Other_Alphabetic # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
@@ -704,6 +707,11 @@
116AD ; Other_Alphabetic # Mn TAKRI VOWEL SIGN AA
116AE..116AF ; Other_Alphabetic # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
116B0..116B5 ; Other_Alphabetic # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
+1171D..1171F ; Other_Alphabetic # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11720..11721 ; Other_Alphabetic # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
+11722..11725 ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11726 ; Other_Alphabetic # Mc AHOM VOWEL SIGN E
+11727..1172A ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN AW..AHOM VOWEL SIGN AM
16B30..16B36 ; Other_Alphabetic # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16F51..16F7E ; Other_Alphabetic # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG
1BC9E ; Other_Alphabetic # Mn DUPLOYAN DOUBLE MARK
@@ -720,15 +728,16 @@
3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
3400..4DB5 ; Ideographic # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FCC ; Ideographic # Lo [20941] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FCC
+4E00..9FD5 ; Ideographic # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
20000..2A6D6 ; Ideographic # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Ideographic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-# Total code points: 75633
+# Total code points: 81404
# ================================================
@@ -773,7 +782,7 @@
07EB..07F3 ; Diacritic # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
07F4..07F5 ; Diacritic # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
0818..0819 ; Diacritic # Mn [2] SAMARITAN MARK OCCLUSION..SAMARITAN MARK DAGESH
-08E4..08FE ; Diacritic # Mn [27] ARABIC CURLY FATHA..ARABIC DAMMA WITH DOT
+08E3..08FE ; Diacritic # Mn [28] ARABIC TURNED DAMMA BELOW..ARABIC DAMMA WITH DOT
093C ; Diacritic # Mn DEVANAGARI SIGN NUKTA
094D ; Diacritic # Mn DEVANAGARI SIGN VIRAMA
0951..0954 ; Diacritic # Mn [4] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI ACUTE ACCENT
@@ -877,7 +886,7 @@
ABEC ; Diacritic # Mc MEETEI MAYEK LUM IYEK
ABED ; Diacritic # Mn MEETEI MAYEK APUN IYEK
FB1E ; Diacritic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
-FE20..FE2D ; Diacritic # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON BELOW
+FE20..FE2F ; Diacritic # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
FF3E ; Diacritic # Sk FULLWIDTH CIRCUMFLEX ACCENT
FF40 ; Diacritic # Sk FULLWIDTH GRAVE ACCENT
FF70 ; Diacritic # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
@@ -889,6 +898,7 @@
11133..11134 ; Diacritic # Mn [2] CHAKMA VIRAMA..CHAKMA MAAYYAA
11173 ; Diacritic # Mn MAHAJANI SIGN NUKTA
111C0 ; Diacritic # Mc SHARADA SIGN VIRAMA
+111CA..111CC ; Diacritic # Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK
11235 ; Diacritic # Mc KHOJKI SIGN VIRAMA
11236 ; Diacritic # Mn KHOJKI SIGN NUKTA
112E9..112EA ; Diacritic # Mn [2] KHUDAWADI SIGN NUKTA..KHUDAWADI SIGN VIRAMA
@@ -901,6 +911,7 @@
1163F ; Diacritic # Mn MODI SIGN VIRAMA
116B6 ; Diacritic # Mc TAKRI SIGN VIRAMA
116B7 ; Diacritic # Mn TAKRI SIGN NUKTA
+1172B ; Diacritic # Mn AHOM SIGN KILLER
16AF0..16AF4 ; Diacritic # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
@@ -911,7 +922,7 @@
1D1AA..1D1AD ; Diacritic # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
1E8D0..1E8D6 ; Diacritic # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
-# Total code points: 766
+# Total code points: 773
# ================================================
@@ -1053,7 +1064,7 @@
# ================================================
3400..4DB5 ; Unified_Ideograph # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FCC ; Unified_Ideograph # Lo [20941] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FCC
+4E00..9FD5 ; Unified_Ideograph # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
FA0E..FA0F ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
FA11 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA11
FA13..FA14 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
@@ -1064,8 +1075,9 @@
20000..2A6D6 ; Unified_Ideograph # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Unified_Ideograph # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Unified_Ideograph # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Unified_Ideograph # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
-# Total code points: 74617
+# Total code points: 80388
# ================================================
@@ -1094,9 +1106,9 @@
2329 ; Deprecated # Ps LEFT-POINTING ANGLE BRACKET
232A ; Deprecated # Pe RIGHT-POINTING ANGLE BRACKET
E0001 ; Deprecated # Cf LANGUAGE TAG
-E0020..E007F ; Deprecated # Cf [96] TAG SPACE..CANCEL TAG
+E007F ; Deprecated # Cf CANCEL TAG
-# Total code points: 111
+# Total code points: 16
# ================================================
@@ -1138,11 +1150,13 @@
0E40..0E44 ; Logical_Order_Exception # Lo [5] THAI CHARACTER SARA E..THAI CHARACTER SARA AI MAIMALAI
0EC0..0EC4 ; Logical_Order_Exception # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI
+19B5..19B7 ; Logical_Order_Exception # Lo [3] NEW TAI LUE VOWEL SIGN E..NEW TAI LUE VOWEL SIGN O
+19BA ; Logical_Order_Exception # Lo NEW TAI LUE VOWEL SIGN AY
AAB5..AAB6 ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O
AAB9 ; Logical_Order_Exception # Lo TAI VIET VOWEL UEA
AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET VOWEL AY
-# Total code points: 15
+# Total code points: 19
# ================================================
@@ -1213,18 +1227,22 @@
11141..11143 ; STerm # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK
111C5..111C6 ; STerm # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA
111CD ; STerm # Po SHARADA SUTRA MARK
+111DE..111DF ; STerm # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2
11238..11239 ; STerm # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA
1123B..1123C ; STerm # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK
+112A9 ; STerm # Po MULTANI SECTION MARK
115C2..115C3 ; STerm # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA
-115C9 ; STerm # Po SIDDHAM END OF TEXT MARK
+115C9..115D7 ; STerm # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; STerm # Po [2] MODI DANDA..MODI DOUBLE DANDA
+1173C..1173E ; STerm # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
16A6E..16A6F ; STerm # Po [2] MRO DANDA..MRO DOUBLE DANDA
16AF5 ; STerm # Po BASSA VAH FULL STOP
16B37..16B38 ; STerm # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB
16B44 ; STerm # Po PAHAWH HMONG SIGN XAUS
1BC9F ; STerm # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+1DA88 ; STerm # Po SIGNWRITING FULL STOP
-# Total code points: 99
+# Total code points: 120
# ================================================
@@ -1432,7 +1450,9 @@
2BBD..2BC8 ; Pattern_Syntax # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
2BC9 ; Pattern_Syntax # Cn <reserved-2BC9>
2BCA..2BD1 ; Pattern_Syntax # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN
-2BD2..2BFF ; Pattern_Syntax # Cn [46] <reserved-2BD2>..<reserved-2BFF>
+2BD2..2BEB ; Pattern_Syntax # Cn [26] <reserved-2BD2>..<reserved-2BEB>
+2BEC..2BEF ; Pattern_Syntax # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS
+2BF0..2BFF ; Pattern_Syntax # Cn [16] <reserved-2BF0>..<reserved-2BFF>
2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
2E02 ; Pattern_Syntax # Pi LEFT SUBSTITUTION BRACKET
2E03 ; Pattern_Syntax # Pf RIGHT SUBSTITUTION BRACKET
--- a/jdk/make/data/unicodedata/Scripts.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/unicodedata/Scripts.txt Tue Oct 20 08:24:37 2015 -0700
@@ -1,10 +1,16 @@
-# Scripts-7.0.0.txt
-# Date: 2014-05-15, 00:11:35 GMT [MD]
+# Scripts-8.0.0.txt
+# Date: 2015-03-11, 22:29:42 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2014 Unicode, Inc.
+# Copyright (c) 1991-2015 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
+# For more information, see:
+# UAX #24, Unicode Script Property: http://www.unicode.org/reports/tr24/
+# Especially the sections:
+# http://www.unicode.org/reports/tr24/#Assignment_Script_Values
+# http://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values
+#
# ================================================
@@ -89,7 +95,6 @@
061C ; Common # Cf ARABIC LETTER MARK
061F ; Common # Po ARABIC QUESTION MARK
0640 ; Common # Lm ARABIC TATWEEL
-0660..0669 ; Common # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
06DD ; Common # Cf ARABIC END OF AYAH
0964..0965 ; Common # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
0E3F ; Common # Sc THAI CURRENCY SYMBOL BAHT
@@ -148,7 +153,7 @@
208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS
208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS
-20A0..20BD ; Common # Sc [30] EURO-CURRENCY SIGN..RUBLE SIGN
+20A0..20BE ; Common # Sc [31] EURO-CURRENCY SIGN..LARI SIGN
2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
2102 ; Common # L& DOUBLE-STRUCK CAPITAL C
2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA
@@ -182,6 +187,7 @@
214F ; Common # So SYMBOL FOR SAMARITAN SOURCE
2150..215F ; Common # No [16] VULGAR FRACTION ONE SEVENTH..FRACTION NUMERATOR ONE
2189 ; Common # No VULGAR FRACTION ZERO THIRDS
+218A..218B ; Common # So [2] TURNED DIGIT TWO..TURNED DIGIT THREE
2190..2194 ; Common # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW
2195..2199 ; Common # So [5] UP DOWN ARROW..SOUTH WEST ARROW
219A..219B ; Common # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE
@@ -304,6 +310,7 @@
2B98..2BB9 ; Common # So [34] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX
2BBD..2BC8 ; Common # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
2BCA..2BD1 ; Common # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN
+2BEC..2BEF ; Common # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS
2E00..2E01 ; Common # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
2E02 ; Common # Pi LEFT SUBSTITUTION BRACKET
2E03 ; Common # Pf RIGHT SUBSTITUTION BRACKET
@@ -512,7 +519,7 @@
1D173..1D17A ; Common # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
1D183..1D184 ; Common # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN
1D18C..1D1A9 ; Common # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH
-1D1AE..1D1DD ; Common # So [48] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL PES SUBPUNCTIS
+1D1AE..1D1E8 ; Common # So [59] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KIEVAN FLAT SIGN
1D300..1D356 ; Common # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
1D360..1D371 ; Common # No [18] COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TENS DIGIT NINE
1D400..1D454 ; Common # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
@@ -571,16 +578,11 @@
1F210..1F23A ; Common # So [43] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-55B6
1F240..1F248 ; Common # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
1F250..1F251 ; Common # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
-1F300..1F32C ; Common # So [45] CYCLONE..WIND BLOWING FACE
-1F330..1F37D ; Common # So [78] CHESTNUT..FORK AND KNIFE WITH PLATE
-1F380..1F3CE ; Common # So [79] RIBBON..RACING CAR
-1F3D4..1F3F7 ; Common # So [36] SNOW CAPPED MOUNTAIN..LABEL
-1F400..1F4FE ; Common # So [255] RAT..PORTABLE STEREO
-1F500..1F54A ; Common # So [75] TWISTED RIGHTWARDS ARROWS..DOVE OF PEACE
-1F550..1F579 ; Common # So [42] CLOCK FACE ONE OCLOCK..JOYSTICK
+1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA
+1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
+1F400..1F579 ; Common # So [378] RAT..JOYSTICK
1F57B..1F5A3 ; Common # So [41] LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX
-1F5A5..1F642 ; Common # So [158] DESKTOP COMPUTER..SLIGHTLY SMILING FACE
-1F645..1F6CF ; Common # So [139] FACE WITH NO GOOD GESTURE..BED
+1F5A5..1F6D0 ; Common # So [300] DESKTOP COMPUTER..PLACE OF WORSHIP
1F6E0..1F6EC ; Common # So [13] HAMMER AND WRENCH..AIRPLANE ARRIVING
1F6F0..1F6F3 ; Common # So [4] SATELLITE..PASSENGER SHIP
1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE
@@ -590,10 +592,13 @@
1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
+1F910..1F918 ; Common # So [9] ZIPPER-MOUTH FACE..SIGN OF THE HORNS
+1F980..1F984 ; Common # So [5] CRAB..UNICORN FACE
+1F9C0 ; Common # So CHEESE WEDGE
E0001 ; Common # Cf LANGUAGE TAG
E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG
-# Total code points: 7129
+# Total code points: 7179
# ================================================
@@ -635,20 +640,21 @@
A770 ; Latin # Lm MODIFIER LETTER US
A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T
A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
+A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT
A790..A7AD ; Latin # L& [30] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER L WITH BELT
-A7B0..A7B1 ; Latin # L& [2] LATIN CAPITAL LETTER TURNED K..LATIN CAPITAL LETTER TURNED T
+A7B0..A7B7 ; Latin # L& [8] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER OMEGA
A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I
A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
A7FA ; Latin # L& LATIN LETTER SMALL CAPITAL TURNED M
A7FB..A7FF ; Latin # Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
AB30..AB5A ; Latin # L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
AB5C..AB5F ; Latin # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
-AB64 ; Latin # L& LATIN SMALL LETTER INVERTED ALPHA
+AB60..AB64 ; Latin # L& [5] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER INVERTED ALPHA
FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
-# Total code points: 1338
+# Total code points: 1349
# ================================================
@@ -731,9 +737,10 @@
A67F ; Cyrillic # Lm CYRILLIC PAYEROK
A680..A69B ; Cyrillic # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O
A69C..A69D ; Cyrillic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
-A69F ; Cyrillic # Mn COMBINING CYRILLIC LETTER IOTIFIED E
-
-# Total code points: 431
+A69E..A69F ; Cyrillic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
+FE2E..FE2F ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
+
+# Total code points: 434
# ================================================
@@ -788,6 +795,7 @@
0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW
+0660..0669 ; Arabic # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
066A..066D ; Arabic # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
066E..066F ; Arabic # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
0671..06D3 ; Arabic # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
@@ -806,8 +814,8 @@
06FD..06FE ; Arabic # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN
06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V
0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
-08A0..08B2 ; Arabic # Lo [19] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER ZAIN WITH INVERTED V ABOVE
-08E4..08FF ; Arabic # Mn [28] ARABIC CURLY FATHA..ARABIC MARK SIDEWAYS NOON GHUNNA
+08A0..08B4 ; Arabic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW
+08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
FBB2..FBC1 ; Arabic # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW
FBD3..FD3D ; Arabic # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
@@ -854,7 +862,7 @@
1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
-# Total code points: 1244
+# Total code points: 1257
# ================================================
@@ -902,8 +910,10 @@
A8F2..A8F7 ; Devanagari # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
A8F8..A8FA ; Devanagari # Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
A8FB ; Devanagari # Lo DEVANAGARI HEADSTROKE
-
-# Total code points: 152
+A8FC ; Devanagari # Po DEVANAGARI SIGN SIDDHAM
+A8FD ; Devanagari # Lo DEVANAGARI JAIN OM
+
+# Total code points: 154
# ================================================
@@ -987,8 +997,9 @@
0AE6..0AEF ; Gujarati # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
0AF0 ; Gujarati # Po GUJARATI ABBREVIATION SIGN
0AF1 ; Gujarati # Sc GUJARATI RUPEE SIGN
-
-# Total code points: 84
+0AF9 ; Gujarati # Lo GUJARATI LETTER ZHA
+
+# Total code points: 85
# ================================================
@@ -1064,14 +1075,14 @@
0C46..0C48 ; Telugu # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
0C4A..0C4D ; Telugu # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
0C55..0C56 ; Telugu # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
-0C58..0C59 ; Telugu # Lo [2] TELUGU LETTER TSA..TELUGU LETTER DZA
+0C58..0C5A ; Telugu # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
0C60..0C61 ; Telugu # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
0C62..0C63 ; Telugu # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
0C66..0C6F ; Telugu # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
0C78..0C7E ; Telugu # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR
0C7F ; Telugu # So TELUGU SIGN TUUMU
-# Total code points: 95
+# Total code points: 96
# ================================================
@@ -1115,14 +1126,14 @@
0D4D ; Malayalam # Mn MALAYALAM SIGN VIRAMA
0D4E ; Malayalam # Lo MALAYALAM LETTER DOT REPH
0D57 ; Malayalam # Mc MALAYALAM AU LENGTH MARK
-0D60..0D61 ; Malayalam # Lo [2] MALAYALAM LETTER VOCALIC RR..MALAYALAM LETTER VOCALIC LL
+0D5F..0D61 ; Malayalam # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL
0D62..0D63 ; Malayalam # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
0D66..0D6F ; Malayalam # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
0D70..0D75 ; Malayalam # No [6] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE QUARTERS
0D79 ; Malayalam # So MALAYALAM DATE MARK
0D7A..0D7F ; Malayalam # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
-# Total code points: 99
+# Total code points: 100
# ================================================
@@ -1358,9 +1369,11 @@
# ================================================
-13A0..13F4 ; Cherokee # Lo [85] CHEROKEE LETTER A..CHEROKEE LETTER YV
-
-# Total code points: 85
+13A0..13F5 ; Cherokee # L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV
+13F8..13FD ; Cherokee # L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
+AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
+
+# Total code points: 172
# ================================================
@@ -1472,15 +1485,16 @@
3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK
3400..4DB5 ; Han # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FCC ; Han # Lo [20941] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FCC
+4E00..9FD5 ; Han # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
20000..2A6D6 ; Han # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Han # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-# Total code points: 75963
+# Total code points: 81734
# ================================================
@@ -1680,9 +1694,7 @@
# ================================================
1980..19AB ; New_Tai_Lue # Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
-19B0..19C0 ; New_Tai_Lue # Mc [17] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE VOWEL SIGN IY
-19C1..19C7 ; New_Tai_Lue # Lo [7] NEW TAI LUE LETTER FINAL V..NEW TAI LUE LETTER FINAL B
-19C8..19C9 ; New_Tai_Lue # Mc [2] NEW TAI LUE TONE MARK-1..NEW TAI LUE TONE MARK-2
+19B0..19C9 ; New_Tai_Lue # Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
19D0..19D9 ; New_Tai_Lue # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
19DA ; New_Tai_Lue # No NEW TAI LUE THAM DIGIT ONE
19DE..19DF ; New_Tai_Lue # So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
@@ -1770,11 +1782,12 @@
# ================================================
-12000..12398 ; Cuneiform # Lo [921] CUNEIFORM SIGN A..CUNEIFORM SIGN UM TIMES ME
+12000..12399 ; Cuneiform # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U
12400..1246E ; Cuneiform # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
12470..12474 ; Cuneiform # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
-
-# Total code points: 1037
+12480..12543 ; Cuneiform # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
+
+# Total code points: 1234
# ================================================
@@ -2151,9 +2164,12 @@
# ================================================
109A0..109B7 ; Meroitic_Cursive # Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA
+109BC..109BD ; Meroitic_Cursive # No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
109BE..109BF ; Meroitic_Cursive # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
-
-# Total code points: 26
+109C0..109CF ; Meroitic_Cursive # No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
+109D2..109FF ; Meroitic_Cursive # No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
+
+# Total code points: 90
# ================================================
@@ -2180,12 +2196,16 @@
111B6..111BE ; Sharada # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
111BF..111C0 ; Sharada # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
111C1..111C4 ; Sharada # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM
-111C5..111C8 ; Sharada # Po [4] SHARADA DANDA..SHARADA SEPARATOR
+111C5..111C9 ; Sharada # Po [5] SHARADA DANDA..SHARADA SANDHI MARK
+111CA..111CC ; Sharada # Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK
111CD ; Sharada # Po SHARADA SUTRA MARK
111D0..111D9 ; Sharada # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE
111DA ; Sharada # Lo SHARADA EKAM
-
-# Total code points: 85
+111DB ; Sharada # Po SHARADA SIGN SIDDHAM
+111DC ; Sharada # Lo SHARADA HEADSTROKE
+111DD..111DF ; Sharada # Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
+
+# Total code points: 94
# ================================================
@@ -2243,7 +2263,7 @@
# ================================================
-11301 ; Grantha # Mn GRANTHA SIGN CANDRABINDU
+11300..11301 ; Grantha # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
11302..11303 ; Grantha # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
11305..1130C ; Grantha # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
1130F..11310 ; Grantha # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI
@@ -2258,13 +2278,14 @@
11341..11344 ; Grantha # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
11347..11348 ; Grantha # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
1134B..1134D ; Grantha # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
+11350 ; Grantha # Lo GRANTHA OM
11357 ; Grantha # Mc GRANTHA AU LENGTH MARK
1135D..11361 ; Grantha # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL
11362..11363 ; Grantha # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
11366..1136C ; Grantha # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
11370..11374 ; Grantha # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
-# Total code points: 83
+# Total code points: 85
# ================================================
@@ -2407,9 +2428,11 @@
115BC..115BD ; Siddham # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
115BE ; Siddham # Mc SIDDHAM SIGN VISARGA
115BF..115C0 ; Siddham # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
-115C1..115C9 ; Siddham # Po [9] SIDDHAM SIGN SIDDHAM..SIDDHAM END OF TEXT MARK
-
-# Total code points: 72
+115C1..115D7 ; Siddham # Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
+115D8..115DB ; Siddham # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U
+115DC..115DD ; Siddham # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
+
+# Total code points: 92
# ================================================
@@ -2448,4 +2471,69 @@
# Total code points: 84
+# ================================================
+
+11700..11719 ; Ahom # Lo [26] AHOM LETTER KA..AHOM LETTER JHA
+1171D..1171F ; Ahom # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11720..11721 ; Ahom # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
+11722..11725 ; Ahom # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11726 ; Ahom # Mc AHOM VOWEL SIGN E
+11727..1172B ; Ahom # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
+11730..11739 ; Ahom # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE
+1173A..1173B ; Ahom # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY
+1173C..1173E ; Ahom # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
+1173F ; Ahom # So AHOM SYMBOL VI
+
+# Total code points: 57
+
+# ================================================
+
+14400..14646 ; Anatolian_Hieroglyphs # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
+
+# Total code points: 583
+
+# ================================================
+
+108E0..108F2 ; Hatran # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH
+108F4..108F5 ; Hatran # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
+108FB..108FF ; Hatran # No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
+
+# Total code points: 26
+
+# ================================================
+
+11280..11286 ; Multani # Lo [7] MULTANI LETTER A..MULTANI LETTER GA
+11288 ; Multani # Lo MULTANI LETTER GHA
+1128A..1128D ; Multani # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA
+1128F..1129D ; Multani # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA
+1129F..112A8 ; Multani # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA
+112A9 ; Multani # Po MULTANI SECTION MARK
+
+# Total code points: 38
+
+# ================================================
+
+10C80..10CB2 ; Old_Hungarian # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
+10CC0..10CF2 ; Old_Hungarian # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
+10CFA..10CFF ; Old_Hungarian # No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
+
+# Total code points: 108
+
+# ================================================
+
+1D800..1D9FF ; SignWriting # So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
+1DA00..1DA36 ; SignWriting # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA37..1DA3A ; SignWriting # So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
+1DA3B..1DA6C ; SignWriting # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA6D..1DA74 ; SignWriting # So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
+1DA75 ; SignWriting # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA76..1DA83 ; SignWriting # So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
+1DA84 ; SignWriting # Mn SIGNWRITING LOCATION HEAD NECK
+1DA85..1DA86 ; SignWriting # So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS
+1DA87..1DA8B ; SignWriting # Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS
+1DA9B..1DA9F ; SignWriting # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA1..1DAAF ; SignWriting # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+
+# Total code points: 672
+
# EOF
--- a/jdk/make/data/unicodedata/SpecialCasing.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/unicodedata/SpecialCasing.txt Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
-# SpecialCasing-7.0.0.txt
-# Date: 2014-03-18, 07:18:02 GMT [MD]
+# SpecialCasing-8.0.0.txt
+# Date: 2014-12-16, 23:08:04 GMT [MD]
#
# Unicode Character Database
# Copyright (c) 1991-2014 Unicode, Inc.
--- a/jdk/make/data/unicodedata/UnicodeData.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/unicodedata/UnicodeData.txt Tue Oct 20 08:24:37 2015 -0700
@@ -667,7 +667,7 @@
029A;LATIN SMALL LETTER CLOSED OPEN E;Ll;0;L;;;;;N;LATIN SMALL LETTER CLOSED EPSILON;;;;
029B;LATIN LETTER SMALL CAPITAL G WITH HOOK;Ll;0;L;;;;;N;LATIN LETTER SMALL CAPITAL G HOOK;;;;
029C;LATIN LETTER SMALL CAPITAL H;Ll;0;L;;;;;N;;;;;
-029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;;;
+029D;LATIN SMALL LETTER J WITH CROSSED-TAIL;Ll;0;L;;;;;N;LATIN SMALL LETTER CROSSED-TAIL J;;A7B2;;A7B2
029E;LATIN SMALL LETTER TURNED K;Ll;0;L;;;;;N;;;A7B0;;A7B0
029F;LATIN LETTER SMALL CAPITAL L;Ll;0;L;;;;;N;;;;;
02A0;LATIN SMALL LETTER Q WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER Q HOOK;;;;
@@ -2091,6 +2091,9 @@
08B0;ARABIC LETTER GAF WITH INVERTED STROKE;Lo;0;AL;;;;;N;;;;;
08B1;ARABIC LETTER STRAIGHT WAW;Lo;0;AL;;;;;N;;;;;
08B2;ARABIC LETTER ZAIN WITH INVERTED V ABOVE;Lo;0;AL;;;;;N;;;;;
+08B3;ARABIC LETTER AIN WITH THREE DOTS BELOW;Lo;0;AL;;;;;N;;;;;
+08B4;ARABIC LETTER KAF WITH DOT BELOW;Lo;0;AL;;;;;N;;;;;
+08E3;ARABIC TURNED DAMMA BELOW;Mn;220;NSM;;;;;N;;;;;
08E4;ARABIC CURLY FATHA;Mn;230;NSM;;;;;N;;;;;
08E5;ARABIC CURLY DAMMA;Mn;230;NSM;;;;;N;;;;;
08E6;ARABIC CURLY KASRA;Mn;220;NSM;;;;;N;;;;;
@@ -2503,6 +2506,7 @@
0AEF;GUJARATI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
0AF0;GUJARATI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
0AF1;GUJARATI RUPEE SIGN;Sc;0;ET;;;;;N;;;;;
+0AF9;GUJARATI LETTER ZHA;Lo;0;L;;;;;N;;;;;
0B01;ORIYA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
0B02;ORIYA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
0B03;ORIYA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
@@ -2738,6 +2742,7 @@
0C56;TELUGU AI LENGTH MARK;Mn;91;NSM;;;;;N;;;;;
0C58;TELUGU LETTER TSA;Lo;0;L;;;;;N;;;;;
0C59;TELUGU LETTER DZA;Lo;0;L;;;;;N;;;;;
+0C5A;TELUGU LETTER RRRA;Lo;0;L;;;;;N;;;;;
0C60;TELUGU LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
0C61;TELUGU LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
0C62;TELUGU VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
@@ -2919,6 +2924,7 @@
0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;;
0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;;
0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
+0D5F;MALAYALAM LETTER ARCHAIC II;Lo;0;L;;;;;N;;;;;
0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;;
0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;;
0D62;MALAYALAM VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;;
@@ -4289,91 +4295,98 @@
1397;ETHIOPIC TONAL MARK HIDET;So;0;ON;;;;;N;;;;;
1398;ETHIOPIC TONAL MARK DERET-HIDET;So;0;ON;;;;;N;;;;;
1399;ETHIOPIC TONAL MARK KURT;So;0;ON;;;;;N;;;;;
-13A0;CHEROKEE LETTER A;Lo;0;L;;;;;N;;;;;
-13A1;CHEROKEE LETTER E;Lo;0;L;;;;;N;;;;;
-13A2;CHEROKEE LETTER I;Lo;0;L;;;;;N;;;;;
-13A3;CHEROKEE LETTER O;Lo;0;L;;;;;N;;;;;
-13A4;CHEROKEE LETTER U;Lo;0;L;;;;;N;;;;;
-13A5;CHEROKEE LETTER V;Lo;0;L;;;;;N;;;;;
-13A6;CHEROKEE LETTER GA;Lo;0;L;;;;;N;;;;;
-13A7;CHEROKEE LETTER KA;Lo;0;L;;;;;N;;;;;
-13A8;CHEROKEE LETTER GE;Lo;0;L;;;;;N;;;;;
-13A9;CHEROKEE LETTER GI;Lo;0;L;;;;;N;;;;;
-13AA;CHEROKEE LETTER GO;Lo;0;L;;;;;N;;;;;
-13AB;CHEROKEE LETTER GU;Lo;0;L;;;;;N;;;;;
-13AC;CHEROKEE LETTER GV;Lo;0;L;;;;;N;;;;;
-13AD;CHEROKEE LETTER HA;Lo;0;L;;;;;N;;;;;
-13AE;CHEROKEE LETTER HE;Lo;0;L;;;;;N;;;;;
-13AF;CHEROKEE LETTER HI;Lo;0;L;;;;;N;;;;;
-13B0;CHEROKEE LETTER HO;Lo;0;L;;;;;N;;;;;
-13B1;CHEROKEE LETTER HU;Lo;0;L;;;;;N;;;;;
-13B2;CHEROKEE LETTER HV;Lo;0;L;;;;;N;;;;;
-13B3;CHEROKEE LETTER LA;Lo;0;L;;;;;N;;;;;
-13B4;CHEROKEE LETTER LE;Lo;0;L;;;;;N;;;;;
-13B5;CHEROKEE LETTER LI;Lo;0;L;;;;;N;;;;;
-13B6;CHEROKEE LETTER LO;Lo;0;L;;;;;N;;;;;
-13B7;CHEROKEE LETTER LU;Lo;0;L;;;;;N;;;;;
-13B8;CHEROKEE LETTER LV;Lo;0;L;;;;;N;;;;;
-13B9;CHEROKEE LETTER MA;Lo;0;L;;;;;N;;;;;
-13BA;CHEROKEE LETTER ME;Lo;0;L;;;;;N;;;;;
-13BB;CHEROKEE LETTER MI;Lo;0;L;;;;;N;;;;;
-13BC;CHEROKEE LETTER MO;Lo;0;L;;;;;N;;;;;
-13BD;CHEROKEE LETTER MU;Lo;0;L;;;;;N;;;;;
-13BE;CHEROKEE LETTER NA;Lo;0;L;;;;;N;;;;;
-13BF;CHEROKEE LETTER HNA;Lo;0;L;;;;;N;;;;;
-13C0;CHEROKEE LETTER NAH;Lo;0;L;;;;;N;;;;;
-13C1;CHEROKEE LETTER NE;Lo;0;L;;;;;N;;;;;
-13C2;CHEROKEE LETTER NI;Lo;0;L;;;;;N;;;;;
-13C3;CHEROKEE LETTER NO;Lo;0;L;;;;;N;;;;;
-13C4;CHEROKEE LETTER NU;Lo;0;L;;;;;N;;;;;
-13C5;CHEROKEE LETTER NV;Lo;0;L;;;;;N;;;;;
-13C6;CHEROKEE LETTER QUA;Lo;0;L;;;;;N;;;;;
-13C7;CHEROKEE LETTER QUE;Lo;0;L;;;;;N;;;;;
-13C8;CHEROKEE LETTER QUI;Lo;0;L;;;;;N;;;;;
-13C9;CHEROKEE LETTER QUO;Lo;0;L;;;;;N;;;;;
-13CA;CHEROKEE LETTER QUU;Lo;0;L;;;;;N;;;;;
-13CB;CHEROKEE LETTER QUV;Lo;0;L;;;;;N;;;;;
-13CC;CHEROKEE LETTER SA;Lo;0;L;;;;;N;;;;;
-13CD;CHEROKEE LETTER S;Lo;0;L;;;;;N;;;;;
-13CE;CHEROKEE LETTER SE;Lo;0;L;;;;;N;;;;;
-13CF;CHEROKEE LETTER SI;Lo;0;L;;;;;N;;;;;
-13D0;CHEROKEE LETTER SO;Lo;0;L;;;;;N;;;;;
-13D1;CHEROKEE LETTER SU;Lo;0;L;;;;;N;;;;;
-13D2;CHEROKEE LETTER SV;Lo;0;L;;;;;N;;;;;
-13D3;CHEROKEE LETTER DA;Lo;0;L;;;;;N;;;;;
-13D4;CHEROKEE LETTER TA;Lo;0;L;;;;;N;;;;;
-13D5;CHEROKEE LETTER DE;Lo;0;L;;;;;N;;;;;
-13D6;CHEROKEE LETTER TE;Lo;0;L;;;;;N;;;;;
-13D7;CHEROKEE LETTER DI;Lo;0;L;;;;;N;;;;;
-13D8;CHEROKEE LETTER TI;Lo;0;L;;;;;N;;;;;
-13D9;CHEROKEE LETTER DO;Lo;0;L;;;;;N;;;;;
-13DA;CHEROKEE LETTER DU;Lo;0;L;;;;;N;;;;;
-13DB;CHEROKEE LETTER DV;Lo;0;L;;;;;N;;;;;
-13DC;CHEROKEE LETTER DLA;Lo;0;L;;;;;N;;;;;
-13DD;CHEROKEE LETTER TLA;Lo;0;L;;;;;N;;;;;
-13DE;CHEROKEE LETTER TLE;Lo;0;L;;;;;N;;;;;
-13DF;CHEROKEE LETTER TLI;Lo;0;L;;;;;N;;;;;
-13E0;CHEROKEE LETTER TLO;Lo;0;L;;;;;N;;;;;
-13E1;CHEROKEE LETTER TLU;Lo;0;L;;;;;N;;;;;
-13E2;CHEROKEE LETTER TLV;Lo;0;L;;;;;N;;;;;
-13E3;CHEROKEE LETTER TSA;Lo;0;L;;;;;N;;;;;
-13E4;CHEROKEE LETTER TSE;Lo;0;L;;;;;N;;;;;
-13E5;CHEROKEE LETTER TSI;Lo;0;L;;;;;N;;;;;
-13E6;CHEROKEE LETTER TSO;Lo;0;L;;;;;N;;;;;
-13E7;CHEROKEE LETTER TSU;Lo;0;L;;;;;N;;;;;
-13E8;CHEROKEE LETTER TSV;Lo;0;L;;;;;N;;;;;
-13E9;CHEROKEE LETTER WA;Lo;0;L;;;;;N;;;;;
-13EA;CHEROKEE LETTER WE;Lo;0;L;;;;;N;;;;;
-13EB;CHEROKEE LETTER WI;Lo;0;L;;;;;N;;;;;
-13EC;CHEROKEE LETTER WO;Lo;0;L;;;;;N;;;;;
-13ED;CHEROKEE LETTER WU;Lo;0;L;;;;;N;;;;;
-13EE;CHEROKEE LETTER WV;Lo;0;L;;;;;N;;;;;
-13EF;CHEROKEE LETTER YA;Lo;0;L;;;;;N;;;;;
-13F0;CHEROKEE LETTER YE;Lo;0;L;;;;;N;;;;;
-13F1;CHEROKEE LETTER YI;Lo;0;L;;;;;N;;;;;
-13F2;CHEROKEE LETTER YO;Lo;0;L;;;;;N;;;;;
-13F3;CHEROKEE LETTER YU;Lo;0;L;;;;;N;;;;;
-13F4;CHEROKEE LETTER YV;Lo;0;L;;;;;N;;;;;
+13A0;CHEROKEE LETTER A;Lu;0;L;;;;;N;;;;AB70;
+13A1;CHEROKEE LETTER E;Lu;0;L;;;;;N;;;;AB71;
+13A2;CHEROKEE LETTER I;Lu;0;L;;;;;N;;;;AB72;
+13A3;CHEROKEE LETTER O;Lu;0;L;;;;;N;;;;AB73;
+13A4;CHEROKEE LETTER U;Lu;0;L;;;;;N;;;;AB74;
+13A5;CHEROKEE LETTER V;Lu;0;L;;;;;N;;;;AB75;
+13A6;CHEROKEE LETTER GA;Lu;0;L;;;;;N;;;;AB76;
+13A7;CHEROKEE LETTER KA;Lu;0;L;;;;;N;;;;AB77;
+13A8;CHEROKEE LETTER GE;Lu;0;L;;;;;N;;;;AB78;
+13A9;CHEROKEE LETTER GI;Lu;0;L;;;;;N;;;;AB79;
+13AA;CHEROKEE LETTER GO;Lu;0;L;;;;;N;;;;AB7A;
+13AB;CHEROKEE LETTER GU;Lu;0;L;;;;;N;;;;AB7B;
+13AC;CHEROKEE LETTER GV;Lu;0;L;;;;;N;;;;AB7C;
+13AD;CHEROKEE LETTER HA;Lu;0;L;;;;;N;;;;AB7D;
+13AE;CHEROKEE LETTER HE;Lu;0;L;;;;;N;;;;AB7E;
+13AF;CHEROKEE LETTER HI;Lu;0;L;;;;;N;;;;AB7F;
+13B0;CHEROKEE LETTER HO;Lu;0;L;;;;;N;;;;AB80;
+13B1;CHEROKEE LETTER HU;Lu;0;L;;;;;N;;;;AB81;
+13B2;CHEROKEE LETTER HV;Lu;0;L;;;;;N;;;;AB82;
+13B3;CHEROKEE LETTER LA;Lu;0;L;;;;;N;;;;AB83;
+13B4;CHEROKEE LETTER LE;Lu;0;L;;;;;N;;;;AB84;
+13B5;CHEROKEE LETTER LI;Lu;0;L;;;;;N;;;;AB85;
+13B6;CHEROKEE LETTER LO;Lu;0;L;;;;;N;;;;AB86;
+13B7;CHEROKEE LETTER LU;Lu;0;L;;;;;N;;;;AB87;
+13B8;CHEROKEE LETTER LV;Lu;0;L;;;;;N;;;;AB88;
+13B9;CHEROKEE LETTER MA;Lu;0;L;;;;;N;;;;AB89;
+13BA;CHEROKEE LETTER ME;Lu;0;L;;;;;N;;;;AB8A;
+13BB;CHEROKEE LETTER MI;Lu;0;L;;;;;N;;;;AB8B;
+13BC;CHEROKEE LETTER MO;Lu;0;L;;;;;N;;;;AB8C;
+13BD;CHEROKEE LETTER MU;Lu;0;L;;;;;N;;;;AB8D;
+13BE;CHEROKEE LETTER NA;Lu;0;L;;;;;N;;;;AB8E;
+13BF;CHEROKEE LETTER HNA;Lu;0;L;;;;;N;;;;AB8F;
+13C0;CHEROKEE LETTER NAH;Lu;0;L;;;;;N;;;;AB90;
+13C1;CHEROKEE LETTER NE;Lu;0;L;;;;;N;;;;AB91;
+13C2;CHEROKEE LETTER NI;Lu;0;L;;;;;N;;;;AB92;
+13C3;CHEROKEE LETTER NO;Lu;0;L;;;;;N;;;;AB93;
+13C4;CHEROKEE LETTER NU;Lu;0;L;;;;;N;;;;AB94;
+13C5;CHEROKEE LETTER NV;Lu;0;L;;;;;N;;;;AB95;
+13C6;CHEROKEE LETTER QUA;Lu;0;L;;;;;N;;;;AB96;
+13C7;CHEROKEE LETTER QUE;Lu;0;L;;;;;N;;;;AB97;
+13C8;CHEROKEE LETTER QUI;Lu;0;L;;;;;N;;;;AB98;
+13C9;CHEROKEE LETTER QUO;Lu;0;L;;;;;N;;;;AB99;
+13CA;CHEROKEE LETTER QUU;Lu;0;L;;;;;N;;;;AB9A;
+13CB;CHEROKEE LETTER QUV;Lu;0;L;;;;;N;;;;AB9B;
+13CC;CHEROKEE LETTER SA;Lu;0;L;;;;;N;;;;AB9C;
+13CD;CHEROKEE LETTER S;Lu;0;L;;;;;N;;;;AB9D;
+13CE;CHEROKEE LETTER SE;Lu;0;L;;;;;N;;;;AB9E;
+13CF;CHEROKEE LETTER SI;Lu;0;L;;;;;N;;;;AB9F;
+13D0;CHEROKEE LETTER SO;Lu;0;L;;;;;N;;;;ABA0;
+13D1;CHEROKEE LETTER SU;Lu;0;L;;;;;N;;;;ABA1;
+13D2;CHEROKEE LETTER SV;Lu;0;L;;;;;N;;;;ABA2;
+13D3;CHEROKEE LETTER DA;Lu;0;L;;;;;N;;;;ABA3;
+13D4;CHEROKEE LETTER TA;Lu;0;L;;;;;N;;;;ABA4;
+13D5;CHEROKEE LETTER DE;Lu;0;L;;;;;N;;;;ABA5;
+13D6;CHEROKEE LETTER TE;Lu;0;L;;;;;N;;;;ABA6;
+13D7;CHEROKEE LETTER DI;Lu;0;L;;;;;N;;;;ABA7;
+13D8;CHEROKEE LETTER TI;Lu;0;L;;;;;N;;;;ABA8;
+13D9;CHEROKEE LETTER DO;Lu;0;L;;;;;N;;;;ABA9;
+13DA;CHEROKEE LETTER DU;Lu;0;L;;;;;N;;;;ABAA;
+13DB;CHEROKEE LETTER DV;Lu;0;L;;;;;N;;;;ABAB;
+13DC;CHEROKEE LETTER DLA;Lu;0;L;;;;;N;;;;ABAC;
+13DD;CHEROKEE LETTER TLA;Lu;0;L;;;;;N;;;;ABAD;
+13DE;CHEROKEE LETTER TLE;Lu;0;L;;;;;N;;;;ABAE;
+13DF;CHEROKEE LETTER TLI;Lu;0;L;;;;;N;;;;ABAF;
+13E0;CHEROKEE LETTER TLO;Lu;0;L;;;;;N;;;;ABB0;
+13E1;CHEROKEE LETTER TLU;Lu;0;L;;;;;N;;;;ABB1;
+13E2;CHEROKEE LETTER TLV;Lu;0;L;;;;;N;;;;ABB2;
+13E3;CHEROKEE LETTER TSA;Lu;0;L;;;;;N;;;;ABB3;
+13E4;CHEROKEE LETTER TSE;Lu;0;L;;;;;N;;;;ABB4;
+13E5;CHEROKEE LETTER TSI;Lu;0;L;;;;;N;;;;ABB5;
+13E6;CHEROKEE LETTER TSO;Lu;0;L;;;;;N;;;;ABB6;
+13E7;CHEROKEE LETTER TSU;Lu;0;L;;;;;N;;;;ABB7;
+13E8;CHEROKEE LETTER TSV;Lu;0;L;;;;;N;;;;ABB8;
+13E9;CHEROKEE LETTER WA;Lu;0;L;;;;;N;;;;ABB9;
+13EA;CHEROKEE LETTER WE;Lu;0;L;;;;;N;;;;ABBA;
+13EB;CHEROKEE LETTER WI;Lu;0;L;;;;;N;;;;ABBB;
+13EC;CHEROKEE LETTER WO;Lu;0;L;;;;;N;;;;ABBC;
+13ED;CHEROKEE LETTER WU;Lu;0;L;;;;;N;;;;ABBD;
+13EE;CHEROKEE LETTER WV;Lu;0;L;;;;;N;;;;ABBE;
+13EF;CHEROKEE LETTER YA;Lu;0;L;;;;;N;;;;ABBF;
+13F0;CHEROKEE LETTER YE;Lu;0;L;;;;;N;;;;13F8;
+13F1;CHEROKEE LETTER YI;Lu;0;L;;;;;N;;;;13F9;
+13F2;CHEROKEE LETTER YO;Lu;0;L;;;;;N;;;;13FA;
+13F3;CHEROKEE LETTER YU;Lu;0;L;;;;;N;;;;13FB;
+13F4;CHEROKEE LETTER YV;Lu;0;L;;;;;N;;;;13FC;
+13F5;CHEROKEE LETTER MV;Lu;0;L;;;;;N;;;;13FD;
+13F8;CHEROKEE SMALL LETTER YE;Ll;0;L;;;;;N;;;13F0;;13F0
+13F9;CHEROKEE SMALL LETTER YI;Ll;0;L;;;;;N;;;13F1;;13F1
+13FA;CHEROKEE SMALL LETTER YO;Ll;0;L;;;;;N;;;13F2;;13F2
+13FB;CHEROKEE SMALL LETTER YU;Ll;0;L;;;;;N;;;13F3;;13F3
+13FC;CHEROKEE SMALL LETTER YV;Ll;0;L;;;;;N;;;13F4;;13F4
+13FD;CHEROKEE SMALL LETTER MV;Ll;0;L;;;;;N;;;13F5;;13F5
1400;CANADIAN SYLLABICS HYPHEN;Pd;0;ON;;;;;N;;;;;
1401;CANADIAN SYLLABICS E;Lo;0;L;;;;;N;;;;;
1402;CANADIAN SYLLABICS AAI;Lo;0;L;;;;;N;;;;;
@@ -5700,23 +5713,23 @@
19A9;NEW TAI LUE LETTER LOW XVA;Lo;0;L;;;;;N;;;;;
19AA;NEW TAI LUE LETTER HIGH SUA;Lo;0;L;;;;;N;;;;;
19AB;NEW TAI LUE LETTER LOW SUA;Lo;0;L;;;;;N;;;;;
-19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Mc;0;L;;;;;N;;;;;
-19B1;NEW TAI LUE VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
-19B2;NEW TAI LUE VOWEL SIGN II;Mc;0;L;;;;;N;;;;;
-19B3;NEW TAI LUE VOWEL SIGN U;Mc;0;L;;;;;N;;;;;
-19B4;NEW TAI LUE VOWEL SIGN UU;Mc;0;L;;;;;N;;;;;
-19B5;NEW TAI LUE VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
-19B6;NEW TAI LUE VOWEL SIGN AE;Mc;0;L;;;;;N;;;;;
-19B7;NEW TAI LUE VOWEL SIGN O;Mc;0;L;;;;;N;;;;;
-19B8;NEW TAI LUE VOWEL SIGN OA;Mc;0;L;;;;;N;;;;;
-19B9;NEW TAI LUE VOWEL SIGN UE;Mc;0;L;;;;;N;;;;;
-19BA;NEW TAI LUE VOWEL SIGN AY;Mc;0;L;;;;;N;;;;;
-19BB;NEW TAI LUE VOWEL SIGN AAY;Mc;0;L;;;;;N;;;;;
-19BC;NEW TAI LUE VOWEL SIGN UY;Mc;0;L;;;;;N;;;;;
-19BD;NEW TAI LUE VOWEL SIGN OY;Mc;0;L;;;;;N;;;;;
-19BE;NEW TAI LUE VOWEL SIGN OAY;Mc;0;L;;;;;N;;;;;
-19BF;NEW TAI LUE VOWEL SIGN UEY;Mc;0;L;;;;;N;;;;;
-19C0;NEW TAI LUE VOWEL SIGN IY;Mc;0;L;;;;;N;;;;;
+19B0;NEW TAI LUE VOWEL SIGN VOWEL SHORTENER;Lo;0;L;;;;;N;;;;;
+19B1;NEW TAI LUE VOWEL SIGN AA;Lo;0;L;;;;;N;;;;;
+19B2;NEW TAI LUE VOWEL SIGN II;Lo;0;L;;;;;N;;;;;
+19B3;NEW TAI LUE VOWEL SIGN U;Lo;0;L;;;;;N;;;;;
+19B4;NEW TAI LUE VOWEL SIGN UU;Lo;0;L;;;;;N;;;;;
+19B5;NEW TAI LUE VOWEL SIGN E;Lo;0;L;;;;;N;;;;;
+19B6;NEW TAI LUE VOWEL SIGN AE;Lo;0;L;;;;;N;;;;;
+19B7;NEW TAI LUE VOWEL SIGN O;Lo;0;L;;;;;N;;;;;
+19B8;NEW TAI LUE VOWEL SIGN OA;Lo;0;L;;;;;N;;;;;
+19B9;NEW TAI LUE VOWEL SIGN UE;Lo;0;L;;;;;N;;;;;
+19BA;NEW TAI LUE VOWEL SIGN AY;Lo;0;L;;;;;N;;;;;
+19BB;NEW TAI LUE VOWEL SIGN AAY;Lo;0;L;;;;;N;;;;;
+19BC;NEW TAI LUE VOWEL SIGN UY;Lo;0;L;;;;;N;;;;;
+19BD;NEW TAI LUE VOWEL SIGN OY;Lo;0;L;;;;;N;;;;;
+19BE;NEW TAI LUE VOWEL SIGN OAY;Lo;0;L;;;;;N;;;;;
+19BF;NEW TAI LUE VOWEL SIGN UEY;Lo;0;L;;;;;N;;;;;
+19C0;NEW TAI LUE VOWEL SIGN IY;Lo;0;L;;;;;N;;;;;
19C1;NEW TAI LUE LETTER FINAL V;Lo;0;L;;;;;N;;;;;
19C2;NEW TAI LUE LETTER FINAL NG;Lo;0;L;;;;;N;;;;;
19C3;NEW TAI LUE LETTER FINAL N;Lo;0;L;;;;;N;;;;;
@@ -5724,8 +5737,8 @@
19C5;NEW TAI LUE LETTER FINAL K;Lo;0;L;;;;;N;;;;;
19C6;NEW TAI LUE LETTER FINAL D;Lo;0;L;;;;;N;;;;;
19C7;NEW TAI LUE LETTER FINAL B;Lo;0;L;;;;;N;;;;;
-19C8;NEW TAI LUE TONE MARK-1;Mc;0;L;;;;;N;;;;;
-19C9;NEW TAI LUE TONE MARK-2;Mc;0;L;;;;;N;;;;;
+19C8;NEW TAI LUE TONE MARK-1;Lo;0;L;;;;;N;;;;;
+19C9;NEW TAI LUE TONE MARK-2;Lo;0;L;;;;;N;;;;;
19D0;NEW TAI LUE DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
19D1;NEW TAI LUE DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
19D2;NEW TAI LUE DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
@@ -7277,6 +7290,7 @@
20BB;NORDIC MARK SIGN;Sc;0;ET;;;;;N;;;;;
20BC;MANAT SIGN;Sc;0;ET;;;;;N;;;;;
20BD;RUBLE SIGN;Sc;0;ET;;;;;N;;;;;
+20BE;LARI SIGN;Sc;0;ET;;;;;N;;;;;
20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;;
20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;;
20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;;
@@ -7448,6 +7462,8 @@
2187;ROMAN NUMERAL FIFTY THOUSAND;Nl;0;L;;;;50000;N;;;;;
2188;ROMAN NUMERAL ONE HUNDRED THOUSAND;Nl;0;L;;;;100000;N;;;;;
2189;VULGAR FRACTION ZERO THIRDS;No;0;ON;<fraction> 0030 2044 0033;;;0;N;;;;;
+218A;TURNED DIGIT TWO;So;0;ON;;;;;N;;;;;
+218B;TURNED DIGIT THREE;So;0;ON;;;;;N;;;;;
2190;LEFTWARDS ARROW;Sm;0;ON;;;;;N;LEFT ARROW;;;;
2191;UPWARDS ARROW;Sm;0;ON;;;;;N;UP ARROW;;;;
2192;RIGHTWARDS ARROW;Sm;0;ON;;;;;N;RIGHT ARROW;;;;
@@ -10015,6 +10031,10 @@
2BCF;ROTATED WHITE FOUR POINTED CUSP;So;0;ON;;;;;N;;;;;
2BD0;SQUARE POSITION INDICATOR;So;0;ON;;;;;N;;;;;
2BD1;UNCERTAINTY SIGN;So;0;ON;;;;;N;;;;;
+2BEC;LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
+2BED;UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
+2BEE;RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
+2BEF;DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS;So;0;ON;;;;;N;;;;;
2C00;GLAGOLITIC CAPITAL LETTER AZU;Lu;0;L;;;;;N;;;;2C30;
2C01;GLAGOLITIC CAPITAL LETTER BUKY;Lu;0;L;;;;;N;;;;2C31;
2C02;GLAGOLITIC CAPITAL LETTER VEDE;Lu;0;L;;;;;N;;;;2C32;
@@ -11942,7 +11962,7 @@
4DFE;HEXAGRAM FOR AFTER COMPLETION;So;0;ON;;;;;N;;;;;
4DFF;HEXAGRAM FOR BEFORE COMPLETION;So;0;ON;;;;;N;;;;;
4E00;<CJK Ideograph, First>;Lo;0;L;;;;;N;;;;;
-9FCC;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
+9FD5;<CJK Ideograph, Last>;Lo;0;L;;;;;N;;;;;
A000;YI SYLLABLE IT;Lo;0;L;;;;;N;;;;;
A001;YI SYLLABLE IX;Lo;0;L;;;;;N;;;;;
A002;YI SYLLABLE I;Lo;0;L;;;;;N;;;;;
@@ -13605,6 +13625,7 @@
A69B;CYRILLIC SMALL LETTER CROSSED O;Ll;0;L;;;;;N;;;A69A;;A69A
A69C;MODIFIER LETTER CYRILLIC HARD SIGN;Lm;0;L;<super> 044A;;;;N;;;;;
A69D;MODIFIER LETTER CYRILLIC SOFT SIGN;Lm;0;L;<super> 044C;;;;N;;;;;
+A69E;COMBINING CYRILLIC LETTER EF;Mn;230;NSM;;;;;N;;;;;
A69F;COMBINING CYRILLIC LETTER IOTIFIED E;Mn;230;NSM;;;;;N;;;;;
A6A0;BAMUM LETTER A;Lo;0;L;;;;;N;;;;;
A6A1;BAMUM LETTER KA;Lo;0;L;;;;;N;;;;;
@@ -13837,6 +13858,7 @@
A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B
A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265;
A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;;
+A78F;LATIN LETTER SINOLOGICAL DOT;Lo;0;L;;;;;N;;;;;
A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791;
A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790
A792;LATIN CAPITAL LETTER C WITH BAR;Lu;0;L;;;;;N;;;;A793;
@@ -13869,6 +13891,12 @@
A7AD;LATIN CAPITAL LETTER L WITH BELT;Lu;0;L;;;;;N;;;;026C;
A7B0;LATIN CAPITAL LETTER TURNED K;Lu;0;L;;;;;N;;;;029E;
A7B1;LATIN CAPITAL LETTER TURNED T;Lu;0;L;;;;;N;;;;0287;
+A7B2;LATIN CAPITAL LETTER J WITH CROSSED-TAIL;Lu;0;L;;;;;N;;;;029D;
+A7B3;LATIN CAPITAL LETTER CHI;Lu;0;L;;;;;N;;;;AB53;
+A7B4;LATIN CAPITAL LETTER BETA;Lu;0;L;;;;;N;;;;A7B5;
+A7B5;LATIN SMALL LETTER BETA;Ll;0;L;;;;;N;;;A7B4;;A7B4
+A7B6;LATIN CAPITAL LETTER OMEGA;Lu;0;L;;;;;N;;;;A7B7;
+A7B7;LATIN SMALL LETTER OMEGA;Ll;0;L;;;;;N;;;A7B6;;A7B6
A7F7;LATIN EPIGRAPHIC LETTER SIDEWAYS I;Lo;0;L;;;;;N;;;;;
A7F8;MODIFIER LETTER CAPITAL H WITH STROKE;Lm;0;L;<super> 0126;;;;N;;;;;
A7F9;MODIFIER LETTER SMALL LIGATURE OE;Lm;0;L;<super> 0153;;;;N;;;;;
@@ -14097,6 +14125,8 @@
A8F9;DEVANAGARI GAP FILLER;Po;0;L;;;;;N;;;;;
A8FA;DEVANAGARI CARET;Po;0;L;;;;;N;;;;;
A8FB;DEVANAGARI HEADSTROKE;Lo;0;L;;;;;N;;;;;
+A8FC;DEVANAGARI SIGN SIDDHAM;Po;0;L;;;;;N;;;;;
+A8FD;DEVANAGARI JAIN OM;Lo;0;L;;;;;N;;;;;
A900;KAYAH LI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
A901;KAYAH LI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
A902;KAYAH LI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
@@ -14610,7 +14640,7 @@
AB50;LATIN SMALL LETTER UI;Ll;0;L;;;;;N;;;;;
AB51;LATIN SMALL LETTER TURNED UI;Ll;0;L;;;;;N;;;;;
AB52;LATIN SMALL LETTER U WITH LEFT HOOK;Ll;0;L;;;;;N;;;;;
-AB53;LATIN SMALL LETTER CHI;Ll;0;L;;;;;N;;;;;
+AB53;LATIN SMALL LETTER CHI;Ll;0;L;;;;;N;;;A7B3;;A7B3
AB54;LATIN SMALL LETTER CHI WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;;
AB55;LATIN SMALL LETTER CHI WITH LOW LEFT SERIF;Ll;0;L;;;;;N;;;;;
AB56;LATIN SMALL LETTER X WITH LOW RIGHT RING;Ll;0;L;;;;;N;;;;;
@@ -14623,8 +14653,92 @@
AB5D;MODIFIER LETTER SMALL L WITH INVERTED LAZY S;Lm;0;L;<super> AB37;;;;N;;;;;
AB5E;MODIFIER LETTER SMALL L WITH MIDDLE TILDE;Lm;0;L;<super> 026B;;;;N;;;;;
AB5F;MODIFIER LETTER SMALL U WITH LEFT HOOK;Lm;0;L;<super> AB52;;;;N;;;;;
+AB60;LATIN SMALL LETTER SAKHA YAT;Ll;0;L;;;;;N;;;;;
+AB61;LATIN SMALL LETTER IOTIFIED E;Ll;0;L;;;;;N;;;;;
+AB62;LATIN SMALL LETTER OPEN OE;Ll;0;L;;;;;N;;;;;
+AB63;LATIN SMALL LETTER UO;Ll;0;L;;;;;N;;;;;
AB64;LATIN SMALL LETTER INVERTED ALPHA;Ll;0;L;;;;;N;;;;;
AB65;GREEK LETTER SMALL CAPITAL OMEGA;Ll;0;L;;;;;N;;;;;
+AB70;CHEROKEE SMALL LETTER A;Ll;0;L;;;;;N;;;13A0;;13A0
+AB71;CHEROKEE SMALL LETTER E;Ll;0;L;;;;;N;;;13A1;;13A1
+AB72;CHEROKEE SMALL LETTER I;Ll;0;L;;;;;N;;;13A2;;13A2
+AB73;CHEROKEE SMALL LETTER O;Ll;0;L;;;;;N;;;13A3;;13A3
+AB74;CHEROKEE SMALL LETTER U;Ll;0;L;;;;;N;;;13A4;;13A4
+AB75;CHEROKEE SMALL LETTER V;Ll;0;L;;;;;N;;;13A5;;13A5
+AB76;CHEROKEE SMALL LETTER GA;Ll;0;L;;;;;N;;;13A6;;13A6
+AB77;CHEROKEE SMALL LETTER KA;Ll;0;L;;;;;N;;;13A7;;13A7
+AB78;CHEROKEE SMALL LETTER GE;Ll;0;L;;;;;N;;;13A8;;13A8
+AB79;CHEROKEE SMALL LETTER GI;Ll;0;L;;;;;N;;;13A9;;13A9
+AB7A;CHEROKEE SMALL LETTER GO;Ll;0;L;;;;;N;;;13AA;;13AA
+AB7B;CHEROKEE SMALL LETTER GU;Ll;0;L;;;;;N;;;13AB;;13AB
+AB7C;CHEROKEE SMALL LETTER GV;Ll;0;L;;;;;N;;;13AC;;13AC
+AB7D;CHEROKEE SMALL LETTER HA;Ll;0;L;;;;;N;;;13AD;;13AD
+AB7E;CHEROKEE SMALL LETTER HE;Ll;0;L;;;;;N;;;13AE;;13AE
+AB7F;CHEROKEE SMALL LETTER HI;Ll;0;L;;;;;N;;;13AF;;13AF
+AB80;CHEROKEE SMALL LETTER HO;Ll;0;L;;;;;N;;;13B0;;13B0
+AB81;CHEROKEE SMALL LETTER HU;Ll;0;L;;;;;N;;;13B1;;13B1
+AB82;CHEROKEE SMALL LETTER HV;Ll;0;L;;;;;N;;;13B2;;13B2
+AB83;CHEROKEE SMALL LETTER LA;Ll;0;L;;;;;N;;;13B3;;13B3
+AB84;CHEROKEE SMALL LETTER LE;Ll;0;L;;;;;N;;;13B4;;13B4
+AB85;CHEROKEE SMALL LETTER LI;Ll;0;L;;;;;N;;;13B5;;13B5
+AB86;CHEROKEE SMALL LETTER LO;Ll;0;L;;;;;N;;;13B6;;13B6
+AB87;CHEROKEE SMALL LETTER LU;Ll;0;L;;;;;N;;;13B7;;13B7
+AB88;CHEROKEE SMALL LETTER LV;Ll;0;L;;;;;N;;;13B8;;13B8
+AB89;CHEROKEE SMALL LETTER MA;Ll;0;L;;;;;N;;;13B9;;13B9
+AB8A;CHEROKEE SMALL LETTER ME;Ll;0;L;;;;;N;;;13BA;;13BA
+AB8B;CHEROKEE SMALL LETTER MI;Ll;0;L;;;;;N;;;13BB;;13BB
+AB8C;CHEROKEE SMALL LETTER MO;Ll;0;L;;;;;N;;;13BC;;13BC
+AB8D;CHEROKEE SMALL LETTER MU;Ll;0;L;;;;;N;;;13BD;;13BD
+AB8E;CHEROKEE SMALL LETTER NA;Ll;0;L;;;;;N;;;13BE;;13BE
+AB8F;CHEROKEE SMALL LETTER HNA;Ll;0;L;;;;;N;;;13BF;;13BF
+AB90;CHEROKEE SMALL LETTER NAH;Ll;0;L;;;;;N;;;13C0;;13C0
+AB91;CHEROKEE SMALL LETTER NE;Ll;0;L;;;;;N;;;13C1;;13C1
+AB92;CHEROKEE SMALL LETTER NI;Ll;0;L;;;;;N;;;13C2;;13C2
+AB93;CHEROKEE SMALL LETTER NO;Ll;0;L;;;;;N;;;13C3;;13C3
+AB94;CHEROKEE SMALL LETTER NU;Ll;0;L;;;;;N;;;13C4;;13C4
+AB95;CHEROKEE SMALL LETTER NV;Ll;0;L;;;;;N;;;13C5;;13C5
+AB96;CHEROKEE SMALL LETTER QUA;Ll;0;L;;;;;N;;;13C6;;13C6
+AB97;CHEROKEE SMALL LETTER QUE;Ll;0;L;;;;;N;;;13C7;;13C7
+AB98;CHEROKEE SMALL LETTER QUI;Ll;0;L;;;;;N;;;13C8;;13C8
+AB99;CHEROKEE SMALL LETTER QUO;Ll;0;L;;;;;N;;;13C9;;13C9
+AB9A;CHEROKEE SMALL LETTER QUU;Ll;0;L;;;;;N;;;13CA;;13CA
+AB9B;CHEROKEE SMALL LETTER QUV;Ll;0;L;;;;;N;;;13CB;;13CB
+AB9C;CHEROKEE SMALL LETTER SA;Ll;0;L;;;;;N;;;13CC;;13CC
+AB9D;CHEROKEE SMALL LETTER S;Ll;0;L;;;;;N;;;13CD;;13CD
+AB9E;CHEROKEE SMALL LETTER SE;Ll;0;L;;;;;N;;;13CE;;13CE
+AB9F;CHEROKEE SMALL LETTER SI;Ll;0;L;;;;;N;;;13CF;;13CF
+ABA0;CHEROKEE SMALL LETTER SO;Ll;0;L;;;;;N;;;13D0;;13D0
+ABA1;CHEROKEE SMALL LETTER SU;Ll;0;L;;;;;N;;;13D1;;13D1
+ABA2;CHEROKEE SMALL LETTER SV;Ll;0;L;;;;;N;;;13D2;;13D2
+ABA3;CHEROKEE SMALL LETTER DA;Ll;0;L;;;;;N;;;13D3;;13D3
+ABA4;CHEROKEE SMALL LETTER TA;Ll;0;L;;;;;N;;;13D4;;13D4
+ABA5;CHEROKEE SMALL LETTER DE;Ll;0;L;;;;;N;;;13D5;;13D5
+ABA6;CHEROKEE SMALL LETTER TE;Ll;0;L;;;;;N;;;13D6;;13D6
+ABA7;CHEROKEE SMALL LETTER DI;Ll;0;L;;;;;N;;;13D7;;13D7
+ABA8;CHEROKEE SMALL LETTER TI;Ll;0;L;;;;;N;;;13D8;;13D8
+ABA9;CHEROKEE SMALL LETTER DO;Ll;0;L;;;;;N;;;13D9;;13D9
+ABAA;CHEROKEE SMALL LETTER DU;Ll;0;L;;;;;N;;;13DA;;13DA
+ABAB;CHEROKEE SMALL LETTER DV;Ll;0;L;;;;;N;;;13DB;;13DB
+ABAC;CHEROKEE SMALL LETTER DLA;Ll;0;L;;;;;N;;;13DC;;13DC
+ABAD;CHEROKEE SMALL LETTER TLA;Ll;0;L;;;;;N;;;13DD;;13DD
+ABAE;CHEROKEE SMALL LETTER TLE;Ll;0;L;;;;;N;;;13DE;;13DE
+ABAF;CHEROKEE SMALL LETTER TLI;Ll;0;L;;;;;N;;;13DF;;13DF
+ABB0;CHEROKEE SMALL LETTER TLO;Ll;0;L;;;;;N;;;13E0;;13E0
+ABB1;CHEROKEE SMALL LETTER TLU;Ll;0;L;;;;;N;;;13E1;;13E1
+ABB2;CHEROKEE SMALL LETTER TLV;Ll;0;L;;;;;N;;;13E2;;13E2
+ABB3;CHEROKEE SMALL LETTER TSA;Ll;0;L;;;;;N;;;13E3;;13E3
+ABB4;CHEROKEE SMALL LETTER TSE;Ll;0;L;;;;;N;;;13E4;;13E4
+ABB5;CHEROKEE SMALL LETTER TSI;Ll;0;L;;;;;N;;;13E5;;13E5
+ABB6;CHEROKEE SMALL LETTER TSO;Ll;0;L;;;;;N;;;13E6;;13E6
+ABB7;CHEROKEE SMALL LETTER TSU;Ll;0;L;;;;;N;;;13E7;;13E7
+ABB8;CHEROKEE SMALL LETTER TSV;Ll;0;L;;;;;N;;;13E8;;13E8
+ABB9;CHEROKEE SMALL LETTER WA;Ll;0;L;;;;;N;;;13E9;;13E9
+ABBA;CHEROKEE SMALL LETTER WE;Ll;0;L;;;;;N;;;13EA;;13EA
+ABBB;CHEROKEE SMALL LETTER WI;Ll;0;L;;;;;N;;;13EB;;13EB
+ABBC;CHEROKEE SMALL LETTER WO;Ll;0;L;;;;;N;;;13EC;;13EC
+ABBD;CHEROKEE SMALL LETTER WU;Ll;0;L;;;;;N;;;13ED;;13ED
+ABBE;CHEROKEE SMALL LETTER WV;Ll;0;L;;;;;N;;;13EE;;13EE
+ABBF;CHEROKEE SMALL LETTER YA;Ll;0;L;;;;;N;;;13EF;;13EF
ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;;
ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;;
ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;;
@@ -15944,6 +16058,8 @@
FE2B;COMBINING MACRON LEFT HALF BELOW;Mn;220;NSM;;;;;N;;;;;
FE2C;COMBINING MACRON RIGHT HALF BELOW;Mn;220;NSM;;;;;N;;;;;
FE2D;COMBINING CONJOINING MACRON BELOW;Mn;220;NSM;;;;;N;;;;;
+FE2E;COMBINING CYRILLIC TITLO LEFT HALF;Mn;230;NSM;;;;;N;;;;;
+FE2F;COMBINING CYRILLIC TITLO RIGHT HALF;Mn;230;NSM;;;;;N;;;;;
FE30;PRESENTATION FORM FOR VERTICAL TWO DOT LEADER;Po;0;ON;<vertical> 2025;;;;N;GLYPH FOR VERTICAL TWO DOT LEADER;;;;
FE31;PRESENTATION FORM FOR VERTICAL EM DASH;Pd;0;ON;<vertical> 2014;;;;N;GLYPH FOR VERTICAL EM DASH;;;;
FE32;PRESENTATION FORM FOR VERTICAL EN DASH;Pd;0;ON;<vertical> 2013;;;;N;GLYPH FOR VERTICAL EN DASH;;;;
@@ -17830,6 +17946,32 @@
108AD;NABATAEAN NUMBER TEN;No;0;R;;;;10;N;;;;;
108AE;NABATAEAN NUMBER TWENTY;No;0;R;;;;20;N;;;;;
108AF;NABATAEAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+108E0;HATRAN LETTER ALEPH;Lo;0;R;;;;;N;;;;;
+108E1;HATRAN LETTER BETH;Lo;0;R;;;;;N;;;;;
+108E2;HATRAN LETTER GIMEL;Lo;0;R;;;;;N;;;;;
+108E3;HATRAN LETTER DALETH-RESH;Lo;0;R;;;;;N;;;;;
+108E4;HATRAN LETTER HE;Lo;0;R;;;;;N;;;;;
+108E5;HATRAN LETTER WAW;Lo;0;R;;;;;N;;;;;
+108E6;HATRAN LETTER ZAYN;Lo;0;R;;;;;N;;;;;
+108E7;HATRAN LETTER HETH;Lo;0;R;;;;;N;;;;;
+108E8;HATRAN LETTER TETH;Lo;0;R;;;;;N;;;;;
+108E9;HATRAN LETTER YODH;Lo;0;R;;;;;N;;;;;
+108EA;HATRAN LETTER KAPH;Lo;0;R;;;;;N;;;;;
+108EB;HATRAN LETTER LAMEDH;Lo;0;R;;;;;N;;;;;
+108EC;HATRAN LETTER MEM;Lo;0;R;;;;;N;;;;;
+108ED;HATRAN LETTER NUN;Lo;0;R;;;;;N;;;;;
+108EE;HATRAN LETTER SAMEKH;Lo;0;R;;;;;N;;;;;
+108EF;HATRAN LETTER AYN;Lo;0;R;;;;;N;;;;;
+108F0;HATRAN LETTER PE;Lo;0;R;;;;;N;;;;;
+108F1;HATRAN LETTER SADHE;Lo;0;R;;;;;N;;;;;
+108F2;HATRAN LETTER QOPH;Lo;0;R;;;;;N;;;;;
+108F4;HATRAN LETTER SHIN;Lo;0;R;;;;;N;;;;;
+108F5;HATRAN LETTER TAW;Lo;0;R;;;;;N;;;;;
+108FB;HATRAN NUMBER ONE;No;0;R;;;;1;N;;;;;
+108FC;HATRAN NUMBER FIVE;No;0;R;;;;5;N;;;;;
+108FD;HATRAN NUMBER TEN;No;0;R;;;;10;N;;;;;
+108FE;HATRAN NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+108FF;HATRAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
10900;PHOENICIAN LETTER ALF;Lo;0;R;;;;;N;;;;;
10901;PHOENICIAN LETTER BET;Lo;0;R;;;;;N;;;;;
10902;PHOENICIAN LETTER GAML;Lo;0;R;;;;;N;;;;;
@@ -17942,8 +18084,72 @@
109B5;MEROITIC CURSIVE LETTER TE;Lo;0;R;;;;;N;;;;;
109B6;MEROITIC CURSIVE LETTER TO;Lo;0;R;;;;;N;;;;;
109B7;MEROITIC CURSIVE LETTER DA;Lo;0;R;;;;;N;;;;;
+109BC;MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS;No;0;R;;;;11/12;N;;;;;
+109BD;MEROITIC CURSIVE FRACTION ONE HALF;No;0;R;;;;1/2;N;;;;;
109BE;MEROITIC CURSIVE LOGOGRAM RMT;Lo;0;R;;;;;N;;;;;
109BF;MEROITIC CURSIVE LOGOGRAM IMN;Lo;0;R;;;;;N;;;;;
+109C0;MEROITIC CURSIVE NUMBER ONE;No;0;R;;;;1;N;;;;;
+109C1;MEROITIC CURSIVE NUMBER TWO;No;0;R;;;;2;N;;;;;
+109C2;MEROITIC CURSIVE NUMBER THREE;No;0;R;;;;3;N;;;;;
+109C3;MEROITIC CURSIVE NUMBER FOUR;No;0;R;;;;4;N;;;;;
+109C4;MEROITIC CURSIVE NUMBER FIVE;No;0;R;;;;5;N;;;;;
+109C5;MEROITIC CURSIVE NUMBER SIX;No;0;R;;;;6;N;;;;;
+109C6;MEROITIC CURSIVE NUMBER SEVEN;No;0;R;;;;7;N;;;;;
+109C7;MEROITIC CURSIVE NUMBER EIGHT;No;0;R;;;;8;N;;;;;
+109C8;MEROITIC CURSIVE NUMBER NINE;No;0;R;;;;9;N;;;;;
+109C9;MEROITIC CURSIVE NUMBER TEN;No;0;R;;;;10;N;;;;;
+109CA;MEROITIC CURSIVE NUMBER TWENTY;No;0;R;;;;20;N;;;;;
+109CB;MEROITIC CURSIVE NUMBER THIRTY;No;0;R;;;;30;N;;;;;
+109CC;MEROITIC CURSIVE NUMBER FORTY;No;0;R;;;;40;N;;;;;
+109CD;MEROITIC CURSIVE NUMBER FIFTY;No;0;R;;;;50;N;;;;;
+109CE;MEROITIC CURSIVE NUMBER SIXTY;No;0;R;;;;60;N;;;;;
+109CF;MEROITIC CURSIVE NUMBER SEVENTY;No;0;R;;;;70;N;;;;;
+109D2;MEROITIC CURSIVE NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+109D3;MEROITIC CURSIVE NUMBER TWO HUNDRED;No;0;R;;;;200;N;;;;;
+109D4;MEROITIC CURSIVE NUMBER THREE HUNDRED;No;0;R;;;;300;N;;;;;
+109D5;MEROITIC CURSIVE NUMBER FOUR HUNDRED;No;0;R;;;;400;N;;;;;
+109D6;MEROITIC CURSIVE NUMBER FIVE HUNDRED;No;0;R;;;;500;N;;;;;
+109D7;MEROITIC CURSIVE NUMBER SIX HUNDRED;No;0;R;;;;600;N;;;;;
+109D8;MEROITIC CURSIVE NUMBER SEVEN HUNDRED;No;0;R;;;;700;N;;;;;
+109D9;MEROITIC CURSIVE NUMBER EIGHT HUNDRED;No;0;R;;;;800;N;;;;;
+109DA;MEROITIC CURSIVE NUMBER NINE HUNDRED;No;0;R;;;;900;N;;;;;
+109DB;MEROITIC CURSIVE NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
+109DC;MEROITIC CURSIVE NUMBER TWO THOUSAND;No;0;R;;;;2000;N;;;;;
+109DD;MEROITIC CURSIVE NUMBER THREE THOUSAND;No;0;R;;;;3000;N;;;;;
+109DE;MEROITIC CURSIVE NUMBER FOUR THOUSAND;No;0;R;;;;4000;N;;;;;
+109DF;MEROITIC CURSIVE NUMBER FIVE THOUSAND;No;0;R;;;;5000;N;;;;;
+109E0;MEROITIC CURSIVE NUMBER SIX THOUSAND;No;0;R;;;;6000;N;;;;;
+109E1;MEROITIC CURSIVE NUMBER SEVEN THOUSAND;No;0;R;;;;7000;N;;;;;
+109E2;MEROITIC CURSIVE NUMBER EIGHT THOUSAND;No;0;R;;;;8000;N;;;;;
+109E3;MEROITIC CURSIVE NUMBER NINE THOUSAND;No;0;R;;;;9000;N;;;;;
+109E4;MEROITIC CURSIVE NUMBER TEN THOUSAND;No;0;R;;;;10000;N;;;;;
+109E5;MEROITIC CURSIVE NUMBER TWENTY THOUSAND;No;0;R;;;;20000;N;;;;;
+109E6;MEROITIC CURSIVE NUMBER THIRTY THOUSAND;No;0;R;;;;30000;N;;;;;
+109E7;MEROITIC CURSIVE NUMBER FORTY THOUSAND;No;0;R;;;;40000;N;;;;;
+109E8;MEROITIC CURSIVE NUMBER FIFTY THOUSAND;No;0;R;;;;50000;N;;;;;
+109E9;MEROITIC CURSIVE NUMBER SIXTY THOUSAND;No;0;R;;;;60000;N;;;;;
+109EA;MEROITIC CURSIVE NUMBER SEVENTY THOUSAND;No;0;R;;;;70000;N;;;;;
+109EB;MEROITIC CURSIVE NUMBER EIGHTY THOUSAND;No;0;R;;;;80000;N;;;;;
+109EC;MEROITIC CURSIVE NUMBER NINETY THOUSAND;No;0;R;;;;90000;N;;;;;
+109ED;MEROITIC CURSIVE NUMBER ONE HUNDRED THOUSAND;No;0;R;;;;100000;N;;;;;
+109EE;MEROITIC CURSIVE NUMBER TWO HUNDRED THOUSAND;No;0;R;;;;200000;N;;;;;
+109EF;MEROITIC CURSIVE NUMBER THREE HUNDRED THOUSAND;No;0;R;;;;300000;N;;;;;
+109F0;MEROITIC CURSIVE NUMBER FOUR HUNDRED THOUSAND;No;0;R;;;;400000;N;;;;;
+109F1;MEROITIC CURSIVE NUMBER FIVE HUNDRED THOUSAND;No;0;R;;;;500000;N;;;;;
+109F2;MEROITIC CURSIVE NUMBER SIX HUNDRED THOUSAND;No;0;R;;;;600000;N;;;;;
+109F3;MEROITIC CURSIVE NUMBER SEVEN HUNDRED THOUSAND;No;0;R;;;;700000;N;;;;;
+109F4;MEROITIC CURSIVE NUMBER EIGHT HUNDRED THOUSAND;No;0;R;;;;800000;N;;;;;
+109F5;MEROITIC CURSIVE NUMBER NINE HUNDRED THOUSAND;No;0;R;;;;900000;N;;;;;
+109F6;MEROITIC CURSIVE FRACTION ONE TWELFTH;No;0;R;;;;1/12;N;;;;;
+109F7;MEROITIC CURSIVE FRACTION TWO TWELFTHS;No;0;R;;;;2/12;N;;;;;
+109F8;MEROITIC CURSIVE FRACTION THREE TWELFTHS;No;0;R;;;;3/12;N;;;;;
+109F9;MEROITIC CURSIVE FRACTION FOUR TWELFTHS;No;0;R;;;;4/12;N;;;;;
+109FA;MEROITIC CURSIVE FRACTION FIVE TWELFTHS;No;0;R;;;;5/12;N;;;;;
+109FB;MEROITIC CURSIVE FRACTION SIX TWELFTHS;No;0;R;;;;6/12;N;;;;;
+109FC;MEROITIC CURSIVE FRACTION SEVEN TWELFTHS;No;0;R;;;;7/12;N;;;;;
+109FD;MEROITIC CURSIVE FRACTION EIGHT TWELFTHS;No;0;R;;;;8/12;N;;;;;
+109FE;MEROITIC CURSIVE FRACTION NINE TWELFTHS;No;0;R;;;;9/12;N;;;;;
+109FF;MEROITIC CURSIVE FRACTION TEN TWELFTHS;No;0;R;;;;10/12;N;;;;;
10A00;KHAROSHTHI LETTER A;Lo;0;R;;;;;N;;;;;
10A01;KHAROSHTHI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
10A02;KHAROSHTHI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
@@ -18344,6 +18550,114 @@
10C46;OLD TURKIC LETTER YENISEI AET;Lo;0;R;;;;;N;;;;;
10C47;OLD TURKIC LETTER ORKHON OT;Lo;0;R;;;;;N;;;;;
10C48;OLD TURKIC LETTER ORKHON BASH;Lo;0;R;;;;;N;;;;;
+10C80;OLD HUNGARIAN CAPITAL LETTER A;Lu;0;R;;;;;N;;;;10CC0;
+10C81;OLD HUNGARIAN CAPITAL LETTER AA;Lu;0;R;;;;;N;;;;10CC1;
+10C82;OLD HUNGARIAN CAPITAL LETTER EB;Lu;0;R;;;;;N;;;;10CC2;
+10C83;OLD HUNGARIAN CAPITAL LETTER AMB;Lu;0;R;;;;;N;;;;10CC3;
+10C84;OLD HUNGARIAN CAPITAL LETTER EC;Lu;0;R;;;;;N;;;;10CC4;
+10C85;OLD HUNGARIAN CAPITAL LETTER ENC;Lu;0;R;;;;;N;;;;10CC5;
+10C86;OLD HUNGARIAN CAPITAL LETTER ECS;Lu;0;R;;;;;N;;;;10CC6;
+10C87;OLD HUNGARIAN CAPITAL LETTER ED;Lu;0;R;;;;;N;;;;10CC7;
+10C88;OLD HUNGARIAN CAPITAL LETTER AND;Lu;0;R;;;;;N;;;;10CC8;
+10C89;OLD HUNGARIAN CAPITAL LETTER E;Lu;0;R;;;;;N;;;;10CC9;
+10C8A;OLD HUNGARIAN CAPITAL LETTER CLOSE E;Lu;0;R;;;;;N;;;;10CCA;
+10C8B;OLD HUNGARIAN CAPITAL LETTER EE;Lu;0;R;;;;;N;;;;10CCB;
+10C8C;OLD HUNGARIAN CAPITAL LETTER EF;Lu;0;R;;;;;N;;;;10CCC;
+10C8D;OLD HUNGARIAN CAPITAL LETTER EG;Lu;0;R;;;;;N;;;;10CCD;
+10C8E;OLD HUNGARIAN CAPITAL LETTER EGY;Lu;0;R;;;;;N;;;;10CCE;
+10C8F;OLD HUNGARIAN CAPITAL LETTER EH;Lu;0;R;;;;;N;;;;10CCF;
+10C90;OLD HUNGARIAN CAPITAL LETTER I;Lu;0;R;;;;;N;;;;10CD0;
+10C91;OLD HUNGARIAN CAPITAL LETTER II;Lu;0;R;;;;;N;;;;10CD1;
+10C92;OLD HUNGARIAN CAPITAL LETTER EJ;Lu;0;R;;;;;N;;;;10CD2;
+10C93;OLD HUNGARIAN CAPITAL LETTER EK;Lu;0;R;;;;;N;;;;10CD3;
+10C94;OLD HUNGARIAN CAPITAL LETTER AK;Lu;0;R;;;;;N;;;;10CD4;
+10C95;OLD HUNGARIAN CAPITAL LETTER UNK;Lu;0;R;;;;;N;;;;10CD5;
+10C96;OLD HUNGARIAN CAPITAL LETTER EL;Lu;0;R;;;;;N;;;;10CD6;
+10C97;OLD HUNGARIAN CAPITAL LETTER ELY;Lu;0;R;;;;;N;;;;10CD7;
+10C98;OLD HUNGARIAN CAPITAL LETTER EM;Lu;0;R;;;;;N;;;;10CD8;
+10C99;OLD HUNGARIAN CAPITAL LETTER EN;Lu;0;R;;;;;N;;;;10CD9;
+10C9A;OLD HUNGARIAN CAPITAL LETTER ENY;Lu;0;R;;;;;N;;;;10CDA;
+10C9B;OLD HUNGARIAN CAPITAL LETTER O;Lu;0;R;;;;;N;;;;10CDB;
+10C9C;OLD HUNGARIAN CAPITAL LETTER OO;Lu;0;R;;;;;N;;;;10CDC;
+10C9D;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG OE;Lu;0;R;;;;;N;;;;10CDD;
+10C9E;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA OE;Lu;0;R;;;;;N;;;;10CDE;
+10C9F;OLD HUNGARIAN CAPITAL LETTER OEE;Lu;0;R;;;;;N;;;;10CDF;
+10CA0;OLD HUNGARIAN CAPITAL LETTER EP;Lu;0;R;;;;;N;;;;10CE0;
+10CA1;OLD HUNGARIAN CAPITAL LETTER EMP;Lu;0;R;;;;;N;;;;10CE1;
+10CA2;OLD HUNGARIAN CAPITAL LETTER ER;Lu;0;R;;;;;N;;;;10CE2;
+10CA3;OLD HUNGARIAN CAPITAL LETTER SHORT ER;Lu;0;R;;;;;N;;;;10CE3;
+10CA4;OLD HUNGARIAN CAPITAL LETTER ES;Lu;0;R;;;;;N;;;;10CE4;
+10CA5;OLD HUNGARIAN CAPITAL LETTER ESZ;Lu;0;R;;;;;N;;;;10CE5;
+10CA6;OLD HUNGARIAN CAPITAL LETTER ET;Lu;0;R;;;;;N;;;;10CE6;
+10CA7;OLD HUNGARIAN CAPITAL LETTER ENT;Lu;0;R;;;;;N;;;;10CE7;
+10CA8;OLD HUNGARIAN CAPITAL LETTER ETY;Lu;0;R;;;;;N;;;;10CE8;
+10CA9;OLD HUNGARIAN CAPITAL LETTER ECH;Lu;0;R;;;;;N;;;;10CE9;
+10CAA;OLD HUNGARIAN CAPITAL LETTER U;Lu;0;R;;;;;N;;;;10CEA;
+10CAB;OLD HUNGARIAN CAPITAL LETTER UU;Lu;0;R;;;;;N;;;;10CEB;
+10CAC;OLD HUNGARIAN CAPITAL LETTER NIKOLSBURG UE;Lu;0;R;;;;;N;;;;10CEC;
+10CAD;OLD HUNGARIAN CAPITAL LETTER RUDIMENTA UE;Lu;0;R;;;;;N;;;;10CED;
+10CAE;OLD HUNGARIAN CAPITAL LETTER EV;Lu;0;R;;;;;N;;;;10CEE;
+10CAF;OLD HUNGARIAN CAPITAL LETTER EZ;Lu;0;R;;;;;N;;;;10CEF;
+10CB0;OLD HUNGARIAN CAPITAL LETTER EZS;Lu;0;R;;;;;N;;;;10CF0;
+10CB1;OLD HUNGARIAN CAPITAL LETTER ENT-SHAPED SIGN;Lu;0;R;;;;;N;;;;10CF1;
+10CB2;OLD HUNGARIAN CAPITAL LETTER US;Lu;0;R;;;;;N;;;;10CF2;
+10CC0;OLD HUNGARIAN SMALL LETTER A;Ll;0;R;;;;;N;;;10C80;;10C80
+10CC1;OLD HUNGARIAN SMALL LETTER AA;Ll;0;R;;;;;N;;;10C81;;10C81
+10CC2;OLD HUNGARIAN SMALL LETTER EB;Ll;0;R;;;;;N;;;10C82;;10C82
+10CC3;OLD HUNGARIAN SMALL LETTER AMB;Ll;0;R;;;;;N;;;10C83;;10C83
+10CC4;OLD HUNGARIAN SMALL LETTER EC;Ll;0;R;;;;;N;;;10C84;;10C84
+10CC5;OLD HUNGARIAN SMALL LETTER ENC;Ll;0;R;;;;;N;;;10C85;;10C85
+10CC6;OLD HUNGARIAN SMALL LETTER ECS;Ll;0;R;;;;;N;;;10C86;;10C86
+10CC7;OLD HUNGARIAN SMALL LETTER ED;Ll;0;R;;;;;N;;;10C87;;10C87
+10CC8;OLD HUNGARIAN SMALL LETTER AND;Ll;0;R;;;;;N;;;10C88;;10C88
+10CC9;OLD HUNGARIAN SMALL LETTER E;Ll;0;R;;;;;N;;;10C89;;10C89
+10CCA;OLD HUNGARIAN SMALL LETTER CLOSE E;Ll;0;R;;;;;N;;;10C8A;;10C8A
+10CCB;OLD HUNGARIAN SMALL LETTER EE;Ll;0;R;;;;;N;;;10C8B;;10C8B
+10CCC;OLD HUNGARIAN SMALL LETTER EF;Ll;0;R;;;;;N;;;10C8C;;10C8C
+10CCD;OLD HUNGARIAN SMALL LETTER EG;Ll;0;R;;;;;N;;;10C8D;;10C8D
+10CCE;OLD HUNGARIAN SMALL LETTER EGY;Ll;0;R;;;;;N;;;10C8E;;10C8E
+10CCF;OLD HUNGARIAN SMALL LETTER EH;Ll;0;R;;;;;N;;;10C8F;;10C8F
+10CD0;OLD HUNGARIAN SMALL LETTER I;Ll;0;R;;;;;N;;;10C90;;10C90
+10CD1;OLD HUNGARIAN SMALL LETTER II;Ll;0;R;;;;;N;;;10C91;;10C91
+10CD2;OLD HUNGARIAN SMALL LETTER EJ;Ll;0;R;;;;;N;;;10C92;;10C92
+10CD3;OLD HUNGARIAN SMALL LETTER EK;Ll;0;R;;;;;N;;;10C93;;10C93
+10CD4;OLD HUNGARIAN SMALL LETTER AK;Ll;0;R;;;;;N;;;10C94;;10C94
+10CD5;OLD HUNGARIAN SMALL LETTER UNK;Ll;0;R;;;;;N;;;10C95;;10C95
+10CD6;OLD HUNGARIAN SMALL LETTER EL;Ll;0;R;;;;;N;;;10C96;;10C96
+10CD7;OLD HUNGARIAN SMALL LETTER ELY;Ll;0;R;;;;;N;;;10C97;;10C97
+10CD8;OLD HUNGARIAN SMALL LETTER EM;Ll;0;R;;;;;N;;;10C98;;10C98
+10CD9;OLD HUNGARIAN SMALL LETTER EN;Ll;0;R;;;;;N;;;10C99;;10C99
+10CDA;OLD HUNGARIAN SMALL LETTER ENY;Ll;0;R;;;;;N;;;10C9A;;10C9A
+10CDB;OLD HUNGARIAN SMALL LETTER O;Ll;0;R;;;;;N;;;10C9B;;10C9B
+10CDC;OLD HUNGARIAN SMALL LETTER OO;Ll;0;R;;;;;N;;;10C9C;;10C9C
+10CDD;OLD HUNGARIAN SMALL LETTER NIKOLSBURG OE;Ll;0;R;;;;;N;;;10C9D;;10C9D
+10CDE;OLD HUNGARIAN SMALL LETTER RUDIMENTA OE;Ll;0;R;;;;;N;;;10C9E;;10C9E
+10CDF;OLD HUNGARIAN SMALL LETTER OEE;Ll;0;R;;;;;N;;;10C9F;;10C9F
+10CE0;OLD HUNGARIAN SMALL LETTER EP;Ll;0;R;;;;;N;;;10CA0;;10CA0
+10CE1;OLD HUNGARIAN SMALL LETTER EMP;Ll;0;R;;;;;N;;;10CA1;;10CA1
+10CE2;OLD HUNGARIAN SMALL LETTER ER;Ll;0;R;;;;;N;;;10CA2;;10CA2
+10CE3;OLD HUNGARIAN SMALL LETTER SHORT ER;Ll;0;R;;;;;N;;;10CA3;;10CA3
+10CE4;OLD HUNGARIAN SMALL LETTER ES;Ll;0;R;;;;;N;;;10CA4;;10CA4
+10CE5;OLD HUNGARIAN SMALL LETTER ESZ;Ll;0;R;;;;;N;;;10CA5;;10CA5
+10CE6;OLD HUNGARIAN SMALL LETTER ET;Ll;0;R;;;;;N;;;10CA6;;10CA6
+10CE7;OLD HUNGARIAN SMALL LETTER ENT;Ll;0;R;;;;;N;;;10CA7;;10CA7
+10CE8;OLD HUNGARIAN SMALL LETTER ETY;Ll;0;R;;;;;N;;;10CA8;;10CA8
+10CE9;OLD HUNGARIAN SMALL LETTER ECH;Ll;0;R;;;;;N;;;10CA9;;10CA9
+10CEA;OLD HUNGARIAN SMALL LETTER U;Ll;0;R;;;;;N;;;10CAA;;10CAA
+10CEB;OLD HUNGARIAN SMALL LETTER UU;Ll;0;R;;;;;N;;;10CAB;;10CAB
+10CEC;OLD HUNGARIAN SMALL LETTER NIKOLSBURG UE;Ll;0;R;;;;;N;;;10CAC;;10CAC
+10CED;OLD HUNGARIAN SMALL LETTER RUDIMENTA UE;Ll;0;R;;;;;N;;;10CAD;;10CAD
+10CEE;OLD HUNGARIAN SMALL LETTER EV;Ll;0;R;;;;;N;;;10CAE;;10CAE
+10CEF;OLD HUNGARIAN SMALL LETTER EZ;Ll;0;R;;;;;N;;;10CAF;;10CAF
+10CF0;OLD HUNGARIAN SMALL LETTER EZS;Ll;0;R;;;;;N;;;10CB0;;10CB0
+10CF1;OLD HUNGARIAN SMALL LETTER ENT-SHAPED SIGN;Ll;0;R;;;;;N;;;10CB1;;10CB1
+10CF2;OLD HUNGARIAN SMALL LETTER US;Ll;0;R;;;;;N;;;10CB2;;10CB2
+10CFA;OLD HUNGARIAN NUMBER ONE;No;0;R;;;;1;N;;;;;
+10CFB;OLD HUNGARIAN NUMBER FIVE;No;0;R;;;;5;N;;;;;
+10CFC;OLD HUNGARIAN NUMBER TEN;No;0;R;;;;10;N;;;;;
+10CFD;OLD HUNGARIAN NUMBER FIFTY;No;0;R;;;;50;N;;;;;
+10CFE;OLD HUNGARIAN NUMBER ONE HUNDRED;No;0;R;;;;100;N;;;;;
+10CFF;OLD HUNGARIAN NUMBER ONE THOUSAND;No;0;R;;;;1000;N;;;;;
10E60;RUMI DIGIT ONE;No;0;AN;;;1;1;N;;;;;
10E61;RUMI DIGIT TWO;No;0;AN;;;2;2;N;;;;;
10E62;RUMI DIGIT THREE;No;0;AN;;;3;3;N;;;;;
@@ -18764,6 +19078,10 @@
111C6;SHARADA DOUBLE DANDA;Po;0;L;;;;;N;;;;;
111C7;SHARADA ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
111C8;SHARADA SEPARATOR;Po;0;L;;;;;N;;;;;
+111C9;SHARADA SANDHI MARK;Po;0;L;;;;;N;;;;;
+111CA;SHARADA SIGN NUKTA;Mn;7;NSM;;;;;N;;;;;
+111CB;SHARADA VOWEL MODIFIER MARK;Mn;0;NSM;;;;;N;;;;;
+111CC;SHARADA EXTRA SHORT VOWEL MARK;Mn;0;NSM;;;;;N;;;;;
111CD;SHARADA SUTRA MARK;Po;0;L;;;;;N;;;;;
111D0;SHARADA DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
111D1;SHARADA DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
@@ -18776,6 +19094,11 @@
111D8;SHARADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
111D9;SHARADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
111DA;SHARADA EKAM;Lo;0;L;;;;;N;;;;;
+111DB;SHARADA SIGN SIDDHAM;Po;0;L;;;;;N;;;;;
+111DC;SHARADA HEADSTROKE;Lo;0;L;;;;;N;;;;;
+111DD;SHARADA CONTINUATION SIGN;Po;0;L;;;;;N;;;;;
+111DE;SHARADA SECTION MARK-1;Po;0;L;;;;;N;;;;;
+111DF;SHARADA SECTION MARK-2;Po;0;L;;;;;N;;;;;
111E1;SINHALA ARCHAIC DIGIT ONE;No;0;L;;;;1;N;;;;;
111E2;SINHALA ARCHAIC DIGIT TWO;No;0;L;;;;2;N;;;;;
111E3;SINHALA ARCHAIC DIGIT THREE;No;0;L;;;;3;N;;;;;
@@ -18857,6 +19180,44 @@
1123B;KHOJKI SECTION MARK;Po;0;L;;;;;N;;;;;
1123C;KHOJKI DOUBLE SECTION MARK;Po;0;L;;;;;N;;;;;
1123D;KHOJKI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;;
+11280;MULTANI LETTER A;Lo;0;L;;;;;N;;;;;
+11281;MULTANI LETTER I;Lo;0;L;;;;;N;;;;;
+11282;MULTANI LETTER U;Lo;0;L;;;;;N;;;;;
+11283;MULTANI LETTER E;Lo;0;L;;;;;N;;;;;
+11284;MULTANI LETTER KA;Lo;0;L;;;;;N;;;;;
+11285;MULTANI LETTER KHA;Lo;0;L;;;;;N;;;;;
+11286;MULTANI LETTER GA;Lo;0;L;;;;;N;;;;;
+11288;MULTANI LETTER GHA;Lo;0;L;;;;;N;;;;;
+1128A;MULTANI LETTER CA;Lo;0;L;;;;;N;;;;;
+1128B;MULTANI LETTER CHA;Lo;0;L;;;;;N;;;;;
+1128C;MULTANI LETTER JA;Lo;0;L;;;;;N;;;;;
+1128D;MULTANI LETTER JJA;Lo;0;L;;;;;N;;;;;
+1128F;MULTANI LETTER NYA;Lo;0;L;;;;;N;;;;;
+11290;MULTANI LETTER TTA;Lo;0;L;;;;;N;;;;;
+11291;MULTANI LETTER TTHA;Lo;0;L;;;;;N;;;;;
+11292;MULTANI LETTER DDA;Lo;0;L;;;;;N;;;;;
+11293;MULTANI LETTER DDDA;Lo;0;L;;;;;N;;;;;
+11294;MULTANI LETTER DDHA;Lo;0;L;;;;;N;;;;;
+11295;MULTANI LETTER NNA;Lo;0;L;;;;;N;;;;;
+11296;MULTANI LETTER TA;Lo;0;L;;;;;N;;;;;
+11297;MULTANI LETTER THA;Lo;0;L;;;;;N;;;;;
+11298;MULTANI LETTER DA;Lo;0;L;;;;;N;;;;;
+11299;MULTANI LETTER DHA;Lo;0;L;;;;;N;;;;;
+1129A;MULTANI LETTER NA;Lo;0;L;;;;;N;;;;;
+1129B;MULTANI LETTER PA;Lo;0;L;;;;;N;;;;;
+1129C;MULTANI LETTER PHA;Lo;0;L;;;;;N;;;;;
+1129D;MULTANI LETTER BA;Lo;0;L;;;;;N;;;;;
+1129F;MULTANI LETTER BHA;Lo;0;L;;;;;N;;;;;
+112A0;MULTANI LETTER MA;Lo;0;L;;;;;N;;;;;
+112A1;MULTANI LETTER YA;Lo;0;L;;;;;N;;;;;
+112A2;MULTANI LETTER RA;Lo;0;L;;;;;N;;;;;
+112A3;MULTANI LETTER LA;Lo;0;L;;;;;N;;;;;
+112A4;MULTANI LETTER VA;Lo;0;L;;;;;N;;;;;
+112A5;MULTANI LETTER SA;Lo;0;L;;;;;N;;;;;
+112A6;MULTANI LETTER HA;Lo;0;L;;;;;N;;;;;
+112A7;MULTANI LETTER RRA;Lo;0;L;;;;;N;;;;;
+112A8;MULTANI LETTER RHA;Lo;0;L;;;;;N;;;;;
+112A9;MULTANI SECTION MARK;Po;0;L;;;;;N;;;;;
112B0;KHUDAWADI LETTER A;Lo;0;L;;;;;N;;;;;
112B1;KHUDAWADI LETTER AA;Lo;0;L;;;;;N;;;;;
112B2;KHUDAWADI LETTER I;Lo;0;L;;;;;N;;;;;
@@ -18926,6 +19287,7 @@
112F7;KHUDAWADI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
112F8;KHUDAWADI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
112F9;KHUDAWADI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+11300;GRANTHA SIGN COMBINING ANUSVARA ABOVE;Mn;0;NSM;;;;;N;;;;;
11301;GRANTHA SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;;
11302;GRANTHA SIGN ANUSVARA;Mc;0;L;;;;;N;;;;;
11303;GRANTHA SIGN VISARGA;Mc;0;L;;;;;N;;;;;
@@ -18989,6 +19351,7 @@
1134B;GRANTHA VOWEL SIGN OO;Mc;0;L;11347 1133E;;;;N;;;;;
1134C;GRANTHA VOWEL SIGN AU;Mc;0;L;11347 11357;;;;N;;;;;
1134D;GRANTHA SIGN VIRAMA;Mc;9;L;;;;;N;;;;;
+11350;GRANTHA OM;Lo;0;L;;;;;N;;;;;
11357;GRANTHA AU LENGTH MARK;Mc;0;L;;;;;N;;;;;
1135D;GRANTHA SIGN PLUTA;Lo;0;L;;;;;N;;;;;
1135E;GRANTHA LETTER VEDIC ANUSVARA;Lo;0;L;;;;;N;;;;;
@@ -19163,6 +19526,26 @@
115C7;SIDDHAM REPETITION MARK-2;Po;0;L;;;;;N;;;;;
115C8;SIDDHAM REPETITION MARK-3;Po;0;L;;;;;N;;;;;
115C9;SIDDHAM END OF TEXT MARK;Po;0;L;;;;;N;;;;;
+115CA;SIDDHAM SECTION MARK WITH TRIDENT AND U-SHAPED ORNAMENTS;Po;0;L;;;;;N;;;;;
+115CB;SIDDHAM SECTION MARK WITH TRIDENT AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;;
+115CC;SIDDHAM SECTION MARK WITH RAYS AND DOTTED CRESCENTS;Po;0;L;;;;;N;;;;;
+115CD;SIDDHAM SECTION MARK WITH RAYS AND DOTTED DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;;
+115CE;SIDDHAM SECTION MARK WITH RAYS AND DOTTED TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;;
+115CF;SIDDHAM SECTION MARK DOUBLE RING;Po;0;L;;;;;N;;;;;
+115D0;SIDDHAM SECTION MARK DOUBLE RING WITH RAYS;Po;0;L;;;;;N;;;;;
+115D1;SIDDHAM SECTION MARK WITH DOUBLE CRESCENTS;Po;0;L;;;;;N;;;;;
+115D2;SIDDHAM SECTION MARK WITH TRIPLE CRESCENTS;Po;0;L;;;;;N;;;;;
+115D3;SIDDHAM SECTION MARK WITH QUADRUPLE CRESCENTS;Po;0;L;;;;;N;;;;;
+115D4;SIDDHAM SECTION MARK WITH SEPTUPLE CRESCENTS;Po;0;L;;;;;N;;;;;
+115D5;SIDDHAM SECTION MARK WITH CIRCLES AND RAYS;Po;0;L;;;;;N;;;;;
+115D6;SIDDHAM SECTION MARK WITH CIRCLES AND TWO ENCLOSURES;Po;0;L;;;;;N;;;;;
+115D7;SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES;Po;0;L;;;;;N;;;;;
+115D8;SIDDHAM LETTER THREE-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;;
+115D9;SIDDHAM LETTER TWO-CIRCLE ALTERNATE I;Lo;0;L;;;;;N;;;;;
+115DA;SIDDHAM LETTER TWO-CIRCLE ALTERNATE II;Lo;0;L;;;;;N;;;;;
+115DB;SIDDHAM LETTER ALTERNATE U;Lo;0;L;;;;;N;;;;;
+115DC;SIDDHAM VOWEL SIGN ALTERNATE U;Mn;0;NSM;;;;;N;;;;;
+115DD;SIDDHAM VOWEL SIGN ALTERNATE UU;Mn;0;NSM;;;;;N;;;;;
11600;MODI LETTER A;Lo;0;L;;;;;N;;;;;
11601;MODI LETTER AA;Lo;0;L;;;;;N;;;;;
11602;MODI LETTER I;Lo;0;L;;;;;N;;;;;
@@ -19308,6 +19691,63 @@
116C7;TAKRI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
116C8;TAKRI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
116C9;TAKRI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+11700;AHOM LETTER KA;Lo;0;L;;;;;N;;;;;
+11701;AHOM LETTER KHA;Lo;0;L;;;;;N;;;;;
+11702;AHOM LETTER NGA;Lo;0;L;;;;;N;;;;;
+11703;AHOM LETTER NA;Lo;0;L;;;;;N;;;;;
+11704;AHOM LETTER TA;Lo;0;L;;;;;N;;;;;
+11705;AHOM LETTER ALTERNATE TA;Lo;0;L;;;;;N;;;;;
+11706;AHOM LETTER PA;Lo;0;L;;;;;N;;;;;
+11707;AHOM LETTER PHA;Lo;0;L;;;;;N;;;;;
+11708;AHOM LETTER BA;Lo;0;L;;;;;N;;;;;
+11709;AHOM LETTER MA;Lo;0;L;;;;;N;;;;;
+1170A;AHOM LETTER JA;Lo;0;L;;;;;N;;;;;
+1170B;AHOM LETTER CHA;Lo;0;L;;;;;N;;;;;
+1170C;AHOM LETTER THA;Lo;0;L;;;;;N;;;;;
+1170D;AHOM LETTER RA;Lo;0;L;;;;;N;;;;;
+1170E;AHOM LETTER LA;Lo;0;L;;;;;N;;;;;
+1170F;AHOM LETTER SA;Lo;0;L;;;;;N;;;;;
+11710;AHOM LETTER NYA;Lo;0;L;;;;;N;;;;;
+11711;AHOM LETTER HA;Lo;0;L;;;;;N;;;;;
+11712;AHOM LETTER A;Lo;0;L;;;;;N;;;;;
+11713;AHOM LETTER DA;Lo;0;L;;;;;N;;;;;
+11714;AHOM LETTER DHA;Lo;0;L;;;;;N;;;;;
+11715;AHOM LETTER GA;Lo;0;L;;;;;N;;;;;
+11716;AHOM LETTER ALTERNATE GA;Lo;0;L;;;;;N;;;;;
+11717;AHOM LETTER GHA;Lo;0;L;;;;;N;;;;;
+11718;AHOM LETTER BHA;Lo;0;L;;;;;N;;;;;
+11719;AHOM LETTER JHA;Lo;0;L;;;;;N;;;;;
+1171D;AHOM CONSONANT SIGN MEDIAL LA;Mn;0;NSM;;;;;N;;;;;
+1171E;AHOM CONSONANT SIGN MEDIAL RA;Mn;0;NSM;;;;;N;;;;;
+1171F;AHOM CONSONANT SIGN MEDIAL LIGATING RA;Mn;0;NSM;;;;;N;;;;;
+11720;AHOM VOWEL SIGN A;Mc;0;L;;;;;N;;;;;
+11721;AHOM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;;
+11722;AHOM VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;;
+11723;AHOM VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;;
+11724;AHOM VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;;
+11725;AHOM VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;;
+11726;AHOM VOWEL SIGN E;Mc;0;L;;;;;N;;;;;
+11727;AHOM VOWEL SIGN AW;Mn;0;NSM;;;;;N;;;;;
+11728;AHOM VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;;
+11729;AHOM VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;;
+1172A;AHOM VOWEL SIGN AM;Mn;0;NSM;;;;;N;;;;;
+1172B;AHOM SIGN KILLER;Mn;9;NSM;;;;;N;;;;;
+11730;AHOM DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;;
+11731;AHOM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;;
+11732;AHOM DIGIT TWO;Nd;0;L;;2;2;2;N;;;;;
+11733;AHOM DIGIT THREE;Nd;0;L;;3;3;3;N;;;;;
+11734;AHOM DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;;
+11735;AHOM DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;;
+11736;AHOM DIGIT SIX;Nd;0;L;;6;6;6;N;;;;;
+11737;AHOM DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;;
+11738;AHOM DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;;
+11739;AHOM DIGIT NINE;Nd;0;L;;9;9;9;N;;;;;
+1173A;AHOM NUMBER TEN;No;0;L;;;;10;N;;;;;
+1173B;AHOM NUMBER TWENTY;No;0;L;;;;20;N;;;;;
+1173C;AHOM SIGN SMALL SECTION;Po;0;L;;;;;N;;;;;
+1173D;AHOM SIGN SECTION;Po;0;L;;;;;N;;;;;
+1173E;AHOM SIGN RULAI;Po;0;L;;;;;N;;;;;
+1173F;AHOM SYMBOL VI;So;0;L;;;;;N;;;;;
118A0;WARANG CITI CAPITAL LETTER NGAA;Lu;0;L;;;;;N;;;;118C0;
118A1;WARANG CITI CAPITAL LETTER A;Lu;0;L;;;;;N;;;;118C1;
118A2;WARANG CITI CAPITAL LETTER WI;Lu;0;L;;;;;N;;;;118C2;
@@ -20370,6 +20810,7 @@
12396;CUNEIFORM SIGN SAG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
12397;CUNEIFORM SIGN TI2;Lo;0;L;;;;;N;;;;;
12398;CUNEIFORM SIGN UM TIMES ME;Lo;0;L;;;;;N;;;;;
+12399;CUNEIFORM SIGN U U;Lo;0;L;;;;;N;;;;;
12400;CUNEIFORM NUMERIC SIGN TWO ASH;Nl;0;L;;;;2;N;;;;;
12401;CUNEIFORM NUMERIC SIGN THREE ASH;Nl;0;L;;;;3;N;;;;;
12402;CUNEIFORM NUMERIC SIGN FOUR ASH;Nl;0;L;;;;4;N;;;;;
@@ -20486,6 +20927,202 @@
12472;CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON;Po;0;L;;;;;N;;;;;
12473;CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON;Po;0;L;;;;;N;;;;;
12474;CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON;Po;0;L;;;;;N;;;;;
+12480;CUNEIFORM SIGN AB TIMES NUN TENU;Lo;0;L;;;;;N;;;;;
+12481;CUNEIFORM SIGN AB TIMES SHU2;Lo;0;L;;;;;N;;;;;
+12482;CUNEIFORM SIGN AD TIMES ESH2;Lo;0;L;;;;;N;;;;;
+12483;CUNEIFORM SIGN BAD TIMES DISH TENU;Lo;0;L;;;;;N;;;;;
+12484;CUNEIFORM SIGN BAHAR2 TIMES AB2;Lo;0;L;;;;;N;;;;;
+12485;CUNEIFORM SIGN BAHAR2 TIMES NI;Lo;0;L;;;;;N;;;;;
+12486;CUNEIFORM SIGN BAHAR2 TIMES ZA;Lo;0;L;;;;;N;;;;;
+12487;CUNEIFORM SIGN BU OVER BU TIMES NA2;Lo;0;L;;;;;N;;;;;
+12488;CUNEIFORM SIGN DA TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12489;CUNEIFORM SIGN DAG TIMES KUR;Lo;0;L;;;;;N;;;;;
+1248A;CUNEIFORM SIGN DIM TIMES IGI;Lo;0;L;;;;;N;;;;;
+1248B;CUNEIFORM SIGN DIM TIMES U U U;Lo;0;L;;;;;N;;;;;
+1248C;CUNEIFORM SIGN DIM2 TIMES UD;Lo;0;L;;;;;N;;;;;
+1248D;CUNEIFORM SIGN DUG TIMES ANSHE;Lo;0;L;;;;;N;;;;;
+1248E;CUNEIFORM SIGN DUG TIMES ASH;Lo;0;L;;;;;N;;;;;
+1248F;CUNEIFORM SIGN DUG TIMES ASH AT LEFT;Lo;0;L;;;;;N;;;;;
+12490;CUNEIFORM SIGN DUG TIMES DIN;Lo;0;L;;;;;N;;;;;
+12491;CUNEIFORM SIGN DUG TIMES DUN;Lo;0;L;;;;;N;;;;;
+12492;CUNEIFORM SIGN DUG TIMES ERIN2;Lo;0;L;;;;;N;;;;;
+12493;CUNEIFORM SIGN DUG TIMES GA;Lo;0;L;;;;;N;;;;;
+12494;CUNEIFORM SIGN DUG TIMES GI;Lo;0;L;;;;;N;;;;;
+12495;CUNEIFORM SIGN DUG TIMES GIR2 GUNU;Lo;0;L;;;;;N;;;;;
+12496;CUNEIFORM SIGN DUG TIMES GISH;Lo;0;L;;;;;N;;;;;
+12497;CUNEIFORM SIGN DUG TIMES HA;Lo;0;L;;;;;N;;;;;
+12498;CUNEIFORM SIGN DUG TIMES HI;Lo;0;L;;;;;N;;;;;
+12499;CUNEIFORM SIGN DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+1249A;CUNEIFORM SIGN DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+1249B;CUNEIFORM SIGN DUG TIMES KUR;Lo;0;L;;;;;N;;;;;
+1249C;CUNEIFORM SIGN DUG TIMES KUSHU2;Lo;0;L;;;;;N;;;;;
+1249D;CUNEIFORM SIGN DUG TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;;
+1249E;CUNEIFORM SIGN DUG TIMES LAK-020;Lo;0;L;;;;;N;;;;;
+1249F;CUNEIFORM SIGN DUG TIMES LAM;Lo;0;L;;;;;N;;;;;
+124A0;CUNEIFORM SIGN DUG TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;;
+124A1;CUNEIFORM SIGN DUG TIMES LUH PLUS GISH;Lo;0;L;;;;;N;;;;;
+124A2;CUNEIFORM SIGN DUG TIMES MASH;Lo;0;L;;;;;N;;;;;
+124A3;CUNEIFORM SIGN DUG TIMES MES;Lo;0;L;;;;;N;;;;;
+124A4;CUNEIFORM SIGN DUG TIMES MI;Lo;0;L;;;;;N;;;;;
+124A5;CUNEIFORM SIGN DUG TIMES NI;Lo;0;L;;;;;N;;;;;
+124A6;CUNEIFORM SIGN DUG TIMES PI;Lo;0;L;;;;;N;;;;;
+124A7;CUNEIFORM SIGN DUG TIMES SHE;Lo;0;L;;;;;N;;;;;
+124A8;CUNEIFORM SIGN DUG TIMES SI GUNU;Lo;0;L;;;;;N;;;;;
+124A9;CUNEIFORM SIGN E2 TIMES KUR;Lo;0;L;;;;;N;;;;;
+124AA;CUNEIFORM SIGN E2 TIMES PAP;Lo;0;L;;;;;N;;;;;
+124AB;CUNEIFORM SIGN ERIN2 X;Lo;0;L;;;;;N;;;;;
+124AC;CUNEIFORM SIGN ESH2 CROSSING ESH2;Lo;0;L;;;;;N;;;;;
+124AD;CUNEIFORM SIGN EZEN SHESHIG TIMES ASH;Lo;0;L;;;;;N;;;;;
+124AE;CUNEIFORM SIGN EZEN SHESHIG TIMES HI;Lo;0;L;;;;;N;;;;;
+124AF;CUNEIFORM SIGN EZEN SHESHIG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+124B0;CUNEIFORM SIGN EZEN SHESHIG TIMES LA;Lo;0;L;;;;;N;;;;;
+124B1;CUNEIFORM SIGN EZEN SHESHIG TIMES LAL;Lo;0;L;;;;;N;;;;;
+124B2;CUNEIFORM SIGN EZEN SHESHIG TIMES ME;Lo;0;L;;;;;N;;;;;
+124B3;CUNEIFORM SIGN EZEN SHESHIG TIMES MES;Lo;0;L;;;;;N;;;;;
+124B4;CUNEIFORM SIGN EZEN SHESHIG TIMES SU;Lo;0;L;;;;;N;;;;;
+124B5;CUNEIFORM SIGN EZEN TIMES SU;Lo;0;L;;;;;N;;;;;
+124B6;CUNEIFORM SIGN GA2 TIMES BAHAR2;Lo;0;L;;;;;N;;;;;
+124B7;CUNEIFORM SIGN GA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;;
+124B8;CUNEIFORM SIGN GA2 TIMES DUG TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+124B9;CUNEIFORM SIGN GA2 TIMES DUG TIMES KASKAL;Lo;0;L;;;;;N;;;;;
+124BA;CUNEIFORM SIGN GA2 TIMES EREN;Lo;0;L;;;;;N;;;;;
+124BB;CUNEIFORM SIGN GA2 TIMES GA;Lo;0;L;;;;;N;;;;;
+124BC;CUNEIFORM SIGN GA2 TIMES GAR PLUS DI;Lo;0;L;;;;;N;;;;;
+124BD;CUNEIFORM SIGN GA2 TIMES GAR PLUS NE;Lo;0;L;;;;;N;;;;;
+124BE;CUNEIFORM SIGN GA2 TIMES HA PLUS A;Lo;0;L;;;;;N;;;;;
+124BF;CUNEIFORM SIGN GA2 TIMES KUSHU2 PLUS KASKAL;Lo;0;L;;;;;N;;;;;
+124C0;CUNEIFORM SIGN GA2 TIMES LAM;Lo;0;L;;;;;N;;;;;
+124C1;CUNEIFORM SIGN GA2 TIMES LAM TIMES KUR;Lo;0;L;;;;;N;;;;;
+124C2;CUNEIFORM SIGN GA2 TIMES LUH;Lo;0;L;;;;;N;;;;;
+124C3;CUNEIFORM SIGN GA2 TIMES MUSH;Lo;0;L;;;;;N;;;;;
+124C4;CUNEIFORM SIGN GA2 TIMES NE;Lo;0;L;;;;;N;;;;;
+124C5;CUNEIFORM SIGN GA2 TIMES NE PLUS E2;Lo;0;L;;;;;N;;;;;
+124C6;CUNEIFORM SIGN GA2 TIMES NE PLUS GI;Lo;0;L;;;;;N;;;;;
+124C7;CUNEIFORM SIGN GA2 TIMES SHIM;Lo;0;L;;;;;N;;;;;
+124C8;CUNEIFORM SIGN GA2 TIMES ZIZ2;Lo;0;L;;;;;N;;;;;
+124C9;CUNEIFORM SIGN GABA ROTATED NINETY DEGREES;Lo;0;L;;;;;N;;;;;
+124CA;CUNEIFORM SIGN GESHTIN TIMES U;Lo;0;L;;;;;N;;;;;
+124CB;CUNEIFORM SIGN GISH TIMES GISH CROSSING GISH;Lo;0;L;;;;;N;;;;;
+124CC;CUNEIFORM SIGN GU2 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+124CD;CUNEIFORM SIGN GUD PLUS GISH TIMES TAK4;Lo;0;L;;;;;N;;;;;
+124CE;CUNEIFORM SIGN HA TENU GUNU;Lo;0;L;;;;;N;;;;;
+124CF;CUNEIFORM SIGN HI TIMES ASH OVER HI TIMES ASH;Lo;0;L;;;;;N;;;;;
+124D0;CUNEIFORM SIGN KA TIMES BU;Lo;0;L;;;;;N;;;;;
+124D1;CUNEIFORM SIGN KA TIMES KA;Lo;0;L;;;;;N;;;;;
+124D2;CUNEIFORM SIGN KA TIMES U U U;Lo;0;L;;;;;N;;;;;
+124D3;CUNEIFORM SIGN KA TIMES UR;Lo;0;L;;;;;N;;;;;
+124D4;CUNEIFORM SIGN LAGAB TIMES ZU OVER ZU;Lo;0;L;;;;;N;;;;;
+124D5;CUNEIFORM SIGN LAK-003;Lo;0;L;;;;;N;;;;;
+124D6;CUNEIFORM SIGN LAK-021;Lo;0;L;;;;;N;;;;;
+124D7;CUNEIFORM SIGN LAK-025;Lo;0;L;;;;;N;;;;;
+124D8;CUNEIFORM SIGN LAK-030;Lo;0;L;;;;;N;;;;;
+124D9;CUNEIFORM SIGN LAK-050;Lo;0;L;;;;;N;;;;;
+124DA;CUNEIFORM SIGN LAK-051;Lo;0;L;;;;;N;;;;;
+124DB;CUNEIFORM SIGN LAK-062;Lo;0;L;;;;;N;;;;;
+124DC;CUNEIFORM SIGN LAK-079 OVER LAK-079 GUNU;Lo;0;L;;;;;N;;;;;
+124DD;CUNEIFORM SIGN LAK-080;Lo;0;L;;;;;N;;;;;
+124DE;CUNEIFORM SIGN LAK-081 OVER LAK-081;Lo;0;L;;;;;N;;;;;
+124DF;CUNEIFORM SIGN LAK-092;Lo;0;L;;;;;N;;;;;
+124E0;CUNEIFORM SIGN LAK-130;Lo;0;L;;;;;N;;;;;
+124E1;CUNEIFORM SIGN LAK-142;Lo;0;L;;;;;N;;;;;
+124E2;CUNEIFORM SIGN LAK-210;Lo;0;L;;;;;N;;;;;
+124E3;CUNEIFORM SIGN LAK-219;Lo;0;L;;;;;N;;;;;
+124E4;CUNEIFORM SIGN LAK-220;Lo;0;L;;;;;N;;;;;
+124E5;CUNEIFORM SIGN LAK-225;Lo;0;L;;;;;N;;;;;
+124E6;CUNEIFORM SIGN LAK-228;Lo;0;L;;;;;N;;;;;
+124E7;CUNEIFORM SIGN LAK-238;Lo;0;L;;;;;N;;;;;
+124E8;CUNEIFORM SIGN LAK-265;Lo;0;L;;;;;N;;;;;
+124E9;CUNEIFORM SIGN LAK-266;Lo;0;L;;;;;N;;;;;
+124EA;CUNEIFORM SIGN LAK-343;Lo;0;L;;;;;N;;;;;
+124EB;CUNEIFORM SIGN LAK-347;Lo;0;L;;;;;N;;;;;
+124EC;CUNEIFORM SIGN LAK-348;Lo;0;L;;;;;N;;;;;
+124ED;CUNEIFORM SIGN LAK-383;Lo;0;L;;;;;N;;;;;
+124EE;CUNEIFORM SIGN LAK-384;Lo;0;L;;;;;N;;;;;
+124EF;CUNEIFORM SIGN LAK-390;Lo;0;L;;;;;N;;;;;
+124F0;CUNEIFORM SIGN LAK-441;Lo;0;L;;;;;N;;;;;
+124F1;CUNEIFORM SIGN LAK-449;Lo;0;L;;;;;N;;;;;
+124F2;CUNEIFORM SIGN LAK-449 TIMES GU;Lo;0;L;;;;;N;;;;;
+124F3;CUNEIFORM SIGN LAK-449 TIMES IGI;Lo;0;L;;;;;N;;;;;
+124F4;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS LU3;Lo;0;L;;;;;N;;;;;
+124F5;CUNEIFORM SIGN LAK-449 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;;
+124F6;CUNEIFORM SIGN LAK-449 TIMES U2 PLUS BA;Lo;0;L;;;;;N;;;;;
+124F7;CUNEIFORM SIGN LAK-450;Lo;0;L;;;;;N;;;;;
+124F8;CUNEIFORM SIGN LAK-457;Lo;0;L;;;;;N;;;;;
+124F9;CUNEIFORM SIGN LAK-470;Lo;0;L;;;;;N;;;;;
+124FA;CUNEIFORM SIGN LAK-483;Lo;0;L;;;;;N;;;;;
+124FB;CUNEIFORM SIGN LAK-490;Lo;0;L;;;;;N;;;;;
+124FC;CUNEIFORM SIGN LAK-492;Lo;0;L;;;;;N;;;;;
+124FD;CUNEIFORM SIGN LAK-493;Lo;0;L;;;;;N;;;;;
+124FE;CUNEIFORM SIGN LAK-495;Lo;0;L;;;;;N;;;;;
+124FF;CUNEIFORM SIGN LAK-550;Lo;0;L;;;;;N;;;;;
+12500;CUNEIFORM SIGN LAK-608;Lo;0;L;;;;;N;;;;;
+12501;CUNEIFORM SIGN LAK-617;Lo;0;L;;;;;N;;;;;
+12502;CUNEIFORM SIGN LAK-617 TIMES ASH;Lo;0;L;;;;;N;;;;;
+12503;CUNEIFORM SIGN LAK-617 TIMES BAD;Lo;0;L;;;;;N;;;;;
+12504;CUNEIFORM SIGN LAK-617 TIMES DUN3 GUNU GUNU;Lo;0;L;;;;;N;;;;;
+12505;CUNEIFORM SIGN LAK-617 TIMES KU3;Lo;0;L;;;;;N;;;;;
+12506;CUNEIFORM SIGN LAK-617 TIMES LA;Lo;0;L;;;;;N;;;;;
+12507;CUNEIFORM SIGN LAK-617 TIMES TAR;Lo;0;L;;;;;N;;;;;
+12508;CUNEIFORM SIGN LAK-617 TIMES TE;Lo;0;L;;;;;N;;;;;
+12509;CUNEIFORM SIGN LAK-617 TIMES U2;Lo;0;L;;;;;N;;;;;
+1250A;CUNEIFORM SIGN LAK-617 TIMES UD;Lo;0;L;;;;;N;;;;;
+1250B;CUNEIFORM SIGN LAK-617 TIMES URUDA;Lo;0;L;;;;;N;;;;;
+1250C;CUNEIFORM SIGN LAK-636;Lo;0;L;;;;;N;;;;;
+1250D;CUNEIFORM SIGN LAK-648;Lo;0;L;;;;;N;;;;;
+1250E;CUNEIFORM SIGN LAK-648 TIMES DUB;Lo;0;L;;;;;N;;;;;
+1250F;CUNEIFORM SIGN LAK-648 TIMES GA;Lo;0;L;;;;;N;;;;;
+12510;CUNEIFORM SIGN LAK-648 TIMES IGI;Lo;0;L;;;;;N;;;;;
+12511;CUNEIFORM SIGN LAK-648 TIMES IGI GUNU;Lo;0;L;;;;;N;;;;;
+12512;CUNEIFORM SIGN LAK-648 TIMES NI;Lo;0;L;;;;;N;;;;;
+12513;CUNEIFORM SIGN LAK-648 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;;
+12514;CUNEIFORM SIGN LAK-648 TIMES SHESH PLUS KI;Lo;0;L;;;;;N;;;;;
+12515;CUNEIFORM SIGN LAK-648 TIMES UD;Lo;0;L;;;;;N;;;;;
+12516;CUNEIFORM SIGN LAK-648 TIMES URUDA;Lo;0;L;;;;;N;;;;;
+12517;CUNEIFORM SIGN LAK-724;Lo;0;L;;;;;N;;;;;
+12518;CUNEIFORM SIGN LAK-749;Lo;0;L;;;;;N;;;;;
+12519;CUNEIFORM SIGN LU2 GUNU TIMES ASH;Lo;0;L;;;;;N;;;;;
+1251A;CUNEIFORM SIGN LU2 TIMES DISH;Lo;0;L;;;;;N;;;;;
+1251B;CUNEIFORM SIGN LU2 TIMES HAL;Lo;0;L;;;;;N;;;;;
+1251C;CUNEIFORM SIGN LU2 TIMES PAP;Lo;0;L;;;;;N;;;;;
+1251D;CUNEIFORM SIGN LU2 TIMES PAP PLUS PAP PLUS LU3;Lo;0;L;;;;;N;;;;;
+1251E;CUNEIFORM SIGN LU2 TIMES TAK4;Lo;0;L;;;;;N;;;;;
+1251F;CUNEIFORM SIGN MI PLUS ZA7;Lo;0;L;;;;;N;;;;;
+12520;CUNEIFORM SIGN MUSH OVER MUSH TIMES GA;Lo;0;L;;;;;N;;;;;
+12521;CUNEIFORM SIGN MUSH OVER MUSH TIMES KAK;Lo;0;L;;;;;N;;;;;
+12522;CUNEIFORM SIGN NINDA2 TIMES DIM GUNU;Lo;0;L;;;;;N;;;;;
+12523;CUNEIFORM SIGN NINDA2 TIMES GISH;Lo;0;L;;;;;N;;;;;
+12524;CUNEIFORM SIGN NINDA2 TIMES GUL;Lo;0;L;;;;;N;;;;;
+12525;CUNEIFORM SIGN NINDA2 TIMES HI;Lo;0;L;;;;;N;;;;;
+12526;CUNEIFORM SIGN NINDA2 TIMES KESH2;Lo;0;L;;;;;N;;;;;
+12527;CUNEIFORM SIGN NINDA2 TIMES LAK-050;Lo;0;L;;;;;N;;;;;
+12528;CUNEIFORM SIGN NINDA2 TIMES MASH;Lo;0;L;;;;;N;;;;;
+12529;CUNEIFORM SIGN NINDA2 TIMES PAP PLUS PAP;Lo;0;L;;;;;N;;;;;
+1252A;CUNEIFORM SIGN NINDA2 TIMES U;Lo;0;L;;;;;N;;;;;
+1252B;CUNEIFORM SIGN NINDA2 TIMES U PLUS U;Lo;0;L;;;;;N;;;;;
+1252C;CUNEIFORM SIGN NINDA2 TIMES URUDA;Lo;0;L;;;;;N;;;;;
+1252D;CUNEIFORM SIGN SAG GUNU TIMES HA;Lo;0;L;;;;;N;;;;;
+1252E;CUNEIFORM SIGN SAG TIMES EN;Lo;0;L;;;;;N;;;;;
+1252F;CUNEIFORM SIGN SAG TIMES SHE AT LEFT;Lo;0;L;;;;;N;;;;;
+12530;CUNEIFORM SIGN SAG TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12531;CUNEIFORM SIGN SHA6 TENU;Lo;0;L;;;;;N;;;;;
+12532;CUNEIFORM SIGN SHE OVER SHE;Lo;0;L;;;;;N;;;;;
+12533;CUNEIFORM SIGN SHE PLUS HUB2;Lo;0;L;;;;;N;;;;;
+12534;CUNEIFORM SIGN SHE PLUS NAM2;Lo;0;L;;;;;N;;;;;
+12535;CUNEIFORM SIGN SHE PLUS SAR;Lo;0;L;;;;;N;;;;;
+12536;CUNEIFORM SIGN SHU2 PLUS DUG TIMES NI;Lo;0;L;;;;;N;;;;;
+12537;CUNEIFORM SIGN SHU2 PLUS E2 TIMES AN;Lo;0;L;;;;;N;;;;;
+12538;CUNEIFORM SIGN SI TIMES TAK4;Lo;0;L;;;;;N;;;;;
+12539;CUNEIFORM SIGN TAK4 PLUS SAG;Lo;0;L;;;;;N;;;;;
+1253A;CUNEIFORM SIGN TUM TIMES GAN2 TENU;Lo;0;L;;;;;N;;;;;
+1253B;CUNEIFORM SIGN TUM TIMES THREE DISH;Lo;0;L;;;;;N;;;;;
+1253C;CUNEIFORM SIGN UR2 INVERTED;Lo;0;L;;;;;N;;;;;
+1253D;CUNEIFORM SIGN UR2 TIMES UD;Lo;0;L;;;;;N;;;;;
+1253E;CUNEIFORM SIGN URU TIMES DARA3;Lo;0;L;;;;;N;;;;;
+1253F;CUNEIFORM SIGN URU TIMES LAK-668;Lo;0;L;;;;;N;;;;;
+12540;CUNEIFORM SIGN URU TIMES LU3;Lo;0;L;;;;;N;;;;;
+12541;CUNEIFORM SIGN ZA7;Lo;0;L;;;;;N;;;;;
+12542;CUNEIFORM SIGN ZU OVER ZU PLUS SAR;Lo;0;L;;;;;N;;;;;
+12543;CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU;Lo;0;L;;;;;N;;;;;
13000;EGYPTIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;;
13001;EGYPTIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;;
13002;EGYPTIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;;
@@ -21557,6 +22194,589 @@
1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;;
1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;;
1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;;
+14400;ANATOLIAN HIEROGLYPH A001;Lo;0;L;;;;;N;;;;;
+14401;ANATOLIAN HIEROGLYPH A002;Lo;0;L;;;;;N;;;;;
+14402;ANATOLIAN HIEROGLYPH A003;Lo;0;L;;;;;N;;;;;
+14403;ANATOLIAN HIEROGLYPH A004;Lo;0;L;;;;;N;;;;;
+14404;ANATOLIAN HIEROGLYPH A005;Lo;0;L;;;;;N;;;;;
+14405;ANATOLIAN HIEROGLYPH A006;Lo;0;L;;;;;N;;;;;
+14406;ANATOLIAN HIEROGLYPH A007;Lo;0;L;;;;;N;;;;;
+14407;ANATOLIAN HIEROGLYPH A008;Lo;0;L;;;;;N;;;;;
+14408;ANATOLIAN HIEROGLYPH A009;Lo;0;L;;;;;N;;;;;
+14409;ANATOLIAN HIEROGLYPH A010;Lo;0;L;;;;;N;;;;;
+1440A;ANATOLIAN HIEROGLYPH A010A;Lo;0;L;;;;;N;;;;;
+1440B;ANATOLIAN HIEROGLYPH A011;Lo;0;L;;;;;N;;;;;
+1440C;ANATOLIAN HIEROGLYPH A012;Lo;0;L;;;;;N;;;;;
+1440D;ANATOLIAN HIEROGLYPH A013;Lo;0;L;;;;;N;;;;;
+1440E;ANATOLIAN HIEROGLYPH A014;Lo;0;L;;;;;N;;;;;
+1440F;ANATOLIAN HIEROGLYPH A015;Lo;0;L;;;;;N;;;;;
+14410;ANATOLIAN HIEROGLYPH A016;Lo;0;L;;;;;N;;;;;
+14411;ANATOLIAN HIEROGLYPH A017;Lo;0;L;;;;;N;;;;;
+14412;ANATOLIAN HIEROGLYPH A018;Lo;0;L;;;;;N;;;;;
+14413;ANATOLIAN HIEROGLYPH A019;Lo;0;L;;;;;N;;;;;
+14414;ANATOLIAN HIEROGLYPH A020;Lo;0;L;;;;;N;;;;;
+14415;ANATOLIAN HIEROGLYPH A021;Lo;0;L;;;;;N;;;;;
+14416;ANATOLIAN HIEROGLYPH A022;Lo;0;L;;;;;N;;;;;
+14417;ANATOLIAN HIEROGLYPH A023;Lo;0;L;;;;;N;;;;;
+14418;ANATOLIAN HIEROGLYPH A024;Lo;0;L;;;;;N;;;;;
+14419;ANATOLIAN HIEROGLYPH A025;Lo;0;L;;;;;N;;;;;
+1441A;ANATOLIAN HIEROGLYPH A026;Lo;0;L;;;;;N;;;;;
+1441B;ANATOLIAN HIEROGLYPH A026A;Lo;0;L;;;;;N;;;;;
+1441C;ANATOLIAN HIEROGLYPH A027;Lo;0;L;;;;;N;;;;;
+1441D;ANATOLIAN HIEROGLYPH A028;Lo;0;L;;;;;N;;;;;
+1441E;ANATOLIAN HIEROGLYPH A029;Lo;0;L;;;;;N;;;;;
+1441F;ANATOLIAN HIEROGLYPH A030;Lo;0;L;;;;;N;;;;;
+14420;ANATOLIAN HIEROGLYPH A031;Lo;0;L;;;;;N;;;;;
+14421;ANATOLIAN HIEROGLYPH A032;Lo;0;L;;;;;N;;;;;
+14422;ANATOLIAN HIEROGLYPH A033;Lo;0;L;;;;;N;;;;;
+14423;ANATOLIAN HIEROGLYPH A034;Lo;0;L;;;;;N;;;;;
+14424;ANATOLIAN HIEROGLYPH A035;Lo;0;L;;;;;N;;;;;
+14425;ANATOLIAN HIEROGLYPH A036;Lo;0;L;;;;;N;;;;;
+14426;ANATOLIAN HIEROGLYPH A037;Lo;0;L;;;;;N;;;;;
+14427;ANATOLIAN HIEROGLYPH A038;Lo;0;L;;;;;N;;;;;
+14428;ANATOLIAN HIEROGLYPH A039;Lo;0;L;;;;;N;;;;;
+14429;ANATOLIAN HIEROGLYPH A039A;Lo;0;L;;;;;N;;;;;
+1442A;ANATOLIAN HIEROGLYPH A040;Lo;0;L;;;;;N;;;;;
+1442B;ANATOLIAN HIEROGLYPH A041;Lo;0;L;;;;;N;;;;;
+1442C;ANATOLIAN HIEROGLYPH A041A;Lo;0;L;;;;;N;;;;;
+1442D;ANATOLIAN HIEROGLYPH A042;Lo;0;L;;;;;N;;;;;
+1442E;ANATOLIAN HIEROGLYPH A043;Lo;0;L;;;;;N;;;;;
+1442F;ANATOLIAN HIEROGLYPH A044;Lo;0;L;;;;;N;;;;;
+14430;ANATOLIAN HIEROGLYPH A045;Lo;0;L;;;;;N;;;;;
+14431;ANATOLIAN HIEROGLYPH A045A;Lo;0;L;;;;;N;;;;;
+14432;ANATOLIAN HIEROGLYPH A046;Lo;0;L;;;;;N;;;;;
+14433;ANATOLIAN HIEROGLYPH A046A;Lo;0;L;;;;;N;;;;;
+14434;ANATOLIAN HIEROGLYPH A046B;Lo;0;L;;;;;N;;;;;
+14435;ANATOLIAN HIEROGLYPH A047;Lo;0;L;;;;;N;;;;;
+14436;ANATOLIAN HIEROGLYPH A048;Lo;0;L;;;;;N;;;;;
+14437;ANATOLIAN HIEROGLYPH A049;Lo;0;L;;;;;N;;;;;
+14438;ANATOLIAN HIEROGLYPH A050;Lo;0;L;;;;;N;;;;;
+14439;ANATOLIAN HIEROGLYPH A051;Lo;0;L;;;;;N;;;;;
+1443A;ANATOLIAN HIEROGLYPH A052;Lo;0;L;;;;;N;;;;;
+1443B;ANATOLIAN HIEROGLYPH A053;Lo;0;L;;;;;N;;;;;
+1443C;ANATOLIAN HIEROGLYPH A054;Lo;0;L;;;;;N;;;;;
+1443D;ANATOLIAN HIEROGLYPH A055;Lo;0;L;;;;;N;;;;;
+1443E;ANATOLIAN HIEROGLYPH A056;Lo;0;L;;;;;N;;;;;
+1443F;ANATOLIAN HIEROGLYPH A057;Lo;0;L;;;;;N;;;;;
+14440;ANATOLIAN HIEROGLYPH A058;Lo;0;L;;;;;N;;;;;
+14441;ANATOLIAN HIEROGLYPH A059;Lo;0;L;;;;;N;;;;;
+14442;ANATOLIAN HIEROGLYPH A060;Lo;0;L;;;;;N;;;;;
+14443;ANATOLIAN HIEROGLYPH A061;Lo;0;L;;;;;N;;;;;
+14444;ANATOLIAN HIEROGLYPH A062;Lo;0;L;;;;;N;;;;;
+14445;ANATOLIAN HIEROGLYPH A063;Lo;0;L;;;;;N;;;;;
+14446;ANATOLIAN HIEROGLYPH A064;Lo;0;L;;;;;N;;;;;
+14447;ANATOLIAN HIEROGLYPH A065;Lo;0;L;;;;;N;;;;;
+14448;ANATOLIAN HIEROGLYPH A066;Lo;0;L;;;;;N;;;;;
+14449;ANATOLIAN HIEROGLYPH A066A;Lo;0;L;;;;;N;;;;;
+1444A;ANATOLIAN HIEROGLYPH A066B;Lo;0;L;;;;;N;;;;;
+1444B;ANATOLIAN HIEROGLYPH A066C;Lo;0;L;;;;;N;;;;;
+1444C;ANATOLIAN HIEROGLYPH A067;Lo;0;L;;;;;N;;;;;
+1444D;ANATOLIAN HIEROGLYPH A068;Lo;0;L;;;;;N;;;;;
+1444E;ANATOLIAN HIEROGLYPH A069;Lo;0;L;;;;;N;;;;;
+1444F;ANATOLIAN HIEROGLYPH A070;Lo;0;L;;;;;N;;;;;
+14450;ANATOLIAN HIEROGLYPH A071;Lo;0;L;;;;;N;;;;;
+14451;ANATOLIAN HIEROGLYPH A072;Lo;0;L;;;;;N;;;;;
+14452;ANATOLIAN HIEROGLYPH A073;Lo;0;L;;;;;N;;;;;
+14453;ANATOLIAN HIEROGLYPH A074;Lo;0;L;;;;;N;;;;;
+14454;ANATOLIAN HIEROGLYPH A075;Lo;0;L;;;;;N;;;;;
+14455;ANATOLIAN HIEROGLYPH A076;Lo;0;L;;;;;N;;;;;
+14456;ANATOLIAN HIEROGLYPH A077;Lo;0;L;;;;;N;;;;;
+14457;ANATOLIAN HIEROGLYPH A078;Lo;0;L;;;;;N;;;;;
+14458;ANATOLIAN HIEROGLYPH A079;Lo;0;L;;;;;N;;;;;
+14459;ANATOLIAN HIEROGLYPH A080;Lo;0;L;;;;;N;;;;;
+1445A;ANATOLIAN HIEROGLYPH A081;Lo;0;L;;;;;N;;;;;
+1445B;ANATOLIAN HIEROGLYPH A082;Lo;0;L;;;;;N;;;;;
+1445C;ANATOLIAN HIEROGLYPH A083;Lo;0;L;;;;;N;;;;;
+1445D;ANATOLIAN HIEROGLYPH A084;Lo;0;L;;;;;N;;;;;
+1445E;ANATOLIAN HIEROGLYPH A085;Lo;0;L;;;;;N;;;;;
+1445F;ANATOLIAN HIEROGLYPH A086;Lo;0;L;;;;;N;;;;;
+14460;ANATOLIAN HIEROGLYPH A087;Lo;0;L;;;;;N;;;;;
+14461;ANATOLIAN HIEROGLYPH A088;Lo;0;L;;;;;N;;;;;
+14462;ANATOLIAN HIEROGLYPH A089;Lo;0;L;;;;;N;;;;;
+14463;ANATOLIAN HIEROGLYPH A090;Lo;0;L;;;;;N;;;;;
+14464;ANATOLIAN HIEROGLYPH A091;Lo;0;L;;;;;N;;;;;
+14465;ANATOLIAN HIEROGLYPH A092;Lo;0;L;;;;;N;;;;;
+14466;ANATOLIAN HIEROGLYPH A093;Lo;0;L;;;;;N;;;;;
+14467;ANATOLIAN HIEROGLYPH A094;Lo;0;L;;;;;N;;;;;
+14468;ANATOLIAN HIEROGLYPH A095;Lo;0;L;;;;;N;;;;;
+14469;ANATOLIAN HIEROGLYPH A096;Lo;0;L;;;;;N;;;;;
+1446A;ANATOLIAN HIEROGLYPH A097;Lo;0;L;;;;;N;;;;;
+1446B;ANATOLIAN HIEROGLYPH A097A;Lo;0;L;;;;;N;;;;;
+1446C;ANATOLIAN HIEROGLYPH A098;Lo;0;L;;;;;N;;;;;
+1446D;ANATOLIAN HIEROGLYPH A098A;Lo;0;L;;;;;N;;;;;
+1446E;ANATOLIAN HIEROGLYPH A099;Lo;0;L;;;;;N;;;;;
+1446F;ANATOLIAN HIEROGLYPH A100;Lo;0;L;;;;;N;;;;;
+14470;ANATOLIAN HIEROGLYPH A100A;Lo;0;L;;;;;N;;;;;
+14471;ANATOLIAN HIEROGLYPH A101;Lo;0;L;;;;;N;;;;;
+14472;ANATOLIAN HIEROGLYPH A101A;Lo;0;L;;;;;N;;;;;
+14473;ANATOLIAN HIEROGLYPH A102;Lo;0;L;;;;;N;;;;;
+14474;ANATOLIAN HIEROGLYPH A102A;Lo;0;L;;;;;N;;;;;
+14475;ANATOLIAN HIEROGLYPH A103;Lo;0;L;;;;;N;;;;;
+14476;ANATOLIAN HIEROGLYPH A104;Lo;0;L;;;;;N;;;;;
+14477;ANATOLIAN HIEROGLYPH A104A;Lo;0;L;;;;;N;;;;;
+14478;ANATOLIAN HIEROGLYPH A104B;Lo;0;L;;;;;N;;;;;
+14479;ANATOLIAN HIEROGLYPH A104C;Lo;0;L;;;;;N;;;;;
+1447A;ANATOLIAN HIEROGLYPH A105;Lo;0;L;;;;;N;;;;;
+1447B;ANATOLIAN HIEROGLYPH A105A;Lo;0;L;;;;;N;;;;;
+1447C;ANATOLIAN HIEROGLYPH A105B;Lo;0;L;;;;;N;;;;;
+1447D;ANATOLIAN HIEROGLYPH A106;Lo;0;L;;;;;N;;;;;
+1447E;ANATOLIAN HIEROGLYPH A107;Lo;0;L;;;;;N;;;;;
+1447F;ANATOLIAN HIEROGLYPH A107A;Lo;0;L;;;;;N;;;;;
+14480;ANATOLIAN HIEROGLYPH A107B;Lo;0;L;;;;;N;;;;;
+14481;ANATOLIAN HIEROGLYPH A107C;Lo;0;L;;;;;N;;;;;
+14482;ANATOLIAN HIEROGLYPH A108;Lo;0;L;;;;;N;;;;;
+14483;ANATOLIAN HIEROGLYPH A109;Lo;0;L;;;;;N;;;;;
+14484;ANATOLIAN HIEROGLYPH A110;Lo;0;L;;;;;N;;;;;
+14485;ANATOLIAN HIEROGLYPH A110A;Lo;0;L;;;;;N;;;;;
+14486;ANATOLIAN HIEROGLYPH A110B;Lo;0;L;;;;;N;;;;;
+14487;ANATOLIAN HIEROGLYPH A111;Lo;0;L;;;;;N;;;;;
+14488;ANATOLIAN HIEROGLYPH A112;Lo;0;L;;;;;N;;;;;
+14489;ANATOLIAN HIEROGLYPH A113;Lo;0;L;;;;;N;;;;;
+1448A;ANATOLIAN HIEROGLYPH A114;Lo;0;L;;;;;N;;;;;
+1448B;ANATOLIAN HIEROGLYPH A115;Lo;0;L;;;;;N;;;;;
+1448C;ANATOLIAN HIEROGLYPH A115A;Lo;0;L;;;;;N;;;;;
+1448D;ANATOLIAN HIEROGLYPH A116;Lo;0;L;;;;;N;;;;;
+1448E;ANATOLIAN HIEROGLYPH A117;Lo;0;L;;;;;N;;;;;
+1448F;ANATOLIAN HIEROGLYPH A118;Lo;0;L;;;;;N;;;;;
+14490;ANATOLIAN HIEROGLYPH A119;Lo;0;L;;;;;N;;;;;
+14491;ANATOLIAN HIEROGLYPH A120;Lo;0;L;;;;;N;;;;;
+14492;ANATOLIAN HIEROGLYPH A121;Lo;0;L;;;;;N;;;;;
+14493;ANATOLIAN HIEROGLYPH A122;Lo;0;L;;;;;N;;;;;
+14494;ANATOLIAN HIEROGLYPH A123;Lo;0;L;;;;;N;;;;;
+14495;ANATOLIAN HIEROGLYPH A124;Lo;0;L;;;;;N;;;;;
+14496;ANATOLIAN HIEROGLYPH A125;Lo;0;L;;;;;N;;;;;
+14497;ANATOLIAN HIEROGLYPH A125A;Lo;0;L;;;;;N;;;;;
+14498;ANATOLIAN HIEROGLYPH A126;Lo;0;L;;;;;N;;;;;
+14499;ANATOLIAN HIEROGLYPH A127;Lo;0;L;;;;;N;;;;;
+1449A;ANATOLIAN HIEROGLYPH A128;Lo;0;L;;;;;N;;;;;
+1449B;ANATOLIAN HIEROGLYPH A129;Lo;0;L;;;;;N;;;;;
+1449C;ANATOLIAN HIEROGLYPH A130;Lo;0;L;;;;;N;;;;;
+1449D;ANATOLIAN HIEROGLYPH A131;Lo;0;L;;;;;N;;;;;
+1449E;ANATOLIAN HIEROGLYPH A132;Lo;0;L;;;;;N;;;;;
+1449F;ANATOLIAN HIEROGLYPH A133;Lo;0;L;;;;;N;;;;;
+144A0;ANATOLIAN HIEROGLYPH A134;Lo;0;L;;;;;N;;;;;
+144A1;ANATOLIAN HIEROGLYPH A135;Lo;0;L;;;;;N;;;;;
+144A2;ANATOLIAN HIEROGLYPH A135A;Lo;0;L;;;;;N;;;;;
+144A3;ANATOLIAN HIEROGLYPH A136;Lo;0;L;;;;;N;;;;;
+144A4;ANATOLIAN HIEROGLYPH A137;Lo;0;L;;;;;N;;;;;
+144A5;ANATOLIAN HIEROGLYPH A138;Lo;0;L;;;;;N;;;;;
+144A6;ANATOLIAN HIEROGLYPH A139;Lo;0;L;;;;;N;;;;;
+144A7;ANATOLIAN HIEROGLYPH A140;Lo;0;L;;;;;N;;;;;
+144A8;ANATOLIAN HIEROGLYPH A141;Lo;0;L;;;;;N;;;;;
+144A9;ANATOLIAN HIEROGLYPH A142;Lo;0;L;;;;;N;;;;;
+144AA;ANATOLIAN HIEROGLYPH A143;Lo;0;L;;;;;N;;;;;
+144AB;ANATOLIAN HIEROGLYPH A144;Lo;0;L;;;;;N;;;;;
+144AC;ANATOLIAN HIEROGLYPH A145;Lo;0;L;;;;;N;;;;;
+144AD;ANATOLIAN HIEROGLYPH A146;Lo;0;L;;;;;N;;;;;
+144AE;ANATOLIAN HIEROGLYPH A147;Lo;0;L;;;;;N;;;;;
+144AF;ANATOLIAN HIEROGLYPH A148;Lo;0;L;;;;;N;;;;;
+144B0;ANATOLIAN HIEROGLYPH A149;Lo;0;L;;;;;N;;;;;
+144B1;ANATOLIAN HIEROGLYPH A150;Lo;0;L;;;;;N;;;;;
+144B2;ANATOLIAN HIEROGLYPH A151;Lo;0;L;;;;;N;;;;;
+144B3;ANATOLIAN HIEROGLYPH A152;Lo;0;L;;;;;N;;;;;
+144B4;ANATOLIAN HIEROGLYPH A153;Lo;0;L;;;;;N;;;;;
+144B5;ANATOLIAN HIEROGLYPH A154;Lo;0;L;;;;;N;;;;;
+144B6;ANATOLIAN HIEROGLYPH A155;Lo;0;L;;;;;N;;;;;
+144B7;ANATOLIAN HIEROGLYPH A156;Lo;0;L;;;;;N;;;;;
+144B8;ANATOLIAN HIEROGLYPH A157;Lo;0;L;;;;;N;;;;;
+144B9;ANATOLIAN HIEROGLYPH A158;Lo;0;L;;;;;N;;;;;
+144BA;ANATOLIAN HIEROGLYPH A159;Lo;0;L;;;;;N;;;;;
+144BB;ANATOLIAN HIEROGLYPH A160;Lo;0;L;;;;;N;;;;;
+144BC;ANATOLIAN HIEROGLYPH A161;Lo;0;L;;;;;N;;;;;
+144BD;ANATOLIAN HIEROGLYPH A162;Lo;0;L;;;;;N;;;;;
+144BE;ANATOLIAN HIEROGLYPH A163;Lo;0;L;;;;;N;;;;;
+144BF;ANATOLIAN HIEROGLYPH A164;Lo;0;L;;;;;N;;;;;
+144C0;ANATOLIAN HIEROGLYPH A165;Lo;0;L;;;;;N;;;;;
+144C1;ANATOLIAN HIEROGLYPH A166;Lo;0;L;;;;;N;;;;;
+144C2;ANATOLIAN HIEROGLYPH A167;Lo;0;L;;;;;N;;;;;
+144C3;ANATOLIAN HIEROGLYPH A168;Lo;0;L;;;;;N;;;;;
+144C4;ANATOLIAN HIEROGLYPH A169;Lo;0;L;;;;;N;;;;;
+144C5;ANATOLIAN HIEROGLYPH A170;Lo;0;L;;;;;N;;;;;
+144C6;ANATOLIAN HIEROGLYPH A171;Lo;0;L;;;;;N;;;;;
+144C7;ANATOLIAN HIEROGLYPH A172;Lo;0;L;;;;;N;;;;;
+144C8;ANATOLIAN HIEROGLYPH A173;Lo;0;L;;;;;N;;;;;
+144C9;ANATOLIAN HIEROGLYPH A174;Lo;0;L;;;;;N;;;;;
+144CA;ANATOLIAN HIEROGLYPH A175;Lo;0;L;;;;;N;;;;;
+144CB;ANATOLIAN HIEROGLYPH A176;Lo;0;L;;;;;N;;;;;
+144CC;ANATOLIAN HIEROGLYPH A177;Lo;0;L;;;;;N;;;;;
+144CD;ANATOLIAN HIEROGLYPH A178;Lo;0;L;;;;;N;;;;;
+144CE;ANATOLIAN HIEROGLYPH A179;Lo;0;L;;;;;N;;;;;
+144CF;ANATOLIAN HIEROGLYPH A180;Lo;0;L;;;;;N;;;;;
+144D0;ANATOLIAN HIEROGLYPH A181;Lo;0;L;;;;;N;;;;;
+144D1;ANATOLIAN HIEROGLYPH A182;Lo;0;L;;;;;N;;;;;
+144D2;ANATOLIAN HIEROGLYPH A183;Lo;0;L;;;;;N;;;;;
+144D3;ANATOLIAN HIEROGLYPH A184;Lo;0;L;;;;;N;;;;;
+144D4;ANATOLIAN HIEROGLYPH A185;Lo;0;L;;;;;N;;;;;
+144D5;ANATOLIAN HIEROGLYPH A186;Lo;0;L;;;;;N;;;;;
+144D6;ANATOLIAN HIEROGLYPH A187;Lo;0;L;;;;;N;;;;;
+144D7;ANATOLIAN HIEROGLYPH A188;Lo;0;L;;;;;N;;;;;
+144D8;ANATOLIAN HIEROGLYPH A189;Lo;0;L;;;;;N;;;;;
+144D9;ANATOLIAN HIEROGLYPH A190;Lo;0;L;;;;;N;;;;;
+144DA;ANATOLIAN HIEROGLYPH A191;Lo;0;L;;;;;N;;;;;
+144DB;ANATOLIAN HIEROGLYPH A192;Lo;0;L;;;;;N;;;;;
+144DC;ANATOLIAN HIEROGLYPH A193;Lo;0;L;;;;;N;;;;;
+144DD;ANATOLIAN HIEROGLYPH A194;Lo;0;L;;;;;N;;;;;
+144DE;ANATOLIAN HIEROGLYPH A195;Lo;0;L;;;;;N;;;;;
+144DF;ANATOLIAN HIEROGLYPH A196;Lo;0;L;;;;;N;;;;;
+144E0;ANATOLIAN HIEROGLYPH A197;Lo;0;L;;;;;N;;;;;
+144E1;ANATOLIAN HIEROGLYPH A198;Lo;0;L;;;;;N;;;;;
+144E2;ANATOLIAN HIEROGLYPH A199;Lo;0;L;;;;;N;;;;;
+144E3;ANATOLIAN HIEROGLYPH A200;Lo;0;L;;;;;N;;;;;
+144E4;ANATOLIAN HIEROGLYPH A201;Lo;0;L;;;;;N;;;;;
+144E5;ANATOLIAN HIEROGLYPH A202;Lo;0;L;;;;;N;;;;;
+144E6;ANATOLIAN HIEROGLYPH A202A;Lo;0;L;;;;;N;;;;;
+144E7;ANATOLIAN HIEROGLYPH A202B;Lo;0;L;;;;;N;;;;;
+144E8;ANATOLIAN HIEROGLYPH A203;Lo;0;L;;;;;N;;;;;
+144E9;ANATOLIAN HIEROGLYPH A204;Lo;0;L;;;;;N;;;;;
+144EA;ANATOLIAN HIEROGLYPH A205;Lo;0;L;;;;;N;;;;;
+144EB;ANATOLIAN HIEROGLYPH A206;Lo;0;L;;;;;N;;;;;
+144EC;ANATOLIAN HIEROGLYPH A207;Lo;0;L;;;;;N;;;;;
+144ED;ANATOLIAN HIEROGLYPH A207A;Lo;0;L;;;;;N;;;;;
+144EE;ANATOLIAN HIEROGLYPH A208;Lo;0;L;;;;;N;;;;;
+144EF;ANATOLIAN HIEROGLYPH A209;Lo;0;L;;;;;N;;;;;
+144F0;ANATOLIAN HIEROGLYPH A209A;Lo;0;L;;;;;N;;;;;
+144F1;ANATOLIAN HIEROGLYPH A210;Lo;0;L;;;;;N;;;;;
+144F2;ANATOLIAN HIEROGLYPH A211;Lo;0;L;;;;;N;;;;;
+144F3;ANATOLIAN HIEROGLYPH A212;Lo;0;L;;;;;N;;;;;
+144F4;ANATOLIAN HIEROGLYPH A213;Lo;0;L;;;;;N;;;;;
+144F5;ANATOLIAN HIEROGLYPH A214;Lo;0;L;;;;;N;;;;;
+144F6;ANATOLIAN HIEROGLYPH A215;Lo;0;L;;;;;N;;;;;
+144F7;ANATOLIAN HIEROGLYPH A215A;Lo;0;L;;;;;N;;;;;
+144F8;ANATOLIAN HIEROGLYPH A216;Lo;0;L;;;;;N;;;;;
+144F9;ANATOLIAN HIEROGLYPH A216A;Lo;0;L;;;;;N;;;;;
+144FA;ANATOLIAN HIEROGLYPH A217;Lo;0;L;;;;;N;;;;;
+144FB;ANATOLIAN HIEROGLYPH A218;Lo;0;L;;;;;N;;;;;
+144FC;ANATOLIAN HIEROGLYPH A219;Lo;0;L;;;;;N;;;;;
+144FD;ANATOLIAN HIEROGLYPH A220;Lo;0;L;;;;;N;;;;;
+144FE;ANATOLIAN HIEROGLYPH A221;Lo;0;L;;;;;N;;;;;
+144FF;ANATOLIAN HIEROGLYPH A222;Lo;0;L;;;;;N;;;;;
+14500;ANATOLIAN HIEROGLYPH A223;Lo;0;L;;;;;N;;;;;
+14501;ANATOLIAN HIEROGLYPH A224;Lo;0;L;;;;;N;;;;;
+14502;ANATOLIAN HIEROGLYPH A225;Lo;0;L;;;;;N;;;;;
+14503;ANATOLIAN HIEROGLYPH A226;Lo;0;L;;;;;N;;;;;
+14504;ANATOLIAN HIEROGLYPH A227;Lo;0;L;;;;;N;;;;;
+14505;ANATOLIAN HIEROGLYPH A227A;Lo;0;L;;;;;N;;;;;
+14506;ANATOLIAN HIEROGLYPH A228;Lo;0;L;;;;;N;;;;;
+14507;ANATOLIAN HIEROGLYPH A229;Lo;0;L;;;;;N;;;;;
+14508;ANATOLIAN HIEROGLYPH A230;Lo;0;L;;;;;N;;;;;
+14509;ANATOLIAN HIEROGLYPH A231;Lo;0;L;;;;;N;;;;;
+1450A;ANATOLIAN HIEROGLYPH A232;Lo;0;L;;;;;N;;;;;
+1450B;ANATOLIAN HIEROGLYPH A233;Lo;0;L;;;;;N;;;;;
+1450C;ANATOLIAN HIEROGLYPH A234;Lo;0;L;;;;;N;;;;;
+1450D;ANATOLIAN HIEROGLYPH A235;Lo;0;L;;;;;N;;;;;
+1450E;ANATOLIAN HIEROGLYPH A236;Lo;0;L;;;;;N;;;;;
+1450F;ANATOLIAN HIEROGLYPH A237;Lo;0;L;;;;;N;;;;;
+14510;ANATOLIAN HIEROGLYPH A238;Lo;0;L;;;;;N;;;;;
+14511;ANATOLIAN HIEROGLYPH A239;Lo;0;L;;;;;N;;;;;
+14512;ANATOLIAN HIEROGLYPH A240;Lo;0;L;;;;;N;;;;;
+14513;ANATOLIAN HIEROGLYPH A241;Lo;0;L;;;;;N;;;;;
+14514;ANATOLIAN HIEROGLYPH A242;Lo;0;L;;;;;N;;;;;
+14515;ANATOLIAN HIEROGLYPH A243;Lo;0;L;;;;;N;;;;;
+14516;ANATOLIAN HIEROGLYPH A244;Lo;0;L;;;;;N;;;;;
+14517;ANATOLIAN HIEROGLYPH A245;Lo;0;L;;;;;N;;;;;
+14518;ANATOLIAN HIEROGLYPH A246;Lo;0;L;;;;;N;;;;;
+14519;ANATOLIAN HIEROGLYPH A247;Lo;0;L;;;;;N;;;;;
+1451A;ANATOLIAN HIEROGLYPH A248;Lo;0;L;;;;;N;;;;;
+1451B;ANATOLIAN HIEROGLYPH A249;Lo;0;L;;;;;N;;;;;
+1451C;ANATOLIAN HIEROGLYPH A250;Lo;0;L;;;;;N;;;;;
+1451D;ANATOLIAN HIEROGLYPH A251;Lo;0;L;;;;;N;;;;;
+1451E;ANATOLIAN HIEROGLYPH A252;Lo;0;L;;;;;N;;;;;
+1451F;ANATOLIAN HIEROGLYPH A253;Lo;0;L;;;;;N;;;;;
+14520;ANATOLIAN HIEROGLYPH A254;Lo;0;L;;;;;N;;;;;
+14521;ANATOLIAN HIEROGLYPH A255;Lo;0;L;;;;;N;;;;;
+14522;ANATOLIAN HIEROGLYPH A256;Lo;0;L;;;;;N;;;;;
+14523;ANATOLIAN HIEROGLYPH A257;Lo;0;L;;;;;N;;;;;
+14524;ANATOLIAN HIEROGLYPH A258;Lo;0;L;;;;;N;;;;;
+14525;ANATOLIAN HIEROGLYPH A259;Lo;0;L;;;;;N;;;;;
+14526;ANATOLIAN HIEROGLYPH A260;Lo;0;L;;;;;N;;;;;
+14527;ANATOLIAN HIEROGLYPH A261;Lo;0;L;;;;;N;;;;;
+14528;ANATOLIAN HIEROGLYPH A262;Lo;0;L;;;;;N;;;;;
+14529;ANATOLIAN HIEROGLYPH A263;Lo;0;L;;;;;N;;;;;
+1452A;ANATOLIAN HIEROGLYPH A264;Lo;0;L;;;;;N;;;;;
+1452B;ANATOLIAN HIEROGLYPH A265;Lo;0;L;;;;;N;;;;;
+1452C;ANATOLIAN HIEROGLYPH A266;Lo;0;L;;;;;N;;;;;
+1452D;ANATOLIAN HIEROGLYPH A267;Lo;0;L;;;;;N;;;;;
+1452E;ANATOLIAN HIEROGLYPH A267A;Lo;0;L;;;;;N;;;;;
+1452F;ANATOLIAN HIEROGLYPH A268;Lo;0;L;;;;;N;;;;;
+14530;ANATOLIAN HIEROGLYPH A269;Lo;0;L;;;;;N;;;;;
+14531;ANATOLIAN HIEROGLYPH A270;Lo;0;L;;;;;N;;;;;
+14532;ANATOLIAN HIEROGLYPH A271;Lo;0;L;;;;;N;;;;;
+14533;ANATOLIAN HIEROGLYPH A272;Lo;0;L;;;;;N;;;;;
+14534;ANATOLIAN HIEROGLYPH A273;Lo;0;L;;;;;N;;;;;
+14535;ANATOLIAN HIEROGLYPH A274;Lo;0;L;;;;;N;;;;;
+14536;ANATOLIAN HIEROGLYPH A275;Lo;0;L;;;;;N;;;;;
+14537;ANATOLIAN HIEROGLYPH A276;Lo;0;L;;;;;N;;;;;
+14538;ANATOLIAN HIEROGLYPH A277;Lo;0;L;;;;;N;;;;;
+14539;ANATOLIAN HIEROGLYPH A278;Lo;0;L;;;;;N;;;;;
+1453A;ANATOLIAN HIEROGLYPH A279;Lo;0;L;;;;;N;;;;;
+1453B;ANATOLIAN HIEROGLYPH A280;Lo;0;L;;;;;N;;;;;
+1453C;ANATOLIAN HIEROGLYPH A281;Lo;0;L;;;;;N;;;;;
+1453D;ANATOLIAN HIEROGLYPH A282;Lo;0;L;;;;;N;;;;;
+1453E;ANATOLIAN HIEROGLYPH A283;Lo;0;L;;;;;N;;;;;
+1453F;ANATOLIAN HIEROGLYPH A284;Lo;0;L;;;;;N;;;;;
+14540;ANATOLIAN HIEROGLYPH A285;Lo;0;L;;;;;N;;;;;
+14541;ANATOLIAN HIEROGLYPH A286;Lo;0;L;;;;;N;;;;;
+14542;ANATOLIAN HIEROGLYPH A287;Lo;0;L;;;;;N;;;;;
+14543;ANATOLIAN HIEROGLYPH A288;Lo;0;L;;;;;N;;;;;
+14544;ANATOLIAN HIEROGLYPH A289;Lo;0;L;;;;;N;;;;;
+14545;ANATOLIAN HIEROGLYPH A289A;Lo;0;L;;;;;N;;;;;
+14546;ANATOLIAN HIEROGLYPH A290;Lo;0;L;;;;;N;;;;;
+14547;ANATOLIAN HIEROGLYPH A291;Lo;0;L;;;;;N;;;;;
+14548;ANATOLIAN HIEROGLYPH A292;Lo;0;L;;;;;N;;;;;
+14549;ANATOLIAN HIEROGLYPH A293;Lo;0;L;;;;;N;;;;;
+1454A;ANATOLIAN HIEROGLYPH A294;Lo;0;L;;;;;N;;;;;
+1454B;ANATOLIAN HIEROGLYPH A294A;Lo;0;L;;;;;N;;;;;
+1454C;ANATOLIAN HIEROGLYPH A295;Lo;0;L;;;;;N;;;;;
+1454D;ANATOLIAN HIEROGLYPH A296;Lo;0;L;;;;;N;;;;;
+1454E;ANATOLIAN HIEROGLYPH A297;Lo;0;L;;;;;N;;;;;
+1454F;ANATOLIAN HIEROGLYPH A298;Lo;0;L;;;;;N;;;;;
+14550;ANATOLIAN HIEROGLYPH A299;Lo;0;L;;;;;N;;;;;
+14551;ANATOLIAN HIEROGLYPH A299A;Lo;0;L;;;;;N;;;;;
+14552;ANATOLIAN HIEROGLYPH A300;Lo;0;L;;;;;N;;;;;
+14553;ANATOLIAN HIEROGLYPH A301;Lo;0;L;;;;;N;;;;;
+14554;ANATOLIAN HIEROGLYPH A302;Lo;0;L;;;;;N;;;;;
+14555;ANATOLIAN HIEROGLYPH A303;Lo;0;L;;;;;N;;;;;
+14556;ANATOLIAN HIEROGLYPH A304;Lo;0;L;;;;;N;;;;;
+14557;ANATOLIAN HIEROGLYPH A305;Lo;0;L;;;;;N;;;;;
+14558;ANATOLIAN HIEROGLYPH A306;Lo;0;L;;;;;N;;;;;
+14559;ANATOLIAN HIEROGLYPH A307;Lo;0;L;;;;;N;;;;;
+1455A;ANATOLIAN HIEROGLYPH A308;Lo;0;L;;;;;N;;;;;
+1455B;ANATOLIAN HIEROGLYPH A309;Lo;0;L;;;;;N;;;;;
+1455C;ANATOLIAN HIEROGLYPH A309A;Lo;0;L;;;;;N;;;;;
+1455D;ANATOLIAN HIEROGLYPH A310;Lo;0;L;;;;;N;;;;;
+1455E;ANATOLIAN HIEROGLYPH A311;Lo;0;L;;;;;N;;;;;
+1455F;ANATOLIAN HIEROGLYPH A312;Lo;0;L;;;;;N;;;;;
+14560;ANATOLIAN HIEROGLYPH A313;Lo;0;L;;;;;N;;;;;
+14561;ANATOLIAN HIEROGLYPH A314;Lo;0;L;;;;;N;;;;;
+14562;ANATOLIAN HIEROGLYPH A315;Lo;0;L;;;;;N;;;;;
+14563;ANATOLIAN HIEROGLYPH A316;Lo;0;L;;;;;N;;;;;
+14564;ANATOLIAN HIEROGLYPH A317;Lo;0;L;;;;;N;;;;;
+14565;ANATOLIAN HIEROGLYPH A318;Lo;0;L;;;;;N;;;;;
+14566;ANATOLIAN HIEROGLYPH A319;Lo;0;L;;;;;N;;;;;
+14567;ANATOLIAN HIEROGLYPH A320;Lo;0;L;;;;;N;;;;;
+14568;ANATOLIAN HIEROGLYPH A321;Lo;0;L;;;;;N;;;;;
+14569;ANATOLIAN HIEROGLYPH A322;Lo;0;L;;;;;N;;;;;
+1456A;ANATOLIAN HIEROGLYPH A323;Lo;0;L;;;;;N;;;;;
+1456B;ANATOLIAN HIEROGLYPH A324;Lo;0;L;;;;;N;;;;;
+1456C;ANATOLIAN HIEROGLYPH A325;Lo;0;L;;;;;N;;;;;
+1456D;ANATOLIAN HIEROGLYPH A326;Lo;0;L;;;;;N;;;;;
+1456E;ANATOLIAN HIEROGLYPH A327;Lo;0;L;;;;;N;;;;;
+1456F;ANATOLIAN HIEROGLYPH A328;Lo;0;L;;;;;N;;;;;
+14570;ANATOLIAN HIEROGLYPH A329;Lo;0;L;;;;;N;;;;;
+14571;ANATOLIAN HIEROGLYPH A329A;Lo;0;L;;;;;N;;;;;
+14572;ANATOLIAN HIEROGLYPH A330;Lo;0;L;;;;;N;;;;;
+14573;ANATOLIAN HIEROGLYPH A331;Lo;0;L;;;;;N;;;;;
+14574;ANATOLIAN HIEROGLYPH A332A;Lo;0;L;;;;;N;;;;;
+14575;ANATOLIAN HIEROGLYPH A332B;Lo;0;L;;;;;N;;;;;
+14576;ANATOLIAN HIEROGLYPH A332C;Lo;0;L;;;;;N;;;;;
+14577;ANATOLIAN HIEROGLYPH A333;Lo;0;L;;;;;N;;;;;
+14578;ANATOLIAN HIEROGLYPH A334;Lo;0;L;;;;;N;;;;;
+14579;ANATOLIAN HIEROGLYPH A335;Lo;0;L;;;;;N;;;;;
+1457A;ANATOLIAN HIEROGLYPH A336;Lo;0;L;;;;;N;;;;;
+1457B;ANATOLIAN HIEROGLYPH A336A;Lo;0;L;;;;;N;;;;;
+1457C;ANATOLIAN HIEROGLYPH A336B;Lo;0;L;;;;;N;;;;;
+1457D;ANATOLIAN HIEROGLYPH A336C;Lo;0;L;;;;;N;;;;;
+1457E;ANATOLIAN HIEROGLYPH A337;Lo;0;L;;;;;N;;;;;
+1457F;ANATOLIAN HIEROGLYPH A338;Lo;0;L;;;;;N;;;;;
+14580;ANATOLIAN HIEROGLYPH A339;Lo;0;L;;;;;N;;;;;
+14581;ANATOLIAN HIEROGLYPH A340;Lo;0;L;;;;;N;;;;;
+14582;ANATOLIAN HIEROGLYPH A341;Lo;0;L;;;;;N;;;;;
+14583;ANATOLIAN HIEROGLYPH A342;Lo;0;L;;;;;N;;;;;
+14584;ANATOLIAN HIEROGLYPH A343;Lo;0;L;;;;;N;;;;;
+14585;ANATOLIAN HIEROGLYPH A344;Lo;0;L;;;;;N;;;;;
+14586;ANATOLIAN HIEROGLYPH A345;Lo;0;L;;;;;N;;;;;
+14587;ANATOLIAN HIEROGLYPH A346;Lo;0;L;;;;;N;;;;;
+14588;ANATOLIAN HIEROGLYPH A347;Lo;0;L;;;;;N;;;;;
+14589;ANATOLIAN HIEROGLYPH A348;Lo;0;L;;;;;N;;;;;
+1458A;ANATOLIAN HIEROGLYPH A349;Lo;0;L;;;;;N;;;;;
+1458B;ANATOLIAN HIEROGLYPH A350;Lo;0;L;;;;;N;;;;;
+1458C;ANATOLIAN HIEROGLYPH A351;Lo;0;L;;;;;N;;;;;
+1458D;ANATOLIAN HIEROGLYPH A352;Lo;0;L;;;;;N;;;;;
+1458E;ANATOLIAN HIEROGLYPH A353;Lo;0;L;;;;;N;;;;;
+1458F;ANATOLIAN HIEROGLYPH A354;Lo;0;L;;;;;N;;;;;
+14590;ANATOLIAN HIEROGLYPH A355;Lo;0;L;;;;;N;;;;;
+14591;ANATOLIAN HIEROGLYPH A356;Lo;0;L;;;;;N;;;;;
+14592;ANATOLIAN HIEROGLYPH A357;Lo;0;L;;;;;N;;;;;
+14593;ANATOLIAN HIEROGLYPH A358;Lo;0;L;;;;;N;;;;;
+14594;ANATOLIAN HIEROGLYPH A359;Lo;0;L;;;;;N;;;;;
+14595;ANATOLIAN HIEROGLYPH A359A;Lo;0;L;;;;;N;;;;;
+14596;ANATOLIAN HIEROGLYPH A360;Lo;0;L;;;;;N;;;;;
+14597;ANATOLIAN HIEROGLYPH A361;Lo;0;L;;;;;N;;;;;
+14598;ANATOLIAN HIEROGLYPH A362;Lo;0;L;;;;;N;;;;;
+14599;ANATOLIAN HIEROGLYPH A363;Lo;0;L;;;;;N;;;;;
+1459A;ANATOLIAN HIEROGLYPH A364;Lo;0;L;;;;;N;;;;;
+1459B;ANATOLIAN HIEROGLYPH A364A;Lo;0;L;;;;;N;;;;;
+1459C;ANATOLIAN HIEROGLYPH A365;Lo;0;L;;;;;N;;;;;
+1459D;ANATOLIAN HIEROGLYPH A366;Lo;0;L;;;;;N;;;;;
+1459E;ANATOLIAN HIEROGLYPH A367;Lo;0;L;;;;;N;;;;;
+1459F;ANATOLIAN HIEROGLYPH A368;Lo;0;L;;;;;N;;;;;
+145A0;ANATOLIAN HIEROGLYPH A368A;Lo;0;L;;;;;N;;;;;
+145A1;ANATOLIAN HIEROGLYPH A369;Lo;0;L;;;;;N;;;;;
+145A2;ANATOLIAN HIEROGLYPH A370;Lo;0;L;;;;;N;;;;;
+145A3;ANATOLIAN HIEROGLYPH A371;Lo;0;L;;;;;N;;;;;
+145A4;ANATOLIAN HIEROGLYPH A371A;Lo;0;L;;;;;N;;;;;
+145A5;ANATOLIAN HIEROGLYPH A372;Lo;0;L;;;;;N;;;;;
+145A6;ANATOLIAN HIEROGLYPH A373;Lo;0;L;;;;;N;;;;;
+145A7;ANATOLIAN HIEROGLYPH A374;Lo;0;L;;;;;N;;;;;
+145A8;ANATOLIAN HIEROGLYPH A375;Lo;0;L;;;;;N;;;;;
+145A9;ANATOLIAN HIEROGLYPH A376;Lo;0;L;;;;;N;;;;;
+145AA;ANATOLIAN HIEROGLYPH A377;Lo;0;L;;;;;N;;;;;
+145AB;ANATOLIAN HIEROGLYPH A378;Lo;0;L;;;;;N;;;;;
+145AC;ANATOLIAN HIEROGLYPH A379;Lo;0;L;;;;;N;;;;;
+145AD;ANATOLIAN HIEROGLYPH A380;Lo;0;L;;;;;N;;;;;
+145AE;ANATOLIAN HIEROGLYPH A381;Lo;0;L;;;;;N;;;;;
+145AF;ANATOLIAN HIEROGLYPH A381A;Lo;0;L;;;;;N;;;;;
+145B0;ANATOLIAN HIEROGLYPH A382;Lo;0;L;;;;;N;;;;;
+145B1;ANATOLIAN HIEROGLYPH A383 RA OR RI;Lo;0;L;;;;;N;;;;;
+145B2;ANATOLIAN HIEROGLYPH A383A;Lo;0;L;;;;;N;;;;;
+145B3;ANATOLIAN HIEROGLYPH A384;Lo;0;L;;;;;N;;;;;
+145B4;ANATOLIAN HIEROGLYPH A385;Lo;0;L;;;;;N;;;;;
+145B5;ANATOLIAN HIEROGLYPH A386;Lo;0;L;;;;;N;;;;;
+145B6;ANATOLIAN HIEROGLYPH A386A;Lo;0;L;;;;;N;;;;;
+145B7;ANATOLIAN HIEROGLYPH A387;Lo;0;L;;;;;N;;;;;
+145B8;ANATOLIAN HIEROGLYPH A388;Lo;0;L;;;;;N;;;;;
+145B9;ANATOLIAN HIEROGLYPH A389;Lo;0;L;;;;;N;;;;;
+145BA;ANATOLIAN HIEROGLYPH A390;Lo;0;L;;;;;N;;;;;
+145BB;ANATOLIAN HIEROGLYPH A391;Lo;0;L;;;;;N;;;;;
+145BC;ANATOLIAN HIEROGLYPH A392;Lo;0;L;;;;;N;;;;;
+145BD;ANATOLIAN HIEROGLYPH A393 EIGHT;Lo;0;L;;;;;N;;;;;
+145BE;ANATOLIAN HIEROGLYPH A394;Lo;0;L;;;;;N;;;;;
+145BF;ANATOLIAN HIEROGLYPH A395;Lo;0;L;;;;;N;;;;;
+145C0;ANATOLIAN HIEROGLYPH A396;Lo;0;L;;;;;N;;;;;
+145C1;ANATOLIAN HIEROGLYPH A397;Lo;0;L;;;;;N;;;;;
+145C2;ANATOLIAN HIEROGLYPH A398;Lo;0;L;;;;;N;;;;;
+145C3;ANATOLIAN HIEROGLYPH A399;Lo;0;L;;;;;N;;;;;
+145C4;ANATOLIAN HIEROGLYPH A400;Lo;0;L;;;;;N;;;;;
+145C5;ANATOLIAN HIEROGLYPH A401;Lo;0;L;;;;;N;;;;;
+145C6;ANATOLIAN HIEROGLYPH A402;Lo;0;L;;;;;N;;;;;
+145C7;ANATOLIAN HIEROGLYPH A403;Lo;0;L;;;;;N;;;;;
+145C8;ANATOLIAN HIEROGLYPH A404;Lo;0;L;;;;;N;;;;;
+145C9;ANATOLIAN HIEROGLYPH A405;Lo;0;L;;;;;N;;;;;
+145CA;ANATOLIAN HIEROGLYPH A406;Lo;0;L;;;;;N;;;;;
+145CB;ANATOLIAN HIEROGLYPH A407;Lo;0;L;;;;;N;;;;;
+145CC;ANATOLIAN HIEROGLYPH A408;Lo;0;L;;;;;N;;;;;
+145CD;ANATOLIAN HIEROGLYPH A409;Lo;0;L;;;;;N;;;;;
+145CE;ANATOLIAN HIEROGLYPH A410 BEGIN LOGOGRAM MARK;Lo;0;L;;;;;N;;;;;
+145CF;ANATOLIAN HIEROGLYPH A410A END LOGOGRAM MARK;Lo;0;L;;;;;N;;;;;
+145D0;ANATOLIAN HIEROGLYPH A411;Lo;0;L;;;;;N;;;;;
+145D1;ANATOLIAN HIEROGLYPH A412;Lo;0;L;;;;;N;;;;;
+145D2;ANATOLIAN HIEROGLYPH A413;Lo;0;L;;;;;N;;;;;
+145D3;ANATOLIAN HIEROGLYPH A414;Lo;0;L;;;;;N;;;;;
+145D4;ANATOLIAN HIEROGLYPH A415;Lo;0;L;;;;;N;;;;;
+145D5;ANATOLIAN HIEROGLYPH A416;Lo;0;L;;;;;N;;;;;
+145D6;ANATOLIAN HIEROGLYPH A417;Lo;0;L;;;;;N;;;;;
+145D7;ANATOLIAN HIEROGLYPH A418;Lo;0;L;;;;;N;;;;;
+145D8;ANATOLIAN HIEROGLYPH A419;Lo;0;L;;;;;N;;;;;
+145D9;ANATOLIAN HIEROGLYPH A420;Lo;0;L;;;;;N;;;;;
+145DA;ANATOLIAN HIEROGLYPH A421;Lo;0;L;;;;;N;;;;;
+145DB;ANATOLIAN HIEROGLYPH A422;Lo;0;L;;;;;N;;;;;
+145DC;ANATOLIAN HIEROGLYPH A423;Lo;0;L;;;;;N;;;;;
+145DD;ANATOLIAN HIEROGLYPH A424;Lo;0;L;;;;;N;;;;;
+145DE;ANATOLIAN HIEROGLYPH A425;Lo;0;L;;;;;N;;;;;
+145DF;ANATOLIAN HIEROGLYPH A426;Lo;0;L;;;;;N;;;;;
+145E0;ANATOLIAN HIEROGLYPH A427;Lo;0;L;;;;;N;;;;;
+145E1;ANATOLIAN HIEROGLYPH A428;Lo;0;L;;;;;N;;;;;
+145E2;ANATOLIAN HIEROGLYPH A429;Lo;0;L;;;;;N;;;;;
+145E3;ANATOLIAN HIEROGLYPH A430;Lo;0;L;;;;;N;;;;;
+145E4;ANATOLIAN HIEROGLYPH A431;Lo;0;L;;;;;N;;;;;
+145E5;ANATOLIAN HIEROGLYPH A432;Lo;0;L;;;;;N;;;;;
+145E6;ANATOLIAN HIEROGLYPH A433;Lo;0;L;;;;;N;;;;;
+145E7;ANATOLIAN HIEROGLYPH A434;Lo;0;L;;;;;N;;;;;
+145E8;ANATOLIAN HIEROGLYPH A435;Lo;0;L;;;;;N;;;;;
+145E9;ANATOLIAN HIEROGLYPH A436;Lo;0;L;;;;;N;;;;;
+145EA;ANATOLIAN HIEROGLYPH A437;Lo;0;L;;;;;N;;;;;
+145EB;ANATOLIAN HIEROGLYPH A438;Lo;0;L;;;;;N;;;;;
+145EC;ANATOLIAN HIEROGLYPH A439;Lo;0;L;;;;;N;;;;;
+145ED;ANATOLIAN HIEROGLYPH A440;Lo;0;L;;;;;N;;;;;
+145EE;ANATOLIAN HIEROGLYPH A441;Lo;0;L;;;;;N;;;;;
+145EF;ANATOLIAN HIEROGLYPH A442;Lo;0;L;;;;;N;;;;;
+145F0;ANATOLIAN HIEROGLYPH A443;Lo;0;L;;;;;N;;;;;
+145F1;ANATOLIAN HIEROGLYPH A444;Lo;0;L;;;;;N;;;;;
+145F2;ANATOLIAN HIEROGLYPH A445;Lo;0;L;;;;;N;;;;;
+145F3;ANATOLIAN HIEROGLYPH A446;Lo;0;L;;;;;N;;;;;
+145F4;ANATOLIAN HIEROGLYPH A447;Lo;0;L;;;;;N;;;;;
+145F5;ANATOLIAN HIEROGLYPH A448;Lo;0;L;;;;;N;;;;;
+145F6;ANATOLIAN HIEROGLYPH A449;Lo;0;L;;;;;N;;;;;
+145F7;ANATOLIAN HIEROGLYPH A450;Lo;0;L;;;;;N;;;;;
+145F8;ANATOLIAN HIEROGLYPH A450A;Lo;0;L;;;;;N;;;;;
+145F9;ANATOLIAN HIEROGLYPH A451;Lo;0;L;;;;;N;;;;;
+145FA;ANATOLIAN HIEROGLYPH A452;Lo;0;L;;;;;N;;;;;
+145FB;ANATOLIAN HIEROGLYPH A453;Lo;0;L;;;;;N;;;;;
+145FC;ANATOLIAN HIEROGLYPH A454;Lo;0;L;;;;;N;;;;;
+145FD;ANATOLIAN HIEROGLYPH A455;Lo;0;L;;;;;N;;;;;
+145FE;ANATOLIAN HIEROGLYPH A456;Lo;0;L;;;;;N;;;;;
+145FF;ANATOLIAN HIEROGLYPH A457;Lo;0;L;;;;;N;;;;;
+14600;ANATOLIAN HIEROGLYPH A457A;Lo;0;L;;;;;N;;;;;
+14601;ANATOLIAN HIEROGLYPH A458;Lo;0;L;;;;;N;;;;;
+14602;ANATOLIAN HIEROGLYPH A459;Lo;0;L;;;;;N;;;;;
+14603;ANATOLIAN HIEROGLYPH A460;Lo;0;L;;;;;N;;;;;
+14604;ANATOLIAN HIEROGLYPH A461;Lo;0;L;;;;;N;;;;;
+14605;ANATOLIAN HIEROGLYPH A462;Lo;0;L;;;;;N;;;;;
+14606;ANATOLIAN HIEROGLYPH A463;Lo;0;L;;;;;N;;;;;
+14607;ANATOLIAN HIEROGLYPH A464;Lo;0;L;;;;;N;;;;;
+14608;ANATOLIAN HIEROGLYPH A465;Lo;0;L;;;;;N;;;;;
+14609;ANATOLIAN HIEROGLYPH A466;Lo;0;L;;;;;N;;;;;
+1460A;ANATOLIAN HIEROGLYPH A467;Lo;0;L;;;;;N;;;;;
+1460B;ANATOLIAN HIEROGLYPH A468;Lo;0;L;;;;;N;;;;;
+1460C;ANATOLIAN HIEROGLYPH A469;Lo;0;L;;;;;N;;;;;
+1460D;ANATOLIAN HIEROGLYPH A470;Lo;0;L;;;;;N;;;;;
+1460E;ANATOLIAN HIEROGLYPH A471;Lo;0;L;;;;;N;;;;;
+1460F;ANATOLIAN HIEROGLYPH A472;Lo;0;L;;;;;N;;;;;
+14610;ANATOLIAN HIEROGLYPH A473;Lo;0;L;;;;;N;;;;;
+14611;ANATOLIAN HIEROGLYPH A474;Lo;0;L;;;;;N;;;;;
+14612;ANATOLIAN HIEROGLYPH A475;Lo;0;L;;;;;N;;;;;
+14613;ANATOLIAN HIEROGLYPH A476;Lo;0;L;;;;;N;;;;;
+14614;ANATOLIAN HIEROGLYPH A477;Lo;0;L;;;;;N;;;;;
+14615;ANATOLIAN HIEROGLYPH A478;Lo;0;L;;;;;N;;;;;
+14616;ANATOLIAN HIEROGLYPH A479;Lo;0;L;;;;;N;;;;;
+14617;ANATOLIAN HIEROGLYPH A480;Lo;0;L;;;;;N;;;;;
+14618;ANATOLIAN HIEROGLYPH A481;Lo;0;L;;;;;N;;;;;
+14619;ANATOLIAN HIEROGLYPH A482;Lo;0;L;;;;;N;;;;;
+1461A;ANATOLIAN HIEROGLYPH A483;Lo;0;L;;;;;N;;;;;
+1461B;ANATOLIAN HIEROGLYPH A484;Lo;0;L;;;;;N;;;;;
+1461C;ANATOLIAN HIEROGLYPH A485;Lo;0;L;;;;;N;;;;;
+1461D;ANATOLIAN HIEROGLYPH A486;Lo;0;L;;;;;N;;;;;
+1461E;ANATOLIAN HIEROGLYPH A487;Lo;0;L;;;;;N;;;;;
+1461F;ANATOLIAN HIEROGLYPH A488;Lo;0;L;;;;;N;;;;;
+14620;ANATOLIAN HIEROGLYPH A489;Lo;0;L;;;;;N;;;;;
+14621;ANATOLIAN HIEROGLYPH A490;Lo;0;L;;;;;N;;;;;
+14622;ANATOLIAN HIEROGLYPH A491;Lo;0;L;;;;;N;;;;;
+14623;ANATOLIAN HIEROGLYPH A492;Lo;0;L;;;;;N;;;;;
+14624;ANATOLIAN HIEROGLYPH A493;Lo;0;L;;;;;N;;;;;
+14625;ANATOLIAN HIEROGLYPH A494;Lo;0;L;;;;;N;;;;;
+14626;ANATOLIAN HIEROGLYPH A495;Lo;0;L;;;;;N;;;;;
+14627;ANATOLIAN HIEROGLYPH A496;Lo;0;L;;;;;N;;;;;
+14628;ANATOLIAN HIEROGLYPH A497;Lo;0;L;;;;;N;;;;;
+14629;ANATOLIAN HIEROGLYPH A501;Lo;0;L;;;;;N;;;;;
+1462A;ANATOLIAN HIEROGLYPH A502;Lo;0;L;;;;;N;;;;;
+1462B;ANATOLIAN HIEROGLYPH A503;Lo;0;L;;;;;N;;;;;
+1462C;ANATOLIAN HIEROGLYPH A504;Lo;0;L;;;;;N;;;;;
+1462D;ANATOLIAN HIEROGLYPH A505;Lo;0;L;;;;;N;;;;;
+1462E;ANATOLIAN HIEROGLYPH A506;Lo;0;L;;;;;N;;;;;
+1462F;ANATOLIAN HIEROGLYPH A507;Lo;0;L;;;;;N;;;;;
+14630;ANATOLIAN HIEROGLYPH A508;Lo;0;L;;;;;N;;;;;
+14631;ANATOLIAN HIEROGLYPH A509;Lo;0;L;;;;;N;;;;;
+14632;ANATOLIAN HIEROGLYPH A510;Lo;0;L;;;;;N;;;;;
+14633;ANATOLIAN HIEROGLYPH A511;Lo;0;L;;;;;N;;;;;
+14634;ANATOLIAN HIEROGLYPH A512;Lo;0;L;;;;;N;;;;;
+14635;ANATOLIAN HIEROGLYPH A513;Lo;0;L;;;;;N;;;;;
+14636;ANATOLIAN HIEROGLYPH A514;Lo;0;L;;;;;N;;;;;
+14637;ANATOLIAN HIEROGLYPH A515;Lo;0;L;;;;;N;;;;;
+14638;ANATOLIAN HIEROGLYPH A516;Lo;0;L;;;;;N;;;;;
+14639;ANATOLIAN HIEROGLYPH A517;Lo;0;L;;;;;N;;;;;
+1463A;ANATOLIAN HIEROGLYPH A518;Lo;0;L;;;;;N;;;;;
+1463B;ANATOLIAN HIEROGLYPH A519;Lo;0;L;;;;;N;;;;;
+1463C;ANATOLIAN HIEROGLYPH A520;Lo;0;L;;;;;N;;;;;
+1463D;ANATOLIAN HIEROGLYPH A521;Lo;0;L;;;;;N;;;;;
+1463E;ANATOLIAN HIEROGLYPH A522;Lo;0;L;;;;;N;;;;;
+1463F;ANATOLIAN HIEROGLYPH A523;Lo;0;L;;;;;N;;;;;
+14640;ANATOLIAN HIEROGLYPH A524;Lo;0;L;;;;;N;;;;;
+14641;ANATOLIAN HIEROGLYPH A525;Lo;0;L;;;;;N;;;;;
+14642;ANATOLIAN HIEROGLYPH A526;Lo;0;L;;;;;N;;;;;
+14643;ANATOLIAN HIEROGLYPH A527;Lo;0;L;;;;;N;;;;;
+14644;ANATOLIAN HIEROGLYPH A528;Lo;0;L;;;;;N;;;;;
+14645;ANATOLIAN HIEROGLYPH A529;Lo;0;L;;;;;N;;;;;
+14646;ANATOLIAN HIEROGLYPH A530;Lo;0;L;;;;;N;;;;;
16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;;
16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;;
16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;;
@@ -23080,6 +24300,17 @@
1D1DB;MUSICAL SYMBOL SCANDICUS FLEXUS;So;0;L;;;;;N;;;;;
1D1DC;MUSICAL SYMBOL TORCULUS RESUPINUS;So;0;L;;;;;N;;;;;
1D1DD;MUSICAL SYMBOL PES SUBPUNCTIS;So;0;L;;;;;N;;;;;
+1D1DE;MUSICAL SYMBOL KIEVAN C CLEF;So;0;L;;;;;N;;;;;
+1D1DF;MUSICAL SYMBOL KIEVAN END OF PIECE;So;0;L;;;;;N;;;;;
+1D1E0;MUSICAL SYMBOL KIEVAN FINAL NOTE;So;0;L;;;;;N;;;;;
+1D1E1;MUSICAL SYMBOL KIEVAN RECITATIVE MARK;So;0;L;;;;;N;;;;;
+1D1E2;MUSICAL SYMBOL KIEVAN WHOLE NOTE;So;0;L;;;;;N;;;;;
+1D1E3;MUSICAL SYMBOL KIEVAN HALF NOTE;So;0;L;;;;;N;;;;;
+1D1E4;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM DOWN;So;0;L;;;;;N;;;;;
+1D1E5;MUSICAL SYMBOL KIEVAN QUARTER NOTE STEM UP;So;0;L;;;;;N;;;;;
+1D1E6;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM DOWN;So;0;L;;;;;N;;;;;
+1D1E7;MUSICAL SYMBOL KIEVAN EIGHTH NOTE STEM UP;So;0;L;;;;;N;;;;;
+1D1E8;MUSICAL SYMBOL KIEVAN FLAT SIGN;So;0;L;;;;;N;;;;;
1D200;GREEK VOCAL NOTATION SYMBOL-1;So;0;ON;;;;;N;;;;;
1D201;GREEK VOCAL NOTATION SYMBOL-2;So;0;ON;;;;;N;;;;;
1D202;GREEK VOCAL NOTATION SYMBOL-3;So;0;ON;;;;;N;;;;;
@@ -24251,6 +25482,678 @@
1D7FD;MATHEMATICAL MONOSPACE DIGIT SEVEN;Nd;0;EN;<font> 0037;7;7;7;N;;;;;
1D7FE;MATHEMATICAL MONOSPACE DIGIT EIGHT;Nd;0;EN;<font> 0038;8;8;8;N;;;;;
1D7FF;MATHEMATICAL MONOSPACE DIGIT NINE;Nd;0;EN;<font> 0039;9;9;9;N;;;;;
+1D800;SIGNWRITING HAND-FIST INDEX;So;0;L;;;;;N;;;;;
+1D801;SIGNWRITING HAND-CIRCLE INDEX;So;0;L;;;;;N;;;;;
+1D802;SIGNWRITING HAND-CUP INDEX;So;0;L;;;;;N;;;;;
+1D803;SIGNWRITING HAND-OVAL INDEX;So;0;L;;;;;N;;;;;
+1D804;SIGNWRITING HAND-HINGE INDEX;So;0;L;;;;;N;;;;;
+1D805;SIGNWRITING HAND-ANGLE INDEX;So;0;L;;;;;N;;;;;
+1D806;SIGNWRITING HAND-FIST INDEX BENT;So;0;L;;;;;N;;;;;
+1D807;SIGNWRITING HAND-CIRCLE INDEX BENT;So;0;L;;;;;N;;;;;
+1D808;SIGNWRITING HAND-FIST THUMB UNDER INDEX BENT;So;0;L;;;;;N;;;;;
+1D809;SIGNWRITING HAND-FIST INDEX RAISED KNUCKLE;So;0;L;;;;;N;;;;;
+1D80A;SIGNWRITING HAND-FIST INDEX CUPPED;So;0;L;;;;;N;;;;;
+1D80B;SIGNWRITING HAND-FIST INDEX HINGED;So;0;L;;;;;N;;;;;
+1D80C;SIGNWRITING HAND-FIST INDEX HINGED LOW;So;0;L;;;;;N;;;;;
+1D80D;SIGNWRITING HAND-CIRCLE INDEX HINGE;So;0;L;;;;;N;;;;;
+1D80E;SIGNWRITING HAND-FIST INDEX MIDDLE;So;0;L;;;;;N;;;;;
+1D80F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE;So;0;L;;;;;N;;;;;
+1D810;SIGNWRITING HAND-FIST INDEX MIDDLE BENT;So;0;L;;;;;N;;;;;
+1D811;SIGNWRITING HAND-FIST INDEX MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;;
+1D812;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED;So;0;L;;;;;N;;;;;
+1D813;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED;So;0;L;;;;;N;;;;;
+1D814;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP;So;0;L;;;;;N;;;;;
+1D815;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED;So;0;L;;;;;N;;;;;
+1D816;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED INDEX BENT;So;0;L;;;;;N;;;;;
+1D817;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED MIDDLE BENT;So;0;L;;;;;N;;;;;
+1D818;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED;So;0;L;;;;;N;;;;;
+1D819;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED;So;0;L;;;;;N;;;;;
+1D81A;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;;
+1D81B;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSSED;So;0;L;;;;;N;;;;;
+1D81C;SIGNWRITING HAND-FIST MIDDLE BENT OVER INDEX;So;0;L;;;;;N;;;;;
+1D81D;SIGNWRITING HAND-FIST INDEX BENT OVER MIDDLE;So;0;L;;;;;N;;;;;
+1D81E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;;
+1D81F;SIGNWRITING HAND-CIRCLE INDEX MIDDLE THUMB;So;0;L;;;;;N;;;;;
+1D820;SIGNWRITING HAND-FIST INDEX MIDDLE STRAIGHT THUMB BENT;So;0;L;;;;;N;;;;;
+1D821;SIGNWRITING HAND-FIST INDEX MIDDLE BENT THUMB STRAIGHT;So;0;L;;;;;N;;;;;
+1D822;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB BENT;So;0;L;;;;;N;;;;;
+1D823;SIGNWRITING HAND-FIST INDEX MIDDLE HINGED SPREAD THUMB SIDE;So;0;L;;;;;N;;;;;
+1D824;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB SIDE;So;0;L;;;;;N;;;;;
+1D825;SIGNWRITING HAND-FIST INDEX UP MIDDLE HINGED THUMB CONJOINED;So;0;L;;;;;N;;;;;
+1D826;SIGNWRITING HAND-FIST INDEX HINGED MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;;
+1D827;SIGNWRITING HAND-FIST INDEX MIDDLE UP SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D828;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CUPPED;So;0;L;;;;;N;;;;;
+1D829;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CIRCLED;So;0;L;;;;;N;;;;;
+1D82A;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HOOKED;So;0;L;;;;;N;;;;;
+1D82B;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB HINGED;So;0;L;;;;;N;;;;;
+1D82C;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE STRAIGHT;So;0;L;;;;;N;;;;;
+1D82D;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE;So;0;L;;;;;N;;;;;
+1D82E;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;;
+1D82F;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB SIDE BENT;So;0;L;;;;;N;;;;;
+1D830;SIGNWRITING HAND-FIST MIDDLE THUMB HOOKED INDEX UP;So;0;L;;;;;N;;;;;
+1D831;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE UP;So;0;L;;;;;N;;;;;
+1D832;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED HINGED THUMB SIDE;So;0;L;;;;;N;;;;;
+1D833;SIGNWRITING HAND-FIST INDEX MIDDLE CROSSED THUMB SIDE;So;0;L;;;;;N;;;;;
+1D834;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D835;SIGNWRITING HAND-FIST INDEX MIDDLE CONJOINED CUPPED THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D836;SIGNWRITING HAND-FIST MIDDLE THUMB CUPPED INDEX UP;So;0;L;;;;;N;;;;;
+1D837;SIGNWRITING HAND-FIST INDEX THUMB CUPPED MIDDLE UP;So;0;L;;;;;N;;;;;
+1D838;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX UP;So;0;L;;;;;N;;;;;
+1D839;SIGNWRITING HAND-FIST MIDDLE THUMB CIRCLED INDEX HINGED;So;0;L;;;;;N;;;;;
+1D83A;SIGNWRITING HAND-FIST INDEX THUMB ANGLED OUT MIDDLE UP;So;0;L;;;;;N;;;;;
+1D83B;SIGNWRITING HAND-FIST INDEX THUMB ANGLED IN MIDDLE UP;So;0;L;;;;;N;;;;;
+1D83C;SIGNWRITING HAND-FIST INDEX THUMB CIRCLED MIDDLE UP;So;0;L;;;;;N;;;;;
+1D83D;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB CONJOINED HINGED;So;0;L;;;;;N;;;;;
+1D83E;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED OUT;So;0;L;;;;;N;;;;;
+1D83F;SIGNWRITING HAND-FIST INDEX MIDDLE THUMB ANGLED;So;0;L;;;;;N;;;;;
+1D840;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX UP;So;0;L;;;;;N;;;;;
+1D841;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED OUT INDEX CROSSED;So;0;L;;;;;N;;;;;
+1D842;SIGNWRITING HAND-FIST MIDDLE THUMB ANGLED INDEX UP;So;0;L;;;;;N;;;;;
+1D843;SIGNWRITING HAND-FIST INDEX THUMB HOOKED MIDDLE HINGED;So;0;L;;;;;N;;;;;
+1D844;SIGNWRITING HAND-FLAT FOUR FINGERS;So;0;L;;;;;N;;;;;
+1D845;SIGNWRITING HAND-FLAT FOUR FINGERS BENT;So;0;L;;;;;N;;;;;
+1D846;SIGNWRITING HAND-FLAT FOUR FINGERS HINGED;So;0;L;;;;;N;;;;;
+1D847;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;;
+1D848;SIGNWRITING HAND-FLAT FOUR FINGERS CONJOINED SPLIT;So;0;L;;;;;N;;;;;
+1D849;SIGNWRITING HAND-CLAW FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;;
+1D84A;SIGNWRITING HAND-FIST FOUR FINGERS CONJOINED BENT;So;0;L;;;;;N;;;;;
+1D84B;SIGNWRITING HAND-HINGE FOUR FINGERS CONJOINED;So;0;L;;;;;N;;;;;
+1D84C;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;;
+1D84D;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;;
+1D84E;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;;
+1D84F;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD FOUR BENT;So;0;L;;;;;N;;;;;
+1D850;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;;
+1D851;SIGNWRITING HAND-FLAT HEEL FIVE FINGERS SPREAD BENT;So;0;L;;;;;N;;;;;
+1D852;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D853;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;;
+1D854;SIGNWRITING HAND-CUP FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;;
+1D855;SIGNWRITING HAND-HINGE FIVE FINGERS SPREAD OPEN;So;0;L;;;;;N;;;;;
+1D856;SIGNWRITING HAND-OVAL FIVE FINGERS SPREAD;So;0;L;;;;;N;;;;;
+1D857;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED;So;0;L;;;;;N;;;;;
+1D858;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED THUMB SIDE;So;0;L;;;;;N;;;;;
+1D859;SIGNWRITING HAND-FLAT FIVE FINGERS SPREAD HINGED NO THUMB;So;0;L;;;;;N;;;;;
+1D85A;SIGNWRITING HAND-FLAT;So;0;L;;;;;N;;;;;
+1D85B;SIGNWRITING HAND-FLAT BETWEEN PALM FACINGS;So;0;L;;;;;N;;;;;
+1D85C;SIGNWRITING HAND-FLAT HEEL;So;0;L;;;;;N;;;;;
+1D85D;SIGNWRITING HAND-FLAT THUMB SIDE;So;0;L;;;;;N;;;;;
+1D85E;SIGNWRITING HAND-FLAT HEEL THUMB SIDE;So;0;L;;;;;N;;;;;
+1D85F;SIGNWRITING HAND-FLAT THUMB BENT;So;0;L;;;;;N;;;;;
+1D860;SIGNWRITING HAND-FLAT THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D861;SIGNWRITING HAND-FLAT SPLIT INDEX THUMB SIDE;So;0;L;;;;;N;;;;;
+1D862;SIGNWRITING HAND-FLAT SPLIT CENTRE;So;0;L;;;;;N;;;;;
+1D863;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE;So;0;L;;;;;N;;;;;
+1D864;SIGNWRITING HAND-FLAT SPLIT CENTRE THUMB SIDE BENT;So;0;L;;;;;N;;;;;
+1D865;SIGNWRITING HAND-FLAT SPLIT LITTLE;So;0;L;;;;;N;;;;;
+1D866;SIGNWRITING HAND-CLAW;So;0;L;;;;;N;;;;;
+1D867;SIGNWRITING HAND-CLAW THUMB SIDE;So;0;L;;;;;N;;;;;
+1D868;SIGNWRITING HAND-CLAW NO THUMB;So;0;L;;;;;N;;;;;
+1D869;SIGNWRITING HAND-CLAW THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D86A;SIGNWRITING HAND-HOOK CURLICUE;So;0;L;;;;;N;;;;;
+1D86B;SIGNWRITING HAND-HOOK;So;0;L;;;;;N;;;;;
+1D86C;SIGNWRITING HAND-CUP OPEN;So;0;L;;;;;N;;;;;
+1D86D;SIGNWRITING HAND-CUP;So;0;L;;;;;N;;;;;
+1D86E;SIGNWRITING HAND-CUP OPEN THUMB SIDE;So;0;L;;;;;N;;;;;
+1D86F;SIGNWRITING HAND-CUP THUMB SIDE;So;0;L;;;;;N;;;;;
+1D870;SIGNWRITING HAND-CUP OPEN NO THUMB;So;0;L;;;;;N;;;;;
+1D871;SIGNWRITING HAND-CUP NO THUMB;So;0;L;;;;;N;;;;;
+1D872;SIGNWRITING HAND-CUP OPEN THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D873;SIGNWRITING HAND-CUP THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D874;SIGNWRITING HAND-CURLICUE OPEN;So;0;L;;;;;N;;;;;
+1D875;SIGNWRITING HAND-CURLICUE;So;0;L;;;;;N;;;;;
+1D876;SIGNWRITING HAND-CIRCLE;So;0;L;;;;;N;;;;;
+1D877;SIGNWRITING HAND-OVAL;So;0;L;;;;;N;;;;;
+1D878;SIGNWRITING HAND-OVAL THUMB SIDE;So;0;L;;;;;N;;;;;
+1D879;SIGNWRITING HAND-OVAL NO THUMB;So;0;L;;;;;N;;;;;
+1D87A;SIGNWRITING HAND-OVAL THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D87B;SIGNWRITING HAND-HINGE OPEN;So;0;L;;;;;N;;;;;
+1D87C;SIGNWRITING HAND-HINGE OPEN THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D87D;SIGNWRITING HAND-HINGE;So;0;L;;;;;N;;;;;
+1D87E;SIGNWRITING HAND-HINGE SMALL;So;0;L;;;;;N;;;;;
+1D87F;SIGNWRITING HAND-HINGE OPEN THUMB SIDE;So;0;L;;;;;N;;;;;
+1D880;SIGNWRITING HAND-HINGE THUMB SIDE;So;0;L;;;;;N;;;;;
+1D881;SIGNWRITING HAND-HINGE OPEN NO THUMB;So;0;L;;;;;N;;;;;
+1D882;SIGNWRITING HAND-HINGE NO THUMB;So;0;L;;;;;N;;;;;
+1D883;SIGNWRITING HAND-HINGE THUMB SIDE TOUCHING INDEX;So;0;L;;;;;N;;;;;
+1D884;SIGNWRITING HAND-HINGE THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;;
+1D885;SIGNWRITING HAND-ANGLE;So;0;L;;;;;N;;;;;
+1D886;SIGNWRITING HAND-FIST INDEX MIDDLE RING;So;0;L;;;;;N;;;;;
+1D887;SIGNWRITING HAND-CIRCLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;;
+1D888;SIGNWRITING HAND-HINGE INDEX MIDDLE RING;So;0;L;;;;;N;;;;;
+1D889;SIGNWRITING HAND-ANGLE INDEX MIDDLE RING;So;0;L;;;;;N;;;;;
+1D88A;SIGNWRITING HAND-HINGE LITTLE;So;0;L;;;;;N;;;;;
+1D88B;SIGNWRITING HAND-FIST INDEX MIDDLE RING BENT;So;0;L;;;;;N;;;;;
+1D88C;SIGNWRITING HAND-FIST INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;;
+1D88D;SIGNWRITING HAND-HINGE INDEX MIDDLE RING CONJOINED;So;0;L;;;;;N;;;;;
+1D88E;SIGNWRITING HAND-FIST LITTLE DOWN;So;0;L;;;;;N;;;;;
+1D88F;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE STRAIGHT;So;0;L;;;;;N;;;;;
+1D890;SIGNWRITING HAND-FIST LITTLE DOWN RIPPLE CURVED;So;0;L;;;;;N;;;;;
+1D891;SIGNWRITING HAND-FIST LITTLE DOWN OTHERS CIRCLED;So;0;L;;;;;N;;;;;
+1D892;SIGNWRITING HAND-FIST LITTLE UP;So;0;L;;;;;N;;;;;
+1D893;SIGNWRITING HAND-FIST THUMB UNDER LITTLE UP;So;0;L;;;;;N;;;;;
+1D894;SIGNWRITING HAND-CIRCLE LITTLE UP;So;0;L;;;;;N;;;;;
+1D895;SIGNWRITING HAND-OVAL LITTLE UP;So;0;L;;;;;N;;;;;
+1D896;SIGNWRITING HAND-ANGLE LITTLE UP;So;0;L;;;;;N;;;;;
+1D897;SIGNWRITING HAND-FIST LITTLE RAISED KNUCKLE;So;0;L;;;;;N;;;;;
+1D898;SIGNWRITING HAND-FIST LITTLE BENT;So;0;L;;;;;N;;;;;
+1D899;SIGNWRITING HAND-FIST LITTLE TOUCHES THUMB;So;0;L;;;;;N;;;;;
+1D89A;SIGNWRITING HAND-FIST LITTLE THUMB;So;0;L;;;;;N;;;;;
+1D89B;SIGNWRITING HAND-HINGE LITTLE THUMB;So;0;L;;;;;N;;;;;
+1D89C;SIGNWRITING HAND-FIST LITTLE INDEX THUMB;So;0;L;;;;;N;;;;;
+1D89D;SIGNWRITING HAND-HINGE LITTLE INDEX THUMB;So;0;L;;;;;N;;;;;
+1D89E;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB OUT;So;0;L;;;;;N;;;;;
+1D89F;SIGNWRITING HAND-ANGLE LITTLE INDEX THUMB INDEX THUMB;So;0;L;;;;;N;;;;;
+1D8A0;SIGNWRITING HAND-FIST LITTLE INDEX;So;0;L;;;;;N;;;;;
+1D8A1;SIGNWRITING HAND-CIRCLE LITTLE INDEX;So;0;L;;;;;N;;;;;
+1D8A2;SIGNWRITING HAND-HINGE LITTLE INDEX;So;0;L;;;;;N;;;;;
+1D8A3;SIGNWRITING HAND-ANGLE LITTLE INDEX;So;0;L;;;;;N;;;;;
+1D8A4;SIGNWRITING HAND-FIST INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;;
+1D8A5;SIGNWRITING HAND-CIRCLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;;
+1D8A6;SIGNWRITING HAND-HINGE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;;
+1D8A7;SIGNWRITING HAND-HINGE RING;So;0;L;;;;;N;;;;;
+1D8A8;SIGNWRITING HAND-ANGLE INDEX MIDDLE LITTLE;So;0;L;;;;;N;;;;;
+1D8A9;SIGNWRITING HAND-FIST INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;;
+1D8AA;SIGNWRITING HAND-CIRCLE INDEX MIDDLE CROSS LITTLE;So;0;L;;;;;N;;;;;
+1D8AB;SIGNWRITING HAND-FIST RING DOWN;So;0;L;;;;;N;;;;;
+1D8AC;SIGNWRITING HAND-HINGE RING DOWN INDEX THUMB HOOK MIDDLE;So;0;L;;;;;N;;;;;
+1D8AD;SIGNWRITING HAND-ANGLE RING DOWN MIDDLE THUMB INDEX CROSS;So;0;L;;;;;N;;;;;
+1D8AE;SIGNWRITING HAND-FIST RING UP;So;0;L;;;;;N;;;;;
+1D8AF;SIGNWRITING HAND-FIST RING RAISED KNUCKLE;So;0;L;;;;;N;;;;;
+1D8B0;SIGNWRITING HAND-FIST RING LITTLE;So;0;L;;;;;N;;;;;
+1D8B1;SIGNWRITING HAND-CIRCLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8B2;SIGNWRITING HAND-OVAL RING LITTLE;So;0;L;;;;;N;;;;;
+1D8B3;SIGNWRITING HAND-ANGLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8B4;SIGNWRITING HAND-FIST RING MIDDLE;So;0;L;;;;;N;;;;;
+1D8B5;SIGNWRITING HAND-FIST RING MIDDLE CONJOINED;So;0;L;;;;;N;;;;;
+1D8B6;SIGNWRITING HAND-FIST RING MIDDLE RAISED KNUCKLES;So;0;L;;;;;N;;;;;
+1D8B7;SIGNWRITING HAND-FIST RING INDEX;So;0;L;;;;;N;;;;;
+1D8B8;SIGNWRITING HAND-FIST RING THUMB;So;0;L;;;;;N;;;;;
+1D8B9;SIGNWRITING HAND-HOOK RING THUMB;So;0;L;;;;;N;;;;;
+1D8BA;SIGNWRITING HAND-FIST INDEX RING LITTLE;So;0;L;;;;;N;;;;;
+1D8BB;SIGNWRITING HAND-CIRCLE INDEX RING LITTLE;So;0;L;;;;;N;;;;;
+1D8BC;SIGNWRITING HAND-CURLICUE INDEX RING LITTLE ON;So;0;L;;;;;N;;;;;
+1D8BD;SIGNWRITING HAND-HOOK INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;;
+1D8BE;SIGNWRITING HAND-HOOK INDEX RING LITTLE IN;So;0;L;;;;;N;;;;;
+1D8BF;SIGNWRITING HAND-HOOK INDEX RING LITTLE UNDER;So;0;L;;;;;N;;;;;
+1D8C0;SIGNWRITING HAND-CUP INDEX RING LITTLE;So;0;L;;;;;N;;;;;
+1D8C1;SIGNWRITING HAND-HINGE INDEX RING LITTLE;So;0;L;;;;;N;;;;;
+1D8C2;SIGNWRITING HAND-ANGLE INDEX RING LITTLE OUT;So;0;L;;;;;N;;;;;
+1D8C3;SIGNWRITING HAND-ANGLE INDEX RING LITTLE;So;0;L;;;;;N;;;;;
+1D8C4;SIGNWRITING HAND-FIST MIDDLE DOWN;So;0;L;;;;;N;;;;;
+1D8C5;SIGNWRITING HAND-HINGE MIDDLE;So;0;L;;;;;N;;;;;
+1D8C6;SIGNWRITING HAND-FIST MIDDLE UP;So;0;L;;;;;N;;;;;
+1D8C7;SIGNWRITING HAND-CIRCLE MIDDLE UP;So;0;L;;;;;N;;;;;
+1D8C8;SIGNWRITING HAND-FIST MIDDLE RAISED KNUCKLE;So;0;L;;;;;N;;;;;
+1D8C9;SIGNWRITING HAND-FIST MIDDLE UP THUMB SIDE;So;0;L;;;;;N;;;;;
+1D8CA;SIGNWRITING HAND-HOOK MIDDLE THUMB;So;0;L;;;;;N;;;;;
+1D8CB;SIGNWRITING HAND-FIST MIDDLE THUMB LITTLE;So;0;L;;;;;N;;;;;
+1D8CC;SIGNWRITING HAND-FIST MIDDLE LITTLE;So;0;L;;;;;N;;;;;
+1D8CD;SIGNWRITING HAND-FIST MIDDLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8CE;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8CF;SIGNWRITING HAND-CURLICUE MIDDLE RING LITTLE ON;So;0;L;;;;;N;;;;;
+1D8D0;SIGNWRITING HAND-CUP MIDDLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8D1;SIGNWRITING HAND-HINGE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8D2;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE OUT;So;0;L;;;;;N;;;;;
+1D8D3;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE IN;So;0;L;;;;;N;;;;;
+1D8D4;SIGNWRITING HAND-ANGLE MIDDLE RING LITTLE;So;0;L;;;;;N;;;;;
+1D8D5;SIGNWRITING HAND-CIRCLE MIDDLE RING LITTLE BENT;So;0;L;;;;;N;;;;;
+1D8D6;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;;
+1D8D7;SIGNWRITING HAND-CLAW MIDDLE RING LITTLE CONJOINED SIDE;So;0;L;;;;;N;;;;;
+1D8D8;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED OUT;So;0;L;;;;;N;;;;;
+1D8D9;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED IN;So;0;L;;;;;N;;;;;
+1D8DA;SIGNWRITING HAND-HOOK MIDDLE RING LITTLE CONJOINED;So;0;L;;;;;N;;;;;
+1D8DB;SIGNWRITING HAND-HINGE INDEX HINGED;So;0;L;;;;;N;;;;;
+1D8DC;SIGNWRITING HAND-FIST INDEX THUMB SIDE;So;0;L;;;;;N;;;;;
+1D8DD;SIGNWRITING HAND-HINGE INDEX THUMB SIDE;So;0;L;;;;;N;;;;;
+1D8DE;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB DIAGONAL;So;0;L;;;;;N;;;;;
+1D8DF;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB CONJOINED;So;0;L;;;;;N;;;;;
+1D8E0;SIGNWRITING HAND-FIST INDEX THUMB SIDE THUMB BENT;So;0;L;;;;;N;;;;;
+1D8E1;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX BENT;So;0;L;;;;;N;;;;;
+1D8E2;SIGNWRITING HAND-FIST INDEX THUMB SIDE BOTH BENT;So;0;L;;;;;N;;;;;
+1D8E3;SIGNWRITING HAND-FIST INDEX THUMB SIDE INDEX HINGE;So;0;L;;;;;N;;;;;
+1D8E4;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX STRAIGHT;So;0;L;;;;;N;;;;;
+1D8E5;SIGNWRITING HAND-FIST INDEX THUMB FORWARD INDEX BENT;So;0;L;;;;;N;;;;;
+1D8E6;SIGNWRITING HAND-FIST INDEX THUMB HOOK;So;0;L;;;;;N;;;;;
+1D8E7;SIGNWRITING HAND-FIST INDEX THUMB CURLICUE;So;0;L;;;;;N;;;;;
+1D8E8;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;;
+1D8E9;SIGNWRITING HAND-CLAW INDEX THUMB CURVE THUMB INSIDE;So;0;L;;;;;N;;;;;
+1D8EA;SIGNWRITING HAND-FIST INDEX THUMB CURVE THUMB UNDER;So;0;L;;;;;N;;;;;
+1D8EB;SIGNWRITING HAND-FIST INDEX THUMB CIRCLE;So;0;L;;;;;N;;;;;
+1D8EC;SIGNWRITING HAND-CUP INDEX THUMB;So;0;L;;;;;N;;;;;
+1D8ED;SIGNWRITING HAND-CUP INDEX THUMB OPEN;So;0;L;;;;;N;;;;;
+1D8EE;SIGNWRITING HAND-HINGE INDEX THUMB OPEN;So;0;L;;;;;N;;;;;
+1D8EF;SIGNWRITING HAND-HINGE INDEX THUMB LARGE;So;0;L;;;;;N;;;;;
+1D8F0;SIGNWRITING HAND-HINGE INDEX THUMB;So;0;L;;;;;N;;;;;
+1D8F1;SIGNWRITING HAND-HINGE INDEX THUMB SMALL;So;0;L;;;;;N;;;;;
+1D8F2;SIGNWRITING HAND-ANGLE INDEX THUMB OUT;So;0;L;;;;;N;;;;;
+1D8F3;SIGNWRITING HAND-ANGLE INDEX THUMB IN;So;0;L;;;;;N;;;;;
+1D8F4;SIGNWRITING HAND-ANGLE INDEX THUMB;So;0;L;;;;;N;;;;;
+1D8F5;SIGNWRITING HAND-FIST THUMB;So;0;L;;;;;N;;;;;
+1D8F6;SIGNWRITING HAND-FIST THUMB HEEL;So;0;L;;;;;N;;;;;
+1D8F7;SIGNWRITING HAND-FIST THUMB SIDE DIAGONAL;So;0;L;;;;;N;;;;;
+1D8F8;SIGNWRITING HAND-FIST THUMB SIDE CONJOINED;So;0;L;;;;;N;;;;;
+1D8F9;SIGNWRITING HAND-FIST THUMB SIDE BENT;So;0;L;;;;;N;;;;;
+1D8FA;SIGNWRITING HAND-FIST THUMB FORWARD;So;0;L;;;;;N;;;;;
+1D8FB;SIGNWRITING HAND-FIST THUMB BETWEEN INDEX MIDDLE;So;0;L;;;;;N;;;;;
+1D8FC;SIGNWRITING HAND-FIST THUMB BETWEEN MIDDLE RING;So;0;L;;;;;N;;;;;
+1D8FD;SIGNWRITING HAND-FIST THUMB BETWEEN RING LITTLE;So;0;L;;;;;N;;;;;
+1D8FE;SIGNWRITING HAND-FIST THUMB UNDER TWO FINGERS;So;0;L;;;;;N;;;;;
+1D8FF;SIGNWRITING HAND-FIST THUMB OVER TWO FINGERS;So;0;L;;;;;N;;;;;
+1D900;SIGNWRITING HAND-FIST THUMB UNDER THREE FINGERS;So;0;L;;;;;N;;;;;
+1D901;SIGNWRITING HAND-FIST THUMB UNDER FOUR FINGERS;So;0;L;;;;;N;;;;;
+1D902;SIGNWRITING HAND-FIST THUMB OVER FOUR RAISED KNUCKLES;So;0;L;;;;;N;;;;;
+1D903;SIGNWRITING HAND-FIST;So;0;L;;;;;N;;;;;
+1D904;SIGNWRITING HAND-FIST HEEL;So;0;L;;;;;N;;;;;
+1D905;SIGNWRITING TOUCH SINGLE;So;0;L;;;;;N;;;;;
+1D906;SIGNWRITING TOUCH MULTIPLE;So;0;L;;;;;N;;;;;
+1D907;SIGNWRITING TOUCH BETWEEN;So;0;L;;;;;N;;;;;
+1D908;SIGNWRITING GRASP SINGLE;So;0;L;;;;;N;;;;;
+1D909;SIGNWRITING GRASP MULTIPLE;So;0;L;;;;;N;;;;;
+1D90A;SIGNWRITING GRASP BETWEEN;So;0;L;;;;;N;;;;;
+1D90B;SIGNWRITING STRIKE SINGLE;So;0;L;;;;;N;;;;;
+1D90C;SIGNWRITING STRIKE MULTIPLE;So;0;L;;;;;N;;;;;
+1D90D;SIGNWRITING STRIKE BETWEEN;So;0;L;;;;;N;;;;;
+1D90E;SIGNWRITING BRUSH SINGLE;So;0;L;;;;;N;;;;;
+1D90F;SIGNWRITING BRUSH MULTIPLE;So;0;L;;;;;N;;;;;
+1D910;SIGNWRITING BRUSH BETWEEN;So;0;L;;;;;N;;;;;
+1D911;SIGNWRITING RUB SINGLE;So;0;L;;;;;N;;;;;
+1D912;SIGNWRITING RUB MULTIPLE;So;0;L;;;;;N;;;;;
+1D913;SIGNWRITING RUB BETWEEN;So;0;L;;;;;N;;;;;
+1D914;SIGNWRITING SURFACE SYMBOLS;So;0;L;;;;;N;;;;;
+1D915;SIGNWRITING SURFACE BETWEEN;So;0;L;;;;;N;;;;;
+1D916;SIGNWRITING SQUEEZE LARGE SINGLE;So;0;L;;;;;N;;;;;
+1D917;SIGNWRITING SQUEEZE SMALL SINGLE;So;0;L;;;;;N;;;;;
+1D918;SIGNWRITING SQUEEZE LARGE MULTIPLE;So;0;L;;;;;N;;;;;
+1D919;SIGNWRITING SQUEEZE SMALL MULTIPLE;So;0;L;;;;;N;;;;;
+1D91A;SIGNWRITING SQUEEZE SEQUENTIAL;So;0;L;;;;;N;;;;;
+1D91B;SIGNWRITING FLICK LARGE SINGLE;So;0;L;;;;;N;;;;;
+1D91C;SIGNWRITING FLICK SMALL SINGLE;So;0;L;;;;;N;;;;;
+1D91D;SIGNWRITING FLICK LARGE MULTIPLE;So;0;L;;;;;N;;;;;
+1D91E;SIGNWRITING FLICK SMALL MULTIPLE;So;0;L;;;;;N;;;;;
+1D91F;SIGNWRITING FLICK SEQUENTIAL;So;0;L;;;;;N;;;;;
+1D920;SIGNWRITING SQUEEZE FLICK ALTERNATING;So;0;L;;;;;N;;;;;
+1D921;SIGNWRITING MOVEMENT-HINGE UP DOWN LARGE;So;0;L;;;;;N;;;;;
+1D922;SIGNWRITING MOVEMENT-HINGE UP DOWN SMALL;So;0;L;;;;;N;;;;;
+1D923;SIGNWRITING MOVEMENT-HINGE UP SEQUENTIAL;So;0;L;;;;;N;;;;;
+1D924;SIGNWRITING MOVEMENT-HINGE DOWN SEQUENTIAL;So;0;L;;;;;N;;;;;
+1D925;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING LARGE;So;0;L;;;;;N;;;;;
+1D926;SIGNWRITING MOVEMENT-HINGE UP DOWN ALTERNATING SMALL;So;0;L;;;;;N;;;;;
+1D927;SIGNWRITING MOVEMENT-HINGE SIDE TO SIDE SCISSORS;So;0;L;;;;;N;;;;;
+1D928;SIGNWRITING MOVEMENT-WALLPLANE FINGER CONTACT;So;0;L;;;;;N;;;;;
+1D929;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CONTACT;So;0;L;;;;;N;;;;;
+1D92A;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;;
+1D92B;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;;
+1D92C;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;;
+1D92D;SIGNWRITING MOVEMENT-WALLPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;;
+1D92E;SIGNWRITING MOVEMENT-WALLPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;;
+1D92F;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;;
+1D930;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;;
+1D931;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;;
+1D932;SIGNWRITING MOVEMENT-WALLPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;;
+1D933;SIGNWRITING MOVEMENT-WALLPLANE CROSS;So;0;L;;;;;N;;;;;
+1D934;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;;
+1D935;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;;
+1D936;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING;So;0;L;;;;;N;;;;;
+1D937;SIGNWRITING MOVEMENT-WALLPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;;
+1D938;SIGNWRITING MOVEMENT-WALLPLANE BEND SMALL;So;0;L;;;;;N;;;;;
+1D939;SIGNWRITING MOVEMENT-WALLPLANE BEND MEDIUM;So;0;L;;;;;N;;;;;
+1D93A;SIGNWRITING MOVEMENT-WALLPLANE BEND LARGE;So;0;L;;;;;N;;;;;
+1D93B;SIGNWRITING MOVEMENT-WALLPLANE CORNER SMALL;So;0;L;;;;;N;;;;;
+1D93C;SIGNWRITING MOVEMENT-WALLPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;;
+1D93D;SIGNWRITING MOVEMENT-WALLPLANE CORNER LARGE;So;0;L;;;;;N;;;;;
+1D93E;SIGNWRITING MOVEMENT-WALLPLANE CORNER ROTATION;So;0;L;;;;;N;;;;;
+1D93F;SIGNWRITING MOVEMENT-WALLPLANE CHECK SMALL;So;0;L;;;;;N;;;;;
+1D940;SIGNWRITING MOVEMENT-WALLPLANE CHECK MEDIUM;So;0;L;;;;;N;;;;;
+1D941;SIGNWRITING MOVEMENT-WALLPLANE CHECK LARGE;So;0;L;;;;;N;;;;;
+1D942;SIGNWRITING MOVEMENT-WALLPLANE BOX SMALL;So;0;L;;;;;N;;;;;
+1D943;SIGNWRITING MOVEMENT-WALLPLANE BOX MEDIUM;So;0;L;;;;;N;;;;;
+1D944;SIGNWRITING MOVEMENT-WALLPLANE BOX LARGE;So;0;L;;;;;N;;;;;
+1D945;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;;
+1D946;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;;
+1D947;SIGNWRITING MOVEMENT-WALLPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;;
+1D948;SIGNWRITING MOVEMENT-WALLPLANE PEAKS SMALL;So;0;L;;;;;N;;;;;
+1D949;SIGNWRITING MOVEMENT-WALLPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;;
+1D94A;SIGNWRITING MOVEMENT-WALLPLANE PEAKS LARGE;So;0;L;;;;;N;;;;;
+1D94B;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;;
+1D94C;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;;
+1D94D;SIGNWRITING TRAVEL-WALLPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;;
+1D94E;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;;
+1D94F;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;;
+1D950;SIGNWRITING TRAVEL-WALLPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;;
+1D951;SIGNWRITING TRAVEL-WALLPLANE SHAKING;So;0;L;;;;;N;;;;;
+1D952;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL SINGLE;So;0;L;;;;;N;;;;;
+1D953;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL DOUBLE;So;0;L;;;;;N;;;;;
+1D954;SIGNWRITING TRAVEL-WALLPLANE ARM SPIRAL TRIPLE;So;0;L;;;;;N;;;;;
+1D955;SIGNWRITING MOVEMENT-DIAGONAL AWAY SMALL;So;0;L;;;;;N;;;;;
+1D956;SIGNWRITING MOVEMENT-DIAGONAL AWAY MEDIUM;So;0;L;;;;;N;;;;;
+1D957;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGE;So;0;L;;;;;N;;;;;
+1D958;SIGNWRITING MOVEMENT-DIAGONAL AWAY LARGEST;So;0;L;;;;;N;;;;;
+1D959;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS SMALL;So;0;L;;;;;N;;;;;
+1D95A;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS MEDIUM;So;0;L;;;;;N;;;;;
+1D95B;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGE;So;0;L;;;;;N;;;;;
+1D95C;SIGNWRITING MOVEMENT-DIAGONAL TOWARDS LARGEST;So;0;L;;;;;N;;;;;
+1D95D;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY SMALL;So;0;L;;;;;N;;;;;
+1D95E;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY MEDIUM;So;0;L;;;;;N;;;;;
+1D95F;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGE;So;0;L;;;;;N;;;;;
+1D960;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN AWAY LARGEST;So;0;L;;;;;N;;;;;
+1D961;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS SMALL;So;0;L;;;;;N;;;;;
+1D962;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS MEDIUM;So;0;L;;;;;N;;;;;
+1D963;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGE;So;0;L;;;;;N;;;;;
+1D964;SIGNWRITING MOVEMENT-DIAGONAL BETWEEN TOWARDS LARGEST;So;0;L;;;;;N;;;;;
+1D965;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT SMALL;So;0;L;;;;;N;;;;;
+1D966;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT MEDIUM;So;0;L;;;;;N;;;;;
+1D967;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGE;So;0;L;;;;;N;;;;;
+1D968;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE STRAIGHT LARGEST;So;0;L;;;;;N;;;;;
+1D969;SIGNWRITING MOVEMENT-FLOORPLANE SINGLE WRIST FLEX;So;0;L;;;;;N;;;;;
+1D96A;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE STRAIGHT;So;0;L;;;;;N;;;;;
+1D96B;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE WRIST FLEX;So;0;L;;;;;N;;;;;
+1D96C;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING;So;0;L;;;;;N;;;;;
+1D96D;SIGNWRITING MOVEMENT-FLOORPLANE DOUBLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;;
+1D96E;SIGNWRITING MOVEMENT-FLOORPLANE CROSS;So;0;L;;;;;N;;;;;
+1D96F;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE STRAIGHT MOVEMENT;So;0;L;;;;;N;;;;;
+1D970;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE WRIST FLEX;So;0;L;;;;;N;;;;;
+1D971;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING MOVEMENT;So;0;L;;;;;N;;;;;
+1D972;SIGNWRITING MOVEMENT-FLOORPLANE TRIPLE ALTERNATING WRIST FLEX;So;0;L;;;;;N;;;;;
+1D973;SIGNWRITING MOVEMENT-FLOORPLANE BEND;So;0;L;;;;;N;;;;;
+1D974;SIGNWRITING MOVEMENT-FLOORPLANE CORNER SMALL;So;0;L;;;;;N;;;;;
+1D975;SIGNWRITING MOVEMENT-FLOORPLANE CORNER MEDIUM;So;0;L;;;;;N;;;;;
+1D976;SIGNWRITING MOVEMENT-FLOORPLANE CORNER LARGE;So;0;L;;;;;N;;;;;
+1D977;SIGNWRITING MOVEMENT-FLOORPLANE CHECK;So;0;L;;;;;N;;;;;
+1D978;SIGNWRITING MOVEMENT-FLOORPLANE BOX SMALL;So;0;L;;;;;N;;;;;
+1D979;SIGNWRITING MOVEMENT-FLOORPLANE BOX MEDIUM;So;0;L;;;;;N;;;;;
+1D97A;SIGNWRITING MOVEMENT-FLOORPLANE BOX LARGE;So;0;L;;;;;N;;;;;
+1D97B;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG SMALL;So;0;L;;;;;N;;;;;
+1D97C;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG MEDIUM;So;0;L;;;;;N;;;;;
+1D97D;SIGNWRITING MOVEMENT-FLOORPLANE ZIGZAG LARGE;So;0;L;;;;;N;;;;;
+1D97E;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS SMALL;So;0;L;;;;;N;;;;;
+1D97F;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS MEDIUM;So;0;L;;;;;N;;;;;
+1D980;SIGNWRITING MOVEMENT-FLOORPLANE PEAKS LARGE;So;0;L;;;;;N;;;;;
+1D981;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;;
+1D982;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;;
+1D983;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;;
+1D984;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;;
+1D985;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;;
+1D986;SIGNWRITING TRAVEL-FLOORPLANE ROTATION-WALLPLANE ALTERNATING;So;0;L;;;;;N;;;;;
+1D987;SIGNWRITING TRAVEL-FLOORPLANE SHAKING;So;0;L;;;;;N;;;;;
+1D988;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER SMALL;So;0;L;;;;;N;;;;;
+1D989;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER MEDIUM;So;0;L;;;;;N;;;;;
+1D98A;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGE;So;0;L;;;;;N;;;;;
+1D98B;SIGNWRITING MOVEMENT-WALLPLANE CURVE QUARTER LARGEST;So;0;L;;;;;N;;;;;
+1D98C;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE SMALL;So;0;L;;;;;N;;;;;
+1D98D;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE MEDIUM;So;0;L;;;;;N;;;;;
+1D98E;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGE;So;0;L;;;;;N;;;;;
+1D98F;SIGNWRITING MOVEMENT-WALLPLANE CURVE HALF-CIRCLE LARGEST;So;0;L;;;;;N;;;;;
+1D990;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE SMALL;So;0;L;;;;;N;;;;;
+1D991;SIGNWRITING MOVEMENT-WALLPLANE CURVE THREE-QUARTER CIRCLE MEDIUM;So;0;L;;;;;N;;;;;
+1D992;SIGNWRITING MOVEMENT-WALLPLANE HUMP SMALL;So;0;L;;;;;N;;;;;
+1D993;SIGNWRITING MOVEMENT-WALLPLANE HUMP MEDIUM;So;0;L;;;;;N;;;;;
+1D994;SIGNWRITING MOVEMENT-WALLPLANE HUMP LARGE;So;0;L;;;;;N;;;;;
+1D995;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL;So;0;L;;;;;N;;;;;
+1D996;SIGNWRITING MOVEMENT-WALLPLANE LOOP MEDIUM;So;0;L;;;;;N;;;;;
+1D997;SIGNWRITING MOVEMENT-WALLPLANE LOOP LARGE;So;0;L;;;;;N;;;;;
+1D998;SIGNWRITING MOVEMENT-WALLPLANE LOOP SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D999;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE SMALL;So;0;L;;;;;N;;;;;
+1D99A;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE MEDIUM;So;0;L;;;;;N;;;;;
+1D99B;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE DOUBLE LARGE;So;0;L;;;;;N;;;;;
+1D99C;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE SMALL;So;0;L;;;;;N;;;;;
+1D99D;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE MEDIUM;So;0;L;;;;;N;;;;;
+1D99E;SIGNWRITING MOVEMENT-WALLPLANE WAVE CURVE TRIPLE LARGE;So;0;L;;;;;N;;;;;
+1D99F;SIGNWRITING MOVEMENT-WALLPLANE CURVE THEN STRAIGHT;So;0;L;;;;;N;;;;;
+1D9A0;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS SMALL;So;0;L;;;;;N;;;;;
+1D9A1;SIGNWRITING MOVEMENT-WALLPLANE CURVED CROSS MEDIUM;So;0;L;;;;;N;;;;;
+1D9A2;SIGNWRITING ROTATION-WALLPLANE SINGLE;So;0;L;;;;;N;;;;;
+1D9A3;SIGNWRITING ROTATION-WALLPLANE DOUBLE;So;0;L;;;;;N;;;;;
+1D9A4;SIGNWRITING ROTATION-WALLPLANE ALTERNATE;So;0;L;;;;;N;;;;;
+1D9A5;SIGNWRITING MOVEMENT-WALLPLANE SHAKING;So;0;L;;;;;N;;;;;
+1D9A6;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9A7;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9A8;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9A9;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9AA;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9AB;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9AC;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING FRONT WALL;So;0;L;;;;;N;;;;;
+1D9AD;SIGNWRITING MOVEMENT-WALLPLANE CURVE HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9AE;SIGNWRITING MOVEMENT-WALLPLANE HUMP HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9AF;SIGNWRITING MOVEMENT-WALLPLANE LOOP HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9B0;SIGNWRITING MOVEMENT-WALLPLANE WAVE HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9B1;SIGNWRITING ROTATION-WALLPLANE SINGLE HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9B2;SIGNWRITING ROTATION-WALLPLANE DOUBLE HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9B3;SIGNWRITING ROTATION-WALLPLANE ALTERNATING HITTING CHEST;So;0;L;;;;;N;;;;;
+1D9B4;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH SMALL;So;0;L;;;;;N;;;;;
+1D9B5;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH MEDIUM;So;0;L;;;;;N;;;;;
+1D9B6;SIGNWRITING MOVEMENT-WALLPLANE WAVE DIAGONAL PATH LARGE;So;0;L;;;;;N;;;;;
+1D9B7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;;
+1D9B8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;;
+1D9B9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9BA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;;
+1D9BB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING SMALL TRIPLE;So;0;L;;;;;N;;;;;
+1D9BC;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING CEILING LARGE TRIPLE;So;0;L;;;;;N;;;;;
+1D9BD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL SINGLE;So;0;L;;;;;N;;;;;
+1D9BE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE SINGLE;So;0;L;;;;;N;;;;;
+1D9BF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9C0;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING CEILING LARGE DOUBLE;So;0;L;;;;;N;;;;;
+1D9C1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING SMALL;So;0;L;;;;;N;;;;;
+1D9C2;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING CEILING LARGE;So;0;L;;;;;N;;;;;
+1D9C3;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING CEILING;So;0;L;;;;;N;;;;;
+1D9C4;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING CEILING;So;0;L;;;;;N;;;;;
+1D9C5;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING CEILING;So;0;L;;;;;N;;;;;
+1D9C6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;;
+1D9C7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;;
+1D9C8;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9C9;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;;
+1D9CA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE SMALL TRIPLE;So;0;L;;;;;N;;;;;
+1D9CB;SIGNWRITING MOVEMENT-FLOORPLANE HUMP HITTING FLOOR TRIPLE LARGE TRIPLE;So;0;L;;;;;N;;;;;
+1D9CC;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL SINGLE;So;0;L;;;;;N;;;;;
+1D9CD;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE SINGLE;So;0;L;;;;;N;;;;;
+1D9CE;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9CF;SIGNWRITING MOVEMENT-FLOORPLANE LOOP HITTING FLOOR LARGE DOUBLE;So;0;L;;;;;N;;;;;
+1D9D0;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR SMALL;So;0;L;;;;;N;;;;;
+1D9D1;SIGNWRITING MOVEMENT-FLOORPLANE WAVE HITTING FLOOR LARGE;So;0;L;;;;;N;;;;;
+1D9D2;SIGNWRITING ROTATION-FLOORPLANE SINGLE HITTING FLOOR;So;0;L;;;;;N;;;;;
+1D9D3;SIGNWRITING ROTATION-FLOORPLANE DOUBLE HITTING FLOOR;So;0;L;;;;;N;;;;;
+1D9D4;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING HITTING FLOOR;So;0;L;;;;;N;;;;;
+1D9D5;SIGNWRITING MOVEMENT-FLOORPLANE CURVE SMALL;So;0;L;;;;;N;;;;;
+1D9D6;SIGNWRITING MOVEMENT-FLOORPLANE CURVE MEDIUM;So;0;L;;;;;N;;;;;
+1D9D7;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGE;So;0;L;;;;;N;;;;;
+1D9D8;SIGNWRITING MOVEMENT-FLOORPLANE CURVE LARGEST;So;0;L;;;;;N;;;;;
+1D9D9;SIGNWRITING MOVEMENT-FLOORPLANE CURVE COMBINED;So;0;L;;;;;N;;;;;
+1D9DA;SIGNWRITING MOVEMENT-FLOORPLANE HUMP SMALL;So;0;L;;;;;N;;;;;
+1D9DB;SIGNWRITING MOVEMENT-FLOORPLANE LOOP SMALL;So;0;L;;;;;N;;;;;
+1D9DC;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SNAKE;So;0;L;;;;;N;;;;;
+1D9DD;SIGNWRITING MOVEMENT-FLOORPLANE WAVE SMALL;So;0;L;;;;;N;;;;;
+1D9DE;SIGNWRITING MOVEMENT-FLOORPLANE WAVE LARGE;So;0;L;;;;;N;;;;;
+1D9DF;SIGNWRITING ROTATION-FLOORPLANE SINGLE;So;0;L;;;;;N;;;;;
+1D9E0;SIGNWRITING ROTATION-FLOORPLANE DOUBLE;So;0;L;;;;;N;;;;;
+1D9E1;SIGNWRITING ROTATION-FLOORPLANE ALTERNATING;So;0;L;;;;;N;;;;;
+1D9E2;SIGNWRITING MOVEMENT-FLOORPLANE SHAKING PARALLEL;So;0;L;;;;;N;;;;;
+1D9E3;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL SINGLE;So;0;L;;;;;N;;;;;
+1D9E4;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM SINGLE;So;0;L;;;;;N;;;;;
+1D9E5;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9E6;SIGNWRITING MOVEMENT-WALLPLANE ARM CIRCLE MEDIUM DOUBLE;So;0;L;;;;;N;;;;;
+1D9E7;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL SINGLE;So;0;L;;;;;N;;;;;
+1D9E8;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM SINGLE;So;0;L;;;;;N;;;;;
+1D9E9;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE SINGLE;So;0;L;;;;;N;;;;;
+1D9EA;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL SMALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9EB;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL MEDIUM DOUBLE;So;0;L;;;;;N;;;;;
+1D9EC;SIGNWRITING MOVEMENT-FLOORPLANE ARM CIRCLE HITTING WALL LARGE DOUBLE;So;0;L;;;;;N;;;;;
+1D9ED;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT SINGLE;So;0;L;;;;;N;;;;;
+1D9EE;SIGNWRITING MOVEMENT-WALLPLANE WRIST CIRCLE FRONT DOUBLE;So;0;L;;;;;N;;;;;
+1D9EF;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL SINGLE;So;0;L;;;;;N;;;;;
+1D9F0;SIGNWRITING MOVEMENT-FLOORPLANE WRIST CIRCLE HITTING WALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9F1;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES SINGLE;So;0;L;;;;;N;;;;;
+1D9F2;SIGNWRITING MOVEMENT-WALLPLANE FINGER CIRCLES DOUBLE;So;0;L;;;;;N;;;;;
+1D9F3;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL SINGLE;So;0;L;;;;;N;;;;;
+1D9F4;SIGNWRITING MOVEMENT-FLOORPLANE FINGER CIRCLES HITTING WALL DOUBLE;So;0;L;;;;;N;;;;;
+1D9F5;SIGNWRITING DYNAMIC ARROWHEAD SMALL;So;0;L;;;;;N;;;;;
+1D9F6;SIGNWRITING DYNAMIC ARROWHEAD LARGE;So;0;L;;;;;N;;;;;
+1D9F7;SIGNWRITING DYNAMIC FAST;So;0;L;;;;;N;;;;;
+1D9F8;SIGNWRITING DYNAMIC SLOW;So;0;L;;;;;N;;;;;
+1D9F9;SIGNWRITING DYNAMIC TENSE;So;0;L;;;;;N;;;;;
+1D9FA;SIGNWRITING DYNAMIC RELAXED;So;0;L;;;;;N;;;;;
+1D9FB;SIGNWRITING DYNAMIC SIMULTANEOUS;So;0;L;;;;;N;;;;;
+1D9FC;SIGNWRITING DYNAMIC SIMULTANEOUS ALTERNATING;So;0;L;;;;;N;;;;;
+1D9FD;SIGNWRITING DYNAMIC EVERY OTHER TIME;So;0;L;;;;;N;;;;;
+1D9FE;SIGNWRITING DYNAMIC GRADUAL;So;0;L;;;;;N;;;;;
+1D9FF;SIGNWRITING HEAD;So;0;L;;;;;N;;;;;
+1DA00;SIGNWRITING HEAD RIM;Mn;0;NSM;;;;;N;;;;;
+1DA01;SIGNWRITING HEAD MOVEMENT-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;;
+1DA02;SIGNWRITING HEAD MOVEMENT-WALLPLANE TILT;Mn;0;NSM;;;;;N;;;;;
+1DA03;SIGNWRITING HEAD MOVEMENT-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;;
+1DA04;SIGNWRITING HEAD MOVEMENT-WALLPLANE CURVE;Mn;0;NSM;;;;;N;;;;;
+1DA05;SIGNWRITING HEAD MOVEMENT-FLOORPLANE CURVE;Mn;0;NSM;;;;;N;;;;;
+1DA06;SIGNWRITING HEAD MOVEMENT CIRCLE;Mn;0;NSM;;;;;N;;;;;
+1DA07;SIGNWRITING FACE DIRECTION POSITION NOSE FORWARD TILTING;Mn;0;NSM;;;;;N;;;;;
+1DA08;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN;Mn;0;NSM;;;;;N;;;;;
+1DA09;SIGNWRITING FACE DIRECTION POSITION NOSE UP OR DOWN TILTING;Mn;0;NSM;;;;;N;;;;;
+1DA0A;SIGNWRITING EYEBROWS STRAIGHT UP;Mn;0;NSM;;;;;N;;;;;
+1DA0B;SIGNWRITING EYEBROWS STRAIGHT NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA0C;SIGNWRITING EYEBROWS STRAIGHT DOWN;Mn;0;NSM;;;;;N;;;;;
+1DA0D;SIGNWRITING DREAMY EYEBROWS NEUTRAL DOWN;Mn;0;NSM;;;;;N;;;;;
+1DA0E;SIGNWRITING DREAMY EYEBROWS DOWN NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA0F;SIGNWRITING DREAMY EYEBROWS UP NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA10;SIGNWRITING DREAMY EYEBROWS NEUTRAL UP;Mn;0;NSM;;;;;N;;;;;
+1DA11;SIGNWRITING FOREHEAD NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA12;SIGNWRITING FOREHEAD CONTACT;Mn;0;NSM;;;;;N;;;;;
+1DA13;SIGNWRITING FOREHEAD WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA14;SIGNWRITING EYES OPEN;Mn;0;NSM;;;;;N;;;;;
+1DA15;SIGNWRITING EYES SQUEEZED;Mn;0;NSM;;;;;N;;;;;
+1DA16;SIGNWRITING EYES CLOSED;Mn;0;NSM;;;;;N;;;;;
+1DA17;SIGNWRITING EYE BLINK SINGLE;Mn;0;NSM;;;;;N;;;;;
+1DA18;SIGNWRITING EYE BLINK MULTIPLE;Mn;0;NSM;;;;;N;;;;;
+1DA19;SIGNWRITING EYES HALF OPEN;Mn;0;NSM;;;;;N;;;;;
+1DA1A;SIGNWRITING EYES WIDE OPEN;Mn;0;NSM;;;;;N;;;;;
+1DA1B;SIGNWRITING EYES HALF CLOSED;Mn;0;NSM;;;;;N;;;;;
+1DA1C;SIGNWRITING EYES WIDENING MOVEMENT;Mn;0;NSM;;;;;N;;;;;
+1DA1D;SIGNWRITING EYE WINK;Mn;0;NSM;;;;;N;;;;;
+1DA1E;SIGNWRITING EYELASHES UP;Mn;0;NSM;;;;;N;;;;;
+1DA1F;SIGNWRITING EYELASHES DOWN;Mn;0;NSM;;;;;N;;;;;
+1DA20;SIGNWRITING EYELASHES FLUTTERING;Mn;0;NSM;;;;;N;;;;;
+1DA21;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;;
+1DA22;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;;
+1DA23;SIGNWRITING EYEGAZE-WALLPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;;
+1DA24;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT;Mn;0;NSM;;;;;N;;;;;
+1DA25;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT DOUBLE;Mn;0;NSM;;;;;N;;;;;
+1DA26;SIGNWRITING EYEGAZE-FLOORPLANE STRAIGHT ALTERNATING;Mn;0;NSM;;;;;N;;;;;
+1DA27;SIGNWRITING EYEGAZE-WALLPLANE CURVED;Mn;0;NSM;;;;;N;;;;;
+1DA28;SIGNWRITING EYEGAZE-FLOORPLANE CURVED;Mn;0;NSM;;;;;N;;;;;
+1DA29;SIGNWRITING EYEGAZE-WALLPLANE CIRCLING;Mn;0;NSM;;;;;N;;;;;
+1DA2A;SIGNWRITING CHEEKS PUFFED;Mn;0;NSM;;;;;N;;;;;
+1DA2B;SIGNWRITING CHEEKS NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA2C;SIGNWRITING CHEEKS SUCKED;Mn;0;NSM;;;;;N;;;;;
+1DA2D;SIGNWRITING TENSE CHEEKS HIGH;Mn;0;NSM;;;;;N;;;;;
+1DA2E;SIGNWRITING TENSE CHEEKS MIDDLE;Mn;0;NSM;;;;;N;;;;;
+1DA2F;SIGNWRITING TENSE CHEEKS LOW;Mn;0;NSM;;;;;N;;;;;
+1DA30;SIGNWRITING EARS;Mn;0;NSM;;;;;N;;;;;
+1DA31;SIGNWRITING NOSE NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA32;SIGNWRITING NOSE CONTACT;Mn;0;NSM;;;;;N;;;;;
+1DA33;SIGNWRITING NOSE WRINKLES;Mn;0;NSM;;;;;N;;;;;
+1DA34;SIGNWRITING NOSE WIGGLES;Mn;0;NSM;;;;;N;;;;;
+1DA35;SIGNWRITING AIR BLOWING OUT;Mn;0;NSM;;;;;N;;;;;
+1DA36;SIGNWRITING AIR SUCKING IN;Mn;0;NSM;;;;;N;;;;;
+1DA37;SIGNWRITING AIR BLOW SMALL ROTATIONS;So;0;L;;;;;N;;;;;
+1DA38;SIGNWRITING AIR SUCK SMALL ROTATIONS;So;0;L;;;;;N;;;;;
+1DA39;SIGNWRITING BREATH INHALE;So;0;L;;;;;N;;;;;
+1DA3A;SIGNWRITING BREATH EXHALE;So;0;L;;;;;N;;;;;
+1DA3B;SIGNWRITING MOUTH CLOSED NEUTRAL;Mn;0;NSM;;;;;N;;;;;
+1DA3C;SIGNWRITING MOUTH CLOSED FORWARD;Mn;0;NSM;;;;;N;;;;;
+1DA3D;SIGNWRITING MOUTH CLOSED CONTACT;Mn;0;NSM;;;;;N;;;;;
+1DA3E;SIGNWRITING MOUTH SMILE;Mn;0;NSM;;;;;N;;;;;
+1DA3F;SIGNWRITING MOUTH SMILE WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA40;SIGNWRITING MOUTH SMILE OPEN;Mn;0;NSM;;;;;N;;;;;
+1DA41;SIGNWRITING MOUTH FROWN;Mn;0;NSM;;;;;N;;;;;
+1DA42;SIGNWRITING MOUTH FROWN WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA43;SIGNWRITING MOUTH FROWN OPEN;Mn;0;NSM;;;;;N;;;;;
+1DA44;SIGNWRITING MOUTH OPEN CIRCLE;Mn;0;NSM;;;;;N;;;;;
+1DA45;SIGNWRITING MOUTH OPEN FORWARD;Mn;0;NSM;;;;;N;;;;;
+1DA46;SIGNWRITING MOUTH OPEN WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA47;SIGNWRITING MOUTH OPEN OVAL;Mn;0;NSM;;;;;N;;;;;
+1DA48;SIGNWRITING MOUTH OPEN OVAL WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA49;SIGNWRITING MOUTH OPEN OVAL YAWN;Mn;0;NSM;;;;;N;;;;;
+1DA4A;SIGNWRITING MOUTH OPEN RECTANGLE;Mn;0;NSM;;;;;N;;;;;
+1DA4B;SIGNWRITING MOUTH OPEN RECTANGLE WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA4C;SIGNWRITING MOUTH OPEN RECTANGLE YAWN;Mn;0;NSM;;;;;N;;;;;
+1DA4D;SIGNWRITING MOUTH KISS;Mn;0;NSM;;;;;N;;;;;
+1DA4E;SIGNWRITING MOUTH KISS FORWARD;Mn;0;NSM;;;;;N;;;;;
+1DA4F;SIGNWRITING MOUTH KISS WRINKLED;Mn;0;NSM;;;;;N;;;;;
+1DA50;SIGNWRITING MOUTH TENSE;Mn;0;NSM;;;;;N;;;;;
+1DA51;SIGNWRITING MOUTH TENSE FORWARD;Mn;0;NSM;;;;;N;;;;;
+1DA52;SIGNWRITING MOUTH TENSE SUCKED;Mn;0;NSM;;;;;N;;;;;
+1DA53;SIGNWRITING LIPS PRESSED TOGETHER;Mn;0;NSM;;;;;N;;;;;
+1DA54;SIGNWRITING LIP LOWER OVER UPPER;Mn;0;NSM;;;;;N;;;;;
+1DA55;SIGNWRITING LIP UPPER OVER LOWER;Mn;0;NSM;;;;;N;;;;;
+1DA56;SIGNWRITING MOUTH CORNERS;Mn;0;NSM;;;;;N;;;;;
+1DA57;SIGNWRITING MOUTH WRINKLES SINGLE;Mn;0;NSM;;;;;N;;;;;
+1DA58;SIGNWRITING MOUTH WRINKLES DOUBLE;Mn;0;NSM;;;;;N;;;;;
+1DA59;SIGNWRITING TONGUE STICKING OUT FAR;Mn;0;NSM;;;;;N;;;;;
+1DA5A;SIGNWRITING TONGUE LICKING LIPS;Mn;0;NSM;;;;;N;;;;;
+1DA5B;SIGNWRITING TONGUE TIP BETWEEN LIPS;Mn;0;NSM;;;;;N;;;;;
+1DA5C;SIGNWRITING TONGUE TIP TOUCHING INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;;
+1DA5D;SIGNWRITING TONGUE INSIDE MOUTH RELAXED;Mn;0;NSM;;;;;N;;;;;
+1DA5E;SIGNWRITING TONGUE MOVES AGAINST CHEEK;Mn;0;NSM;;;;;N;;;;;
+1DA5F;SIGNWRITING TONGUE CENTRE STICKING OUT;Mn;0;NSM;;;;;N;;;;;
+1DA60;SIGNWRITING TONGUE CENTRE INSIDE MOUTH;Mn;0;NSM;;;;;N;;;;;
+1DA61;SIGNWRITING TEETH;Mn;0;NSM;;;;;N;;;;;
+1DA62;SIGNWRITING TEETH MOVEMENT;Mn;0;NSM;;;;;N;;;;;
+1DA63;SIGNWRITING TEETH ON TONGUE;Mn;0;NSM;;;;;N;;;;;
+1DA64;SIGNWRITING TEETH ON TONGUE MOVEMENT;Mn;0;NSM;;;;;N;;;;;
+1DA65;SIGNWRITING TEETH ON LIPS;Mn;0;NSM;;;;;N;;;;;
+1DA66;SIGNWRITING TEETH ON LIPS MOVEMENT;Mn;0;NSM;;;;;N;;;;;
+1DA67;SIGNWRITING TEETH BITE LIPS;Mn;0;NSM;;;;;N;;;;;
+1DA68;SIGNWRITING MOVEMENT-WALLPLANE JAW;Mn;0;NSM;;;;;N;;;;;
+1DA69;SIGNWRITING MOVEMENT-FLOORPLANE JAW;Mn;0;NSM;;;;;N;;;;;
+1DA6A;SIGNWRITING NECK;Mn;0;NSM;;;;;N;;;;;
+1DA6B;SIGNWRITING HAIR;Mn;0;NSM;;;;;N;;;;;
+1DA6C;SIGNWRITING EXCITEMENT;Mn;0;NSM;;;;;N;;;;;
+1DA6D;SIGNWRITING SHOULDER HIP SPINE;So;0;L;;;;;N;;;;;
+1DA6E;SIGNWRITING SHOULDER HIP POSITIONS;So;0;L;;;;;N;;;;;
+1DA6F;SIGNWRITING WALLPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;;
+1DA70;SIGNWRITING FLOORPLANE SHOULDER HIP MOVE;So;0;L;;;;;N;;;;;
+1DA71;SIGNWRITING SHOULDER TILTING FROM WAIST;So;0;L;;;;;N;;;;;
+1DA72;SIGNWRITING TORSO-WALLPLANE STRAIGHT STRETCH;So;0;L;;;;;N;;;;;
+1DA73;SIGNWRITING TORSO-WALLPLANE CURVED BEND;So;0;L;;;;;N;;;;;
+1DA74;SIGNWRITING TORSO-FLOORPLANE TWISTING;So;0;L;;;;;N;;;;;
+1DA75;SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS;Mn;0;NSM;;;;;N;;;;;
+1DA76;SIGNWRITING LIMB COMBINATION;So;0;L;;;;;N;;;;;
+1DA77;SIGNWRITING LIMB LENGTH-1;So;0;L;;;;;N;;;;;
+1DA78;SIGNWRITING LIMB LENGTH-2;So;0;L;;;;;N;;;;;
+1DA79;SIGNWRITING LIMB LENGTH-3;So;0;L;;;;;N;;;;;
+1DA7A;SIGNWRITING LIMB LENGTH-4;So;0;L;;;;;N;;;;;
+1DA7B;SIGNWRITING LIMB LENGTH-5;So;0;L;;;;;N;;;;;
+1DA7C;SIGNWRITING LIMB LENGTH-6;So;0;L;;;;;N;;;;;
+1DA7D;SIGNWRITING LIMB LENGTH-7;So;0;L;;;;;N;;;;;
+1DA7E;SIGNWRITING FINGER;So;0;L;;;;;N;;;;;
+1DA7F;SIGNWRITING LOCATION-WALLPLANE SPACE;So;0;L;;;;;N;;;;;
+1DA80;SIGNWRITING LOCATION-FLOORPLANE SPACE;So;0;L;;;;;N;;;;;
+1DA81;SIGNWRITING LOCATION HEIGHT;So;0;L;;;;;N;;;;;
+1DA82;SIGNWRITING LOCATION WIDTH;So;0;L;;;;;N;;;;;
+1DA83;SIGNWRITING LOCATION DEPTH;So;0;L;;;;;N;;;;;
+1DA84;SIGNWRITING LOCATION HEAD NECK;Mn;0;NSM;;;;;N;;;;;
+1DA85;SIGNWRITING LOCATION TORSO;So;0;L;;;;;N;;;;;
+1DA86;SIGNWRITING LOCATION LIMBS DIGITS;So;0;L;;;;;N;;;;;
+1DA87;SIGNWRITING COMMA;Po;0;L;;;;;N;;;;;
+1DA88;SIGNWRITING FULL STOP;Po;0;L;;;;;N;;;;;
+1DA89;SIGNWRITING SEMICOLON;Po;0;L;;;;;N;;;;;
+1DA8A;SIGNWRITING COLON;Po;0;L;;;;;N;;;;;
+1DA8B;SIGNWRITING PARENTHESIS;Po;0;L;;;;;N;;;;;
+1DA9B;SIGNWRITING FILL MODIFIER-2;Mn;0;NSM;;;;;N;;;;;
+1DA9C;SIGNWRITING FILL MODIFIER-3;Mn;0;NSM;;;;;N;;;;;
+1DA9D;SIGNWRITING FILL MODIFIER-4;Mn;0;NSM;;;;;N;;;;;
+1DA9E;SIGNWRITING FILL MODIFIER-5;Mn;0;NSM;;;;;N;;;;;
+1DA9F;SIGNWRITING FILL MODIFIER-6;Mn;0;NSM;;;;;N;;;;;
+1DAA1;SIGNWRITING ROTATION MODIFIER-2;Mn;0;NSM;;;;;N;;;;;
+1DAA2;SIGNWRITING ROTATION MODIFIER-3;Mn;0;NSM;;;;;N;;;;;
+1DAA3;SIGNWRITING ROTATION MODIFIER-4;Mn;0;NSM;;;;;N;;;;;
+1DAA4;SIGNWRITING ROTATION MODIFIER-5;Mn;0;NSM;;;;;N;;;;;
+1DAA5;SIGNWRITING ROTATION MODIFIER-6;Mn;0;NSM;;;;;N;;;;;
+1DAA6;SIGNWRITING ROTATION MODIFIER-7;Mn;0;NSM;;;;;N;;;;;
+1DAA7;SIGNWRITING ROTATION MODIFIER-8;Mn;0;NSM;;;;;N;;;;;
+1DAA8;SIGNWRITING ROTATION MODIFIER-9;Mn;0;NSM;;;;;N;;;;;
+1DAA9;SIGNWRITING ROTATION MODIFIER-10;Mn;0;NSM;;;;;N;;;;;
+1DAAA;SIGNWRITING ROTATION MODIFIER-11;Mn;0;NSM;;;;;N;;;;;
+1DAAB;SIGNWRITING ROTATION MODIFIER-12;Mn;0;NSM;;;;;N;;;;;
+1DAAC;SIGNWRITING ROTATION MODIFIER-13;Mn;0;NSM;;;;;N;;;;;
+1DAAD;SIGNWRITING ROTATION MODIFIER-14;Mn;0;NSM;;;;;N;;;;;
+1DAAE;SIGNWRITING ROTATION MODIFIER-15;Mn;0;NSM;;;;;N;;;;;
+1DAAF;SIGNWRITING ROTATION MODIFIER-16;Mn;0;NSM;;;;;N;;;;;
1E800;MENDE KIKAKUI SYLLABLE M001 KI;Lo;0;R;;;;;N;;;;;
1E801;MENDE KIKAKUI SYLLABLE M002 KA;Lo;0;R;;;;;N;;;;;
1E802;MENDE KIKAKUI SYLLABLE M003 KU;Lo;0;R;;;;;N;;;;;
@@ -25108,6 +27011,9 @@
1F32A;CLOUD WITH TORNADO;So;0;ON;;;;;N;;;;;
1F32B;FOG;So;0;ON;;;;;N;;;;;
1F32C;WIND BLOWING FACE;So;0;ON;;;;;N;;;;;
+1F32D;HOT DOG;So;0;ON;;;;;N;;;;;
+1F32E;TACO;So;0;ON;;;;;N;;;;;
+1F32F;BURRITO;So;0;ON;;;;;N;;;;;
1F330;CHESTNUT;So;0;ON;;;;;N;;;;;
1F331;SEEDLING;So;0;ON;;;;;N;;;;;
1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;;
@@ -25186,6 +27092,8 @@
1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;;
1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;;
1F37D;FORK AND KNIFE WITH PLATE;So;0;ON;;;;;N;;;;;
+1F37E;BOTTLE WITH POPPING CORK;So;0;ON;;;;;N;;;;;
+1F37F;POPCORN;So;0;ON;;;;;N;;;;;
1F380;RIBBON;So;0;ON;;;;;N;;;;;
1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;;
1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;;
@@ -25265,6 +27173,11 @@
1F3CC;GOLFER;So;0;ON;;;;;N;;;;;
1F3CD;RACING MOTORCYCLE;So;0;ON;;;;;N;;;;;
1F3CE;RACING CAR;So;0;ON;;;;;N;;;;;
+1F3CF;CRICKET BAT AND BALL;So;0;ON;;;;;N;;;;;
+1F3D0;VOLLEYBALL;So;0;ON;;;;;N;;;;;
+1F3D1;FIELD HOCKEY STICK AND BALL;So;0;ON;;;;;N;;;;;
+1F3D2;ICE HOCKEY STICK AND PUCK;So;0;ON;;;;;N;;;;;
+1F3D3;TABLE TENNIS PADDLE AND BALL;So;0;ON;;;;;N;;;;;
1F3D4;SNOW CAPPED MOUNTAIN;So;0;ON;;;;;N;;;;;
1F3D5;CAMPING;So;0;ON;;;;;N;;;;;
1F3D6;BEACH WITH UMBRELLA;So;0;ON;;;;;N;;;;;
@@ -25301,6 +27214,14 @@
1F3F5;ROSETTE;So;0;ON;;;;;N;;;;;
1F3F6;BLACK ROSETTE;So;0;ON;;;;;N;;;;;
1F3F7;LABEL;So;0;ON;;;;;N;;;;;
+1F3F8;BADMINTON RACQUET AND SHUTTLECOCK;So;0;ON;;;;;N;;;;;
+1F3F9;BOW AND ARROW;So;0;ON;;;;;N;;;;;
+1F3FA;AMPHORA;So;0;ON;;;;;N;;;;;
+1F3FB;EMOJI MODIFIER FITZPATRICK TYPE-1-2;Sk;0;ON;;;;;N;;;;;
+1F3FC;EMOJI MODIFIER FITZPATRICK TYPE-3;Sk;0;ON;;;;;N;;;;;
+1F3FD;EMOJI MODIFIER FITZPATRICK TYPE-4;Sk;0;ON;;;;;N;;;;;
+1F3FE;EMOJI MODIFIER FITZPATRICK TYPE-5;Sk;0;ON;;;;;N;;;;;
+1F3FF;EMOJI MODIFIER FITZPATRICK TYPE-6;Sk;0;ON;;;;;N;;;;;
1F400;RAT;So;0;ON;;;;;N;;;;;
1F401;MOUSE;So;0;ON;;;;;N;;;;;
1F402;OX;So;0;ON;;;;;N;;;;;
@@ -25556,6 +27477,7 @@
1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;;
1F4FD;FILM PROJECTOR;So;0;ON;;;;;N;;;;;
1F4FE;PORTABLE STEREO;So;0;ON;;;;;N;;;;;
+1F4FF;PRAYER BEADS;So;0;ON;;;;;N;;;;;
1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;;
1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;;
1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;;
@@ -25631,6 +27553,11 @@
1F548;CELTIC CROSS;So;0;ON;;;;;N;;;;;
1F549;OM SYMBOL;So;0;ON;;;;;N;;;;;
1F54A;DOVE OF PEACE;So;0;ON;;;;;N;;;;;
+1F54B;KAABA;So;0;ON;;;;;N;;;;;
+1F54C;MOSQUE;So;0;ON;;;;;N;;;;;
+1F54D;SYNAGOGUE;So;0;ON;;;;;N;;;;;
+1F54E;MENORAH WITH NINE BRANCHES;So;0;ON;;;;;N;;;;;
+1F54F;BOWL OF HYGIEIA;So;0;ON;;;;;N;;;;;
1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;;
1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;;
1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;;
@@ -25872,6 +27799,8 @@
1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;;
1F641;SLIGHTLY FROWNING FACE;So;0;ON;;;;;N;;;;;
1F642;SLIGHTLY SMILING FACE;So;0;ON;;;;;N;;;;;
+1F643;UPSIDE-DOWN FACE;So;0;ON;;;;;N;;;;;
+1F644;FACE WITH ROLLING EYES;So;0;ON;;;;;N;;;;;
1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;;
1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;;
1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;;
@@ -26011,6 +27940,7 @@
1F6CD;SHOPPING BAGS;So;0;ON;;;;;N;;;;;
1F6CE;BELLHOP BELL;So;0;ON;;;;;N;;;;;
1F6CF;BED;So;0;ON;;;;;N;;;;;
+1F6D0;PLACE OF WORSHIP;So;0;ON;;;;;N;;;;;
1F6E0;HAMMER AND WRENCH;So;0;ON;;;;;N;;;;;
1F6E1;SHIELD;So;0;ON;;;;;N;;;;;
1F6E2;OIL DRUM;So;0;ON;;;;;N;;;;;
@@ -26377,12 +28307,29 @@
1F8AB;RIGHTWARDS FRONT-TILTED SHADOWED WHITE ARROW;So;0;ON;;;;;N;;;;;
1F8AC;WHITE ARROW SHAFT WIDTH ONE;So;0;ON;;;;;N;;;;;
1F8AD;WHITE ARROW SHAFT WIDTH TWO THIRDS;So;0;ON;;;;;N;;;;;
+1F910;ZIPPER-MOUTH FACE;So;0;ON;;;;;N;;;;;
+1F911;MONEY-MOUTH FACE;So;0;ON;;;;;N;;;;;
+1F912;FACE WITH THERMOMETER;So;0;ON;;;;;N;;;;;
+1F913;NERD FACE;So;0;ON;;;;;N;;;;;
+1F914;THINKING FACE;So;0;ON;;;;;N;;;;;
+1F915;FACE WITH HEAD-BANDAGE;So;0;ON;;;;;N;;;;;
+1F916;ROBOT FACE;So;0;ON;;;;;N;;;;;
+1F917;HUGGING FACE;So;0;ON;;;;;N;;;;;
+1F918;SIGN OF THE HORNS;So;0;ON;;;;;N;;;;;
+1F980;CRAB;So;0;ON;;;;;N;;;;;
+1F981;LION FACE;So;0;ON;;;;;N;;;;;
+1F982;SCORPION;So;0;ON;;;;;N;;;;;
+1F983;TURKEY;So;0;ON;;;;;N;;;;;
+1F984;UNICORN FACE;So;0;ON;;;;;N;;;;;
+1F9C0;CHEESE WEDGE;So;0;ON;;;;;N;;;;;
20000;<CJK Ideograph Extension B, First>;Lo;0;L;;;;;N;;;;;
2A6D6;<CJK Ideograph Extension B, Last>;Lo;0;L;;;;;N;;;;;
2A700;<CJK Ideograph Extension C, First>;Lo;0;L;;;;;N;;;;;
2B734;<CJK Ideograph Extension C, Last>;Lo;0;L;;;;;N;;;;;
2B740;<CJK Ideograph Extension D, First>;Lo;0;L;;;;;N;;;;;
2B81D;<CJK Ideograph Extension D, Last>;Lo;0;L;;;;;N;;;;;
+2B820;<CJK Ideograph Extension E, First>;Lo;0;L;;;;;N;;;;;
+2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
--- a/jdk/make/data/unicodedata/VERSION Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/data/unicodedata/VERSION Tue Oct 20 08:24:37 2015 -0700
@@ -1,1 +1,1 @@
-7.0.0
+8.0.0
--- a/jdk/make/gendata/Gendata-java.base.gmk Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/gendata/Gendata-java.base.gmk Tue Oct 20 08:24:37 2015 -0700
@@ -70,7 +70,7 @@
$(ECHO) "Generating java.security"
$(MKDIR) -p $(@D)
$(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \
- $(RESTRICTED_PKGS_SRC) || exit 1
+ $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC) || exit 1
TARGETS += $(GENDATA_JAVA_SECURITY)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/launcher/Launcher-jdk.jshell.gmk Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LauncherCommon.gmk
+
+$(eval $(call SetupLauncher,jshell, \
+ -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE \
+ -DJAVA_ARGS='{ "-J-ms8m"$(COMMA) "jdk.internal.jshell.tool.JShellTool"$(COMMA) }'))
--- a/jdk/make/mapfiles/libjava/mapfile-vers Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Tue Oct 20 08:24:37 2015 -0700
@@ -152,7 +152,6 @@
Java_java_lang_StrictMath_log10;
Java_java_lang_StrictMath_sin;
Java_java_lang_StrictMath_sqrt;
- Java_java_lang_StrictMath_cbrt;
Java_java_lang_StrictMath_tan;
Java_java_lang_StrictMath_cosh;
Java_java_lang_StrictMath_sinh;
--- a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java Tue Oct 20 08:24:37 2015 -0700
@@ -50,19 +50,21 @@
public static void main(String[] args) throws Exception {
- if (args.length < 3) {
+ if (args.length < 4) {
System.err.println("Usage: java MakeJavaSecurity " +
"[input java.security file name] " +
"[output java.security file name] " +
"[openjdk target os] " +
+ "[openjdk target cpu architecture]" +
"[more restricted packages file name?]");
- System.exit(1);
+
+ System.exit(1);
}
// more restricted packages
List<String> extraLines;
- if (args.length == 4) {
- extraLines = Files.readAllLines(Paths.get(args[3]));
+ if (args.length == 5) {
+ extraLines = Files.readAllLines(Paths.get(args[4]));
} else {
extraLines = Collections.emptyList();
}
@@ -96,7 +98,11 @@
mode = 0;
iter.remove();
} else if (line.startsWith("#ifdef ")) {
- mode = line.endsWith(args[2])?1:2;
+ if (line.indexOf('-') > 0) {
+ mode = line.endsWith(args[2]+"-"+args[3]) ? 1 : 2;
+ } else {
+ mode = line.endsWith(args[2]) ? 1 : 2;
+ }
iter.remove();
} else if (line.startsWith("#ifndef ")) {
mode = line.endsWith(args[2])?2:1;
--- a/jdk/src/java.base/share/classes/java/lang/Character.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Character.java Tue Oct 20 08:24:37 2015 -0700
@@ -42,7 +42,7 @@
* a character's category (lowercase letter, digit, etc.) and for converting
* characters from uppercase to lowercase and vice versa.
* <p>
- * Character information is based on the Unicode Standard, version 7.0.0.
+ * Character information is based on the Unicode Standard, version 8.0.0.
* <p>
* The methods and data of class {@code Character} are defined by
* the information in the <i>UnicodeData</i> file that is part of the
@@ -2850,6 +2850,93 @@
"SUPPLEMENTAL ARROWS-C",
"SUPPLEMENTALARROWS-C");
+ /**
+ * Constant for the "Cherokee Supplement" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock CHEROKEE_SUPPLEMENT =
+ new UnicodeBlock("CHEROKEE_SUPPLEMENT",
+ "CHEROKEE SUPPLEMENT",
+ "CHEROKEESUPPLEMENT");
+
+ /**
+ * Constant for the "Hatran" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock HATRAN =
+ new UnicodeBlock("HATRAN");
+
+ /**
+ * Constant for the "Old Hungarian" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock OLD_HUNGARIAN =
+ new UnicodeBlock("OLD_HUNGARIAN",
+ "OLD HUNGARIAN",
+ "OLDHUNGARIAN");
+
+ /**
+ * Constant for the "Multani" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock MULTANI =
+ new UnicodeBlock("MULTANI");
+
+ /**
+ * Constant for the "Ahom" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock AHOM =
+ new UnicodeBlock("AHOM");
+
+ /**
+ * Constant for the "Early Dynastic Cuneiform" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock EARLY_DYNASTIC_CUNEIFORM =
+ new UnicodeBlock("EARLY_DYNASTIC_CUNEIFORM",
+ "EARLY DYNASTIC CUNEIFORM",
+ "EARLYDYNASTICCUNEIFORM");
+
+ /**
+ * Constant for the "Anatolian Hieroglyphs" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock ANATOLIAN_HIEROGLYPHS =
+ new UnicodeBlock("ANATOLIAN_HIEROGLYPHS",
+ "ANATOLIAN HIEROGLYPHS",
+ "ANATOLIANHIEROGLYPHS");
+
+ /**
+ * Constant for the "Sutton SignWriting" Unicode character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock SUTTON_SIGNWRITING =
+ new UnicodeBlock("SUTTON_SIGNWRITING",
+ "SUTTON SIGNWRITING",
+ "SUTTONSIGNWRITING");
+
+ /**
+ * Constant for the "Supplemental Symbols and Pictographs" Unicode
+ * character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS =
+ new UnicodeBlock("SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS",
+ "SUPPLEMENTAL SYMBOLS AND PICTOGRAPHS",
+ "SUPPLEMENTALSYMBOLSANDPICTOGRAPHS");
+
+ /**
+ * Constant for the "CJK Unified Ideographs Extension E" Unicode
+ * character block.
+ * @since 1.9
+ */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E =
+ new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E",
+ "CJK UNIFIED IDEOGRAPHS EXTENSION E",
+ "CJKUNIFIEDIDEOGRAPHSEXTENSIONE");
+
+
private static final int blockStarts[] = {
0x0000, // 0000..007F; Basic Latin
0x0080, // 0080..00FF; Latin-1 Supplement
@@ -2995,7 +3082,7 @@
0xAAE0, // AAE0..AAFF; Meetei Mayek Extensions
0xAB00, // AB00..AB2F; Ethiopic Extended-A
0xAB30, // AB30..AB6F; Latin Extended-E
- 0xAB70, // unassigned
+ 0xAB70, // AB70..ABBF; Cherokee Supplement
0xABC0, // ABC0..ABFF; Meetei Mayek
0xAC00, // AC00..D7AF; Hangul Syllables
0xD7B0, // D7B0..D7FF; Hangul Jamo Extended-B
@@ -3044,6 +3131,7 @@
0x10860, // 10860..1087F; Palmyrene
0x10880, // 10880..108AF; Nabataean
0x108B0, // unassigned
+ 0x108E0, // 108E0..108FF; Hatran
0x10900, // 10900..1091F; Phoenician
0x10920, // 10920..1093F; Lydian
0x10940, // unassigned
@@ -3061,6 +3149,8 @@
0x10BB0, // unassigned
0x10C00, // 10C00..10C4F; Old Turkic
0x10C50, // unassigned
+ 0x10C80, // 10C80..10CFF; Old Hungarian
+ 0x10D00, // unassigned
0x10E60, // 10E60..10E7F; Rumi Numeral Symbols
0x10E80, // unassigned
0x11000, // 11000..1107F; Brahmi
@@ -3072,6 +3162,7 @@
0x111E0, // 111E0..111FF; Sinhala Archaic Numbers
0x11200, // 11200..1124F; Khojki
0x11250, // unassigned
+ 0x11280, // 11280..112AF; Multani
0x112B0, // 112B0..112FF; Khudawadi
0x11300, // 11300..1137F; Grantha
0x11380, // unassigned
@@ -3082,15 +3173,20 @@
0x11660, // unassigned
0x11680, // 11680..116CF; Takri
0x116D0, // unassigned
+ 0x11700, // 11700..1173F; Ahom
+ 0x11740, // unassigned
0x118A0, // 118A0..118FF; Warang Citi
0x11900, // unassigned
0x11AC0, // 11AC0..11AFF; Pau Cin Hau
0x11B00, // unassigned
0x12000, // 12000..123FF; Cuneiform
0x12400, // 12400..1247F; Cuneiform Numbers and Punctuation
- 0x12480, // unassigned
+ 0x12480, // 12480..1254F; Early Dynastic Cuneiform
+ 0x12550, // unassigned
0x13000, // 13000..1342F; Egyptian Hieroglyphs
0x13430, // unassigned
+ 0x14400, // 14400..1467F; Anatolian Hieroglyphs
+ 0x14680, // unassigned
0x16800, // 16800..16A3F; Bamum Supplement
0x16A40, // 16A40..16A6F; Mro
0x16A70, // unassigned
@@ -3112,7 +3208,8 @@
0x1D360, // 1D360..1D37F; Counting Rod Numerals
0x1D380, // unassigned
0x1D400, // 1D400..1D7FF; Mathematical Alphanumeric Symbols
- 0x1D800, // unassigned
+ 0x1D800, // 1D800..1DAAF; Sutton SignWriting
+ 0x1DAB0, // unassigned
0x1E800, // 1E800..1E8DF; Mende Kikakui
0x1E8E0, // unassigned
0x1EE00, // 1EE00..1EEFF; Arabic Mathematical Alphabetic Symbols
@@ -3122,19 +3219,21 @@
0x1F0A0, // 1F0A0..1F0FF; Playing Cards
0x1F100, // 1F100..1F1FF; Enclosed Alphanumeric Supplement
0x1F200, // 1F200..1F2FF; Enclosed Ideographic Supplement
- 0x1F300, // 1F300..1F5FF; Miscellaneous Symbols And Pictographs
+ 0x1F300, // 1F300..1F5FF; Miscellaneous Symbols and Pictographs
0x1F600, // 1F600..1F64F; Emoticons
0x1F650, // 1F650..1F67F; Ornamental Dingbats
- 0x1F680, // 1F680..1F6FF; Transport And Map Symbols
+ 0x1F680, // 1F680..1F6FF; Transport and Map Symbols
0x1F700, // 1F700..1F77F; Alchemical Symbols
0x1F780, // 1F780..1F7FF; Geometric Shapes Extended
0x1F800, // 1F800..1F8FF; Supplemental Arrows-C
- 0x1F900, // unassigned
+ 0x1F900, // 1F900..1F9FF; Supplemental Symbols and Pictographs
+ 0x1FA00, // unassigned
0x20000, // 20000..2A6DF; CJK Unified Ideographs Extension B
0x2A6E0, // unassigned
0x2A700, // 2A700..2B73F; CJK Unified Ideographs Extension C
0x2B740, // 2B740..2B81F; CJK Unified Ideographs Extension D
- 0x2B820, // unassigned
+ 0x2B820, // 2B820..2CEAF; CJK Unified Ideographs Extension E
+ 0x2CEB0, // unassigned
0x2F800, // 2F800..2FA1F; CJK Compatibility Ideographs Supplement
0x2FA20, // unassigned
0xE0000, // E0000..E007F; Tags
@@ -3290,7 +3389,7 @@
MEETEI_MAYEK_EXTENSIONS,
ETHIOPIC_EXTENDED_A,
LATIN_EXTENDED_E,
- null,
+ CHEROKEE_SUPPLEMENT,
MEETEI_MAYEK,
HANGUL_SYLLABLES,
HANGUL_JAMO_EXTENDED_B,
@@ -3339,6 +3438,7 @@
PALMYRENE,
NABATAEAN,
null,
+ HATRAN,
PHOENICIAN,
LYDIAN,
null,
@@ -3356,6 +3456,8 @@
null,
OLD_TURKIC,
null,
+ OLD_HUNGARIAN,
+ null,
RUMI_NUMERAL_SYMBOLS,
null,
BRAHMI,
@@ -3367,6 +3469,7 @@
SINHALA_ARCHAIC_NUMBERS,
KHOJKI,
null,
+ MULTANI,
KHUDAWADI,
GRANTHA,
null,
@@ -3377,15 +3480,20 @@
null,
TAKRI,
null,
+ AHOM,
+ null,
WARANG_CITI,
null,
PAU_CIN_HAU,
null,
CUNEIFORM,
CUNEIFORM_NUMBERS_AND_PUNCTUATION,
+ EARLY_DYNASTIC_CUNEIFORM,
null,
EGYPTIAN_HIEROGLYPHS,
null,
+ ANATOLIAN_HIEROGLYPHS,
+ null,
BAMUM_SUPPLEMENT,
MRO,
null,
@@ -3407,6 +3515,7 @@
COUNTING_ROD_NUMERALS,
null,
MATHEMATICAL_ALPHANUMERIC_SYMBOLS,
+ SUTTON_SIGNWRITING,
null,
MENDE_KIKAKUI,
null,
@@ -3424,11 +3533,13 @@
ALCHEMICAL_SYMBOLS,
GEOMETRIC_SHAPES_EXTENDED,
SUPPLEMENTAL_ARROWS_C,
+ SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS,
null,
CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B,
null,
CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C,
CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D,
+ CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E,
null,
CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT,
null,
@@ -4214,6 +4325,42 @@
*/
WARANG_CITI,
+ /**
+ * Unicode script "Ahom".
+ * @since 1.9
+ */
+ AHOM,
+
+ /**
+ * Unicode script "Anatolian Hieroglyphs".
+ * @since 1.9
+ */
+ ANATOLIAN_HIEROGLYPHS,
+
+ /**
+ * Unicode script "Hatran".
+ * @since 1.9
+ */
+ HATRAN,
+
+ /**
+ * Unicode script "Multani".
+ * @since 1.9
+ */
+ MULTANI,
+
+ /**
+ * Unicode script "Old Hungarian".
+ * @since 1.9
+ */
+ OLD_HUNGARIAN,
+
+ /**
+ * Unicode script "SignWriting".
+ * @since 1.9
+ */
+ SIGNWRITING,
+
/**
* Unicode script "Unknown".
*/
@@ -4295,9 +4442,7 @@
0x0640, // 0640 ; COMMON
0x0641, // 0641..064A; ARABIC
0x064B, // 064B..0655; INHERITED
- 0x0656, // 0656..065F; ARABIC
- 0x0660, // 0660..0669; COMMON
- 0x066A, // 066A..066F; ARABIC
+ 0x0656, // 0656..066F; ARABIC
0x0670, // 0670 ; INHERITED
0x0671, // 0671..06DC; ARABIC
0x06DD, // 06DD ; COMMON
@@ -4320,9 +4465,9 @@
0x085C, // 085C..085D; UNKNOWN
0x085E, // 085E ; MANDAIC
0x085F, // 085F..089F; UNKNOWN
- 0x08A0, // 08A0..08B2; ARABIC
- 0x08B3, // 08B3..08E3; UNKNOWN
- 0x08E4, // 08E4..08FF; ARABIC
+ 0x08A0, // 08A0..08B4; ARABIC
+ 0x08B5, // 08B5..08E2; UNKNOWN
+ 0x08E3, // 08E3..08FF; ARABIC
0x0900, // 0900..0950; DEVANAGARI
0x0951, // 0951..0952; INHERITED
0x0953, // 0953..0963; DEVANAGARI
@@ -4413,7 +4558,9 @@
0x0AE0, // 0AE0..0AE3; GUJARATI
0x0AE4, // 0AE4..0AE5; UNKNOWN
0x0AE6, // 0AE6..0AF1; GUJARATI
- 0x0AF2, // 0AF2..0B00; UNKNOWN
+ 0x0AF2, // 0AF2..0AF8; UNKNOWN
+ 0x0AF9, // 0AF9 ; GUJARATI
+ 0x0AFA, // 0AFA..0B00; UNKNOWN
0x0B01, // 0B01..0B03; ORIYA
0x0B04, // 0B04 ; UNKNOWN
0x0B05, // 0B05..0B0C; ORIYA
@@ -4492,8 +4639,8 @@
0x0C4E, // 0C4E..0C54; UNKNOWN
0x0C55, // 0C55..0C56; TELUGU
0x0C57, // 0C57 ; UNKNOWN
- 0x0C58, // 0C58..0C59; TELUGU
- 0x0C5A, // 0C5A..0C5F; UNKNOWN
+ 0x0C58, // 0C58..0C5A; TELUGU
+ 0x0C5B, // 0C5B..0C5F; UNKNOWN
0x0C60, // 0C60..0C63; TELUGU
0x0C64, // 0C64..0C65; UNKNOWN
0x0C66, // 0C66..0C6F; TELUGU
@@ -4543,8 +4690,8 @@
0x0D4A, // 0D4A..0D4E; MALAYALAM
0x0D4F, // 0D4F..0D56; UNKNOWN
0x0D57, // 0D57 ; MALAYALAM
- 0x0D58, // 0D58..0D5F; UNKNOWN
- 0x0D60, // 0D60..0D63; MALAYALAM
+ 0x0D58, // 0D58..0D5E; UNKNOWN
+ 0x0D5F, // 0D5F..0D63; MALAYALAM
0x0D64, // 0D64..0D65; UNKNOWN
0x0D66, // 0D66..0D75; MALAYALAM
0x0D76, // 0D76..0D78; UNKNOWN
@@ -4676,8 +4823,10 @@
0x137D, // 137D..137F; UNKNOWN
0x1380, // 1380..1399; ETHIOPIC
0x139A, // 139A..139F; UNKNOWN
- 0x13A0, // 13A0..13F4; CHEROKEE
- 0x13F5, // 13F5..13FF; UNKNOWN
+ 0x13A0, // 13A0..13F5; CHEROKEE
+ 0x13F6, // 13F6..13F7; UNKNOWN
+ 0x13F8, // 13F8..13FD; CHEROKEE
+ 0x13FE, // 13FE..13FF; UNKNOWN
0x1400, // 1400..167F; CANADIAN_ABORIGINAL
0x1680, // 1680..169C; OGHAM
0x169D, // 169D..169F; UNKNOWN
@@ -4846,8 +4995,8 @@
0x208F, // 208F ; UNKNOWN
0x2090, // 2090..209C; LATIN
0x209D, // 209D..209F; UNKNOWN
- 0x20A0, // 20A0..20BD; COMMON
- 0x20BE, // 20BE..20CF; UNKNOWN
+ 0x20A0, // 20A0..20BE; COMMON
+ 0x20BF, // 20BF..20CF; UNKNOWN
0x20D0, // 20D0..20F0; INHERITED
0x20F1, // 20F1..20FF; UNKNOWN
0x2100, // 2100..2125; COMMON
@@ -4860,8 +5009,8 @@
0x214E, // 214E ; LATIN
0x214F, // 214F..215F; COMMON
0x2160, // 2160..2188; LATIN
- 0x2189, // 2189 ; COMMON
- 0x218A, // 218A..218F; UNKNOWN
+ 0x2189, // 2189..218B; COMMON
+ 0x218C, // 218C..218F; UNKNOWN
0x2190, // 2190..23FA; COMMON
0x23FB, // 23FB..23FF; UNKNOWN
0x2400, // 2400..2426; COMMON
@@ -4879,7 +5028,9 @@
0x2BBD, // 2BBD..2BC8; COMMON
0x2BC9, // 2BC9 ; UNKNOWN
0x2BCA, // 2BCA..2BD1; COMMON
- 0x2BD2, // 2BD2..2BFF; UNKNOWN
+ 0x2BD2, // 2BD2..2BEB; UNKNOWN
+ 0x2BEC, // 2BEC..2BEF; COMMON
+ 0x2BF0, // 2BF0..2BFF; UNKNOWN
0x2C00, // 2C00..2C2E; GLAGOLITIC
0x2C2F, // 2C2F ; UNKNOWN
0x2C30, // 2C30..2C5E; GLAGOLITIC
@@ -4972,8 +5123,8 @@
0x3400, // 3400..4DB5; HAN
0x4DB6, // 4DB6..4DBF; UNKNOWN
0x4DC0, // 4DC0..4DFF; COMMON
- 0x4E00, // 4E00..9FCC; HAN
- 0x9FCD, // 9FCD..9FFF; UNKNOWN
+ 0x4E00, // 4E00..9FD5; HAN
+ 0x9FD6, // 9FD6..9FFF; UNKNOWN
0xA000, // A000..A48C; YI
0xA48D, // A48D..A48F; UNKNOWN
0xA490, // A490..A4C6; YI
@@ -4981,20 +5132,16 @@
0xA4D0, // A4D0..A4FF; LISU
0xA500, // A500..A62B; VAI
0xA62C, // A62C..A63F; UNKNOWN
- 0xA640, // A640..A69D; CYRILLIC
- 0xA69E, // A69E ; UNKNOWN
- 0xA69F, // A69F ; CYRILLIC
+ 0xA640, // A640..A69F; CYRILLIC
0xA6A0, // A6A0..A6F7; BAMUM
0xA6F8, // A6F8..A6FF; UNKNOWN
0xA700, // A700..A721; COMMON
0xA722, // A722..A787; LATIN
0xA788, // A788..A78A; COMMON
- 0xA78B, // A78B..A78E; LATIN
- 0xA78F, // A78F ; UNKNOWN
- 0xA790, // A790..A7AD; LATIN
+ 0xA78B, // A78B..A7AD; LATIN
0xA7AE, // A7AE..A7AF; UNKNOWN
- 0xA7B0, // A7B0..A7B1; LATIN
- 0xA7B2, // A7B2..A7F6; UNKNOWN
+ 0xA7B0, // A7B0..A7B7; LATIN
+ 0xA7B8, // A7B8..A7F6; UNKNOWN
0xA7F7, // A7F7..A7FF; LATIN
0xA800, // A800..A82B; SYLOTI_NAGRI
0xA82C, // A82C..A82F; UNKNOWN
@@ -5006,8 +5153,8 @@
0xA8C5, // A8C5..A8CD; UNKNOWN
0xA8CE, // A8CE..A8D9; SAURASHTRA
0xA8DA, // A8DA..A8DF; UNKNOWN
- 0xA8E0, // A8E0..A8FB; DEVANAGARI
- 0xA8FC, // A8FC..A8FF; UNKNOWN
+ 0xA8E0, // A8E0..A8FD; DEVANAGARI
+ 0xA8FE, // A8FE..A8FF; UNKNOWN
0xA900, // A900..A92D; KAYAH_LI
0xA92E, // A92E ; COMMON
0xA92F, // A92F ; KAYAH_LI
@@ -5049,11 +5196,10 @@
0xAB2F, // AB2F ; UNKNOWN
0xAB30, // AB30..AB5A; LATIN
0xAB5B, // AB5B ; COMMON
- 0xAB5C, // AB5C..AB5F; LATIN
- 0xAB60, // AB60..AB63; UNKNOWN
- 0xAB64, // AB64 ; LATIN
+ 0xAB5C, // AB5C..AB64; LATIN
0xAB65, // AB65 ; GREEK
- 0xAB66, // AB66..ABBF; UNKNOWN
+ 0xAB66, // AB66..AB6F; UNKNOWN
+ 0xAB70, // AB70..ABBF; CHEROKEE
0xABC0, // ABC0..ABED; MEETEI_MAYEK
0xABEE, // ABEE..ABEF; UNKNOWN
0xABF0, // ABF0..ABF9; MEETEI_MAYEK
@@ -5098,7 +5244,7 @@
0xFE10, // FE10..FE19; COMMON
0xFE1A, // FE1A..FE1F; UNKNOWN
0xFE20, // FE20..FE2D; INHERITED
- 0xFE2E, // FE2E..FE2F; UNKNOWN
+ 0xFE2E, // FE2E..FE2F; CYRILLIC
0xFE30, // FE30..FE52; COMMON
0xFE53, // FE53 ; UNKNOWN
0xFE54, // FE54..FE66; COMMON
@@ -5220,7 +5366,12 @@
0x10880, // 10880..1089E; NABATAEAN
0x1089F, // 1089F..108A6; UNKNOWN
0x108A7, // 108A7..108AF; NABATAEAN
- 0x108B0, // 108B0..108FF; UNKNOWN
+ 0x108B0, // 108B0..108DF; UNKNOWN
+ 0x108E0, // 108E0..108F2; HATRAN
+ 0x108F3, // 108F3 ; UNKNOWN
+ 0x108F4, // 108F4..108F5; HATRAN
+ 0x108F6, // 108F6..108FA; UNKNOWN
+ 0x108FB, // 108FB..108FF; HATRAN
0x10900, // 10900..1091B; PHOENICIAN
0x1091C, // 1091C..1091E; UNKNOWN
0x1091F, // 1091F ; PHOENICIAN
@@ -5230,9 +5381,10 @@
0x10940, // 10940..1097F; UNKNOWN
0x10980, // 10980..1099F; MEROITIC_HIEROGLYPHS
0x109A0, // 109A0..109B7; MEROITIC_CURSIVE
- 0x109B8, // 109B8..109BD; UNKNOWN
- 0x109BE, // 109BE..109BF; MEROITIC_CURSIVE
- 0x109C0, // 109C0..109FF; UNKNOWN
+ 0x109B8, // 109B8..109BB; UNKNOWN
+ 0x109BC, // 109BC..109CF; MEROITIC_CURSIVE
+ 0x109D0, // 109D0..109D1; UNKNOWN
+ 0x109D2, // 109D2..109FF; MEROITIC_CURSIVE
0x10A00, // 10A00..10A03; KHAROSHTHI
0x10A04, // 10A04 ; UNKNOWN
0x10A05, // 10A05..10A06; KHAROSHTHI
@@ -5272,7 +5424,13 @@
0x10BA9, // 10BA9..10BAF; PSALTER_PAHLAVI
0x10BB0, // 10BB0..10BFF; UNKNOWN
0x10C00, // 10C00..10C48; OLD_TURKIC
- 0x10C49, // 10C49..10E5F; UNKNOWN
+ 0x10C49, // 10C49..10C7F; UNKNOWN
+ 0x10C80, // 10C80..10CB2; OLD_HUNGARIAN
+ 0x10CB3, // 10CB3..10CBF; UNKNOWN
+ 0x10CC0, // 10CC0..10CF2; OLD_HUNGARIAN
+ 0x10CF3, // 10CF3..10CF9; UNKNOWN
+ 0x10CFA, // 10CFA..10CFF; OLD_HUNGARIAN
+ 0x10D00, // 10D00..10E5F; UNKNOWN
0x10E60, // 10E60..10E7E; ARABIC
0x10E7F, // 10E7F..10FFF; UNKNOWN
0x11000, // 11000..1104D; BRAHMI
@@ -5292,23 +5450,31 @@
0x11144, // 11144..1114F; UNKNOWN
0x11150, // 11150..11176; MAHAJANI
0x11177, // 11177..1117F; UNKNOWN
- 0x11180, // 11180..111C8; SHARADA
- 0x111C9, // 111C9..111CC; UNKNOWN
- 0x111CD, // 111CD ; SHARADA
+ 0x11180, // 11180..111CD; SHARADA
0x111CE, // 111CE..111CF; UNKNOWN
- 0x111D0, // 111D0..111DA; SHARADA
- 0x111DB, // 111DB..111E0; UNKNOWN
+ 0x111D0, // 111D0..111DF; SHARADA
+ 0x111E0, // 111E0 ; UNKNOWN
0x111E1, // 111E1..111F4; SINHALA
0x111F5, // 111F5..111FF; UNKNOWN
0x11200, // 11200..11211; KHOJKI
0x11212, // 11212 ; UNKNOWN
0x11213, // 11213..1123D; KHOJKI
- 0x1123E, // 1123E..112AF; UNKNOWN
+ 0x1123E, // 1123E..1127F; UNKNOWN
+ 0x11280, // 11280..11286; MULTANI
+ 0x11287, // 11287 ; UNKNOWN
+ 0x11288, // 11288 ; MULTANI
+ 0x11289, // 11289 ; UNKNOWN
+ 0x1128A, // 1128A..1128D; MULTANI
+ 0x1128E, // 1128E ; UNKNOWN
+ 0x1128F, // 1128F..1129D; MULTANI
+ 0x1129E, // 1129E ; UNKNOWN
+ 0x1129F, // 1129F..112A9; MULTANI
+ 0x112AA, // 112AA..112AF; UNKNOWN
0x112B0, // 112B0..112EA; KHUDAWADI
0x112EB, // 112EB..112EF; UNKNOWN
0x112F0, // 112F0..112F9; KHUDAWADI
- 0x112FA, // 112FA..11300; UNKNOWN
- 0x11301, // 11301..11303; GRANTHA
+ 0x112FA, // 112FA..112FF; UNKNOWN
+ 0x11300, // 11300..11303; GRANTHA
0x11304, // 11304 ; UNKNOWN
0x11305, // 11305..1130C; GRANTHA
0x1130D, // 1130D..1130E; UNKNOWN
@@ -5327,7 +5493,9 @@
0x11347, // 11347..11348; GRANTHA
0x11349, // 11349..1134A; UNKNOWN
0x1134B, // 1134B..1134D; GRANTHA
- 0x1134E, // 1134E..11356; UNKNOWN
+ 0x1134E, // 1134E..1134F; UNKNOWN
+ 0x11350, // 11350 ; GRANTHA
+ 0x11351, // 11351..11356; UNKNOWN
0x11357, // 11357 ; GRANTHA
0x11358, // 11358..1135C; UNKNOWN
0x1135D, // 1135D..11363; GRANTHA
@@ -5342,8 +5510,8 @@
0x114DA, // 114DA..1157F; UNKNOWN
0x11580, // 11580..115B5; SIDDHAM
0x115B6, // 115B6..115B7; UNKNOWN
- 0x115B8, // 115B8..115C9; SIDDHAM
- 0x115CA, // 115CA..115FF; UNKNOWN
+ 0x115B8, // 115B8..115DD; SIDDHAM
+ 0x115DE, // 115DE..115FF; UNKNOWN
0x11600, // 11600..11644; MODI
0x11645, // 11645..1164F; UNKNOWN
0x11650, // 11650..11659; MODI
@@ -5351,21 +5519,31 @@
0x11680, // 11680..116B7; TAKRI
0x116B8, // 116B8..116BF; UNKNOWN
0x116C0, // 116C0..116C9; TAKRI
- 0x116CA, // 116CA..1189F; UNKNOWN
+ 0x116CA, // 116CA..116FF; UNKNOWN
+ 0x11700, // 11700..11719; AHOM
+ 0x1171A, // 1171A..1171C; UNKNOWN
+ 0x1171D, // 1171D..1172B; AHOM
+ 0x1172C, // 1172C..1172F; UNKNOWN
+ 0x11730, // 11730..1173F; AHOM
+ 0x11740, // 11740..1189F; UNKNOWN
0x118A0, // 118A0..118F2; WARANG_CITI
0x118F3, // 118F3..118FE; UNKNOWN
0x118FF, // 118FF ; WARANG_CITI
0x11900, // 11900..11ABF; UNKNOWN
0x11AC0, // 11AC0..11AF8; PAU_CIN_HAU
0x11AF9, // 11AF9..11FFF; UNKNOWN
- 0x12000, // 12000..12398; CUNEIFORM
- 0x12399, // 12399..123FF; UNKNOWN
+ 0x12000, // 12000..12399; CUNEIFORM
+ 0x1239A, // 1239A..123FF; UNKNOWN
0x12400, // 12400..1246E; CUNEIFORM
0x1246F, // 1246F ; UNKNOWN
0x12470, // 12470..12474; CUNEIFORM
- 0x12475, // 12475..12FFF; UNKNOWN
+ 0x12475, // 12475..1247F; UNKNOWN
+ 0x12480, // 12480..12543; CUNEIFORM
+ 0x12544, // 12544..12FFF; UNKNOWN
0x13000, // 13000..1342E; EGYPTIAN_HIEROGLYPHS
- 0x1342F, // 1342F..167FF; UNKNOWN
+ 0x1342F, // 1342F..143FF; UNKNOWN
+ 0x14400, // 14400..14646; ANATOLIAN_HIEROGLYPHS
+ 0x14647, // 14647..167FF; UNKNOWN
0x16800, // 16800..16A38; BAMUM
0x16A39, // 16A39..16A3F; UNKNOWN
0x16A40, // 16A40..16A5E; MRO
@@ -5420,8 +5598,8 @@
0x1D185, // 1D185..1D18B; INHERITED
0x1D18C, // 1D18C..1D1A9; COMMON
0x1D1AA, // 1D1AA..1D1AD; INHERITED
- 0x1D1AE, // 1D1AE..1D1DD; COMMON
- 0x1D1DE, // 1D1DE..1D1FF; UNKNOWN
+ 0x1D1AE, // 1D1AE..1D1E8; COMMON
+ 0x1D1E9, // 1D1E9..1D1FF; UNKNOWN
0x1D200, // 1D200..1D245; GREEK
0x1D246, // 1D246..1D2FF; UNKNOWN
0x1D300, // 1D300..1D356; COMMON
@@ -5469,7 +5647,12 @@
0x1D6A8, // 1D6A8..1D7CB; COMMON
0x1D7CC, // 1D7CC..1D7CD; UNKNOWN
0x1D7CE, // 1D7CE..1D7FF; COMMON
- 0x1D800, // 1D800..1E7FF; UNKNOWN
+ 0x1D800, // 1D800..1DA8B; SIGNWRITING
+ 0x1DA8C, // 1DA8C..1DA9A; UNKNOWN
+ 0x1DA9B, // 1DA9B..1DA9F; SIGNWRITING
+ 0x1DAA0, // 1DAA0 ; UNKNOWN
+ 0x1DAA1, // 1DAA1..1DAAF; SIGNWRITING
+ 0x1DAB0, // 1DAB0..1E7FF; UNKNOWN
0x1E800, // 1E800..1E8C4; MENDE_KIKAKUI
0x1E8C5, // 1E8C5..1E8C6; UNKNOWN
0x1E8C7, // 1E8C7..1E8D6; MENDE_KIKAKUI
@@ -5572,26 +5755,12 @@
0x1F249, // 1F249..1F24F; UNKNOWN
0x1F250, // 1F250..1F251; COMMON
0x1F252, // 1F252..1F2FF; UNKNOWN
- 0x1F300, // 1F300..1F32C; COMMON
- 0x1F32D, // 1F32D..1F32F; UNKNOWN
- 0x1F330, // 1F330..1F37D; COMMON
- 0x1F37E, // 1F37E..1F37F; UNKNOWN
- 0x1F380, // 1F380..1F3CE; COMMON
- 0x1F3CF, // 1F3CF..1F3D3; UNKNOWN
- 0x1F3D4, // 1F3D4..1F3F7; COMMON
- 0x1F3F8, // 1F3F8..1F3FF; UNKNOWN
- 0x1F400, // 1F400..1F4FE; COMMON
- 0x1F4FF, // 1F4FF ; UNKNOWN
- 0x1F500, // 1F500..1F54A; COMMON
- 0x1F54B, // 1F54B..1F54F; UNKNOWN
- 0x1F550, // 1F550..1F579; COMMON
+ 0x1F300, // 1F300..1F579; COMMON
0x1F57A, // 1F57A ; UNKNOWN
0x1F57B, // 1F57B..1F5A3; COMMON
0x1F5A4, // 1F5A4 ; UNKNOWN
- 0x1F5A5, // 1F5A5..1F642; COMMON
- 0x1F643, // 1F643..1F644; UNKNOWN
- 0x1F645, // 1F645..1F6CF; COMMON
- 0x1F6D0, // 1F6D0..1F6DF; UNKNOWN
+ 0x1F5A5, // 1F5A5..1F6D0; COMMON
+ 0x1F6D1, // 1F6D1..1F6DF; UNKNOWN
0x1F6E0, // 1F6E0..1F6EC; COMMON
0x1F6ED, // 1F6ED..1F6EF; UNKNOWN
0x1F6F0, // 1F6F0..1F6F3; COMMON
@@ -5609,13 +5778,21 @@
0x1F860, // 1F860..1F887; COMMON
0x1F888, // 1F888..1F88F; UNKNOWN
0x1F890, // 1F890..1F8AD; COMMON
- 0x1F8AE, // 1F8AE..1FFFF; UNKNOWN
+ 0x1F8AE, // 1F8AE..1F90F; UNKNOWN
+ 0x1F910, // 1F910..1F918; COMMON
+ 0x1F919, // 1F919..1F97F; UNKNOWN
+ 0x1F980, // 1F980..1F984; COMMON
+ 0x1F985, // 1F985..1F9BF; UNKNOWN
+ 0x1F9C0, // 1F9C0 ; COMMON
+ 0x1F9C1, // 1F9C1..1FFFF; UNKNOWN
0x20000, // 20000..2A6D6; HAN
0x2A6D7, // 2A6D7..2A6FF; UNKNOWN
0x2A700, // 2A700..2B734; HAN
0x2B735, // 2B735..2B73F; UNKNOWN
0x2B740, // 2B740..2B81D; HAN
- 0x2B81E, // 2B81E..2F7FF; UNKNOWN
+ 0x2B81E, // 2B81E..2B81F; UNKNOWN
+ 0x2B820, // 2B820..2CEA1; HAN
+ 0x2CEA2, // 2CEA2..2F7FF; UNKNOWN
0x2F800, // 2F800..2FA1D; HAN
0x2FA1E, // 2FA1E..E0000; UNKNOWN
0xE0001, // E0001 ; COMMON
@@ -5702,9 +5879,7 @@
COMMON, // 0640
ARABIC, // 0641..064A
INHERITED, // 064B..0655
- ARABIC, // 0656..065F
- COMMON, // 0660..0669
- ARABIC, // 066A..066F
+ ARABIC, // 0656..066F
INHERITED, // 0670
ARABIC, // 0671..06DC
COMMON, // 06DD
@@ -5727,9 +5902,9 @@
UNKNOWN, // 085C..085D
MANDAIC, // 085E
UNKNOWN, // 085F..089F
- ARABIC, // 08A0..08B2
- UNKNOWN, // 08B3..08E3
- ARABIC, // 08E4..08FF
+ ARABIC, // 08A0..08B4
+ UNKNOWN, // 08B5..08E2
+ ARABIC, // 08E3..08FF
DEVANAGARI, // 0900..0950
INHERITED, // 0951..0952
DEVANAGARI, // 0953..0963
@@ -5820,7 +5995,9 @@
GUJARATI, // 0AE0..0AE3
UNKNOWN, // 0AE4..0AE5
GUJARATI, // 0AE6..0AF1
- UNKNOWN, // 0AF2..0B00
+ UNKNOWN, // 0AF2..0AF8
+ GUJARATI, // 0AF9
+ UNKNOWN, // 0AFA..0B00
ORIYA, // 0B01..0B03
UNKNOWN, // 0B04
ORIYA, // 0B05..0B0C
@@ -5899,8 +6076,8 @@
UNKNOWN, // 0C4E..0C54
TELUGU, // 0C55..0C56
UNKNOWN, // 0C57
- TELUGU, // 0C58..0C59
- UNKNOWN, // 0C5A..0C5F
+ TELUGU, // 0C58..0C5A
+ UNKNOWN, // 0C5B..0C5F
TELUGU, // 0C60..0C63
UNKNOWN, // 0C64..0C65
TELUGU, // 0C66..0C6F
@@ -5950,8 +6127,8 @@
MALAYALAM, // 0D4A..0D4E
UNKNOWN, // 0D4F..0D56
MALAYALAM, // 0D57
- UNKNOWN, // 0D58..0D5F
- MALAYALAM, // 0D60..0D63
+ UNKNOWN, // 0D58..0D5E
+ MALAYALAM, // 0D5F..0D63
UNKNOWN, // 0D64..0D65
MALAYALAM, // 0D66..0D75
UNKNOWN, // 0D76..0D78
@@ -6083,8 +6260,10 @@
UNKNOWN, // 137D..137F
ETHIOPIC, // 1380..1399
UNKNOWN, // 139A..139F
- CHEROKEE, // 13A0..13F4
- UNKNOWN, // 13F5..13FF
+ CHEROKEE, // 13A0..13F5
+ UNKNOWN, // 13F6..13F7
+ CHEROKEE, // 13F8..13FD
+ UNKNOWN, // 13FE..13FF
CANADIAN_ABORIGINAL, // 1400..167F
OGHAM, // 1680..169C
UNKNOWN, // 169D..169F
@@ -6253,8 +6432,8 @@
UNKNOWN, // 208F
LATIN, // 2090..209C
UNKNOWN, // 209D..209F
- COMMON, // 20A0..20BD
- UNKNOWN, // 20BE..20CF
+ COMMON, // 20A0..20BE
+ UNKNOWN, // 20BF..20CF
INHERITED, // 20D0..20F0
UNKNOWN, // 20F1..20FF
COMMON, // 2100..2125
@@ -6267,8 +6446,8 @@
LATIN, // 214E
COMMON, // 214F..215F
LATIN, // 2160..2188
- COMMON, // 2189
- UNKNOWN, // 218A..218F
+ COMMON, // 2189..218B
+ UNKNOWN, // 218C..218F
COMMON, // 2190..23FA
UNKNOWN, // 23FB..23FF
COMMON, // 2400..2426
@@ -6286,7 +6465,9 @@
COMMON, // 2BBD..2BC8
UNKNOWN, // 2BC9
COMMON, // 2BCA..2BD1
- UNKNOWN, // 2BD2..2BFF
+ UNKNOWN, // 2BD2..2BEB
+ COMMON, // 2BEC..2BEF
+ UNKNOWN, // 2BF0..2BFF
GLAGOLITIC, // 2C00..2C2E
UNKNOWN, // 2C2F
GLAGOLITIC, // 2C30..2C5E
@@ -6379,8 +6560,8 @@
HAN, // 3400..4DB5
UNKNOWN, // 4DB6..4DBF
COMMON, // 4DC0..4DFF
- HAN, // 4E00..9FCC
- UNKNOWN, // 9FCD..9FFF
+ HAN, // 4E00..9FD5
+ UNKNOWN, // 9FD6..9FFF
YI, // A000..A48C
UNKNOWN, // A48D..A48F
YI, // A490..A4C6
@@ -6388,20 +6569,16 @@
LISU, // A4D0..A4FF
VAI, // A500..A62B
UNKNOWN, // A62C..A63F
- CYRILLIC, // A640..A69D
- UNKNOWN, // A69E
- CYRILLIC, // A69F
+ CYRILLIC, // A640..A69F
BAMUM, // A6A0..A6F7
UNKNOWN, // A6F8..A6FF
COMMON, // A700..A721
LATIN, // A722..A787
COMMON, // A788..A78A
- LATIN, // A78B..A78E
- UNKNOWN, // A78F
- LATIN, // A790..A7AD
+ LATIN, // A78B..A7AD
UNKNOWN, // A7AE..A7AF
- LATIN, // A7B0..A7B1
- UNKNOWN, // A7B2..A7F6
+ LATIN, // A7B0..A7B7
+ UNKNOWN, // A7B8..A7F6
LATIN, // A7F7..A7FF
SYLOTI_NAGRI, // A800..A82B
UNKNOWN, // A82C..A82F
@@ -6413,8 +6590,8 @@
UNKNOWN, // A8C5..A8CD
SAURASHTRA, // A8CE..A8D9
UNKNOWN, // A8DA..A8DF
- DEVANAGARI, // A8E0..A8FB
- UNKNOWN, // A8FC..A8FF
+ DEVANAGARI, // A8E0..A8FD
+ UNKNOWN, // A8FE..A8FF
KAYAH_LI, // A900..A92D
COMMON, // A92E
KAYAH_LI, // A92F
@@ -6456,11 +6633,10 @@
UNKNOWN, // AB2F
LATIN, // AB30..AB5A
COMMON, // AB5B
- LATIN, // AB5C..AB5F
- UNKNOWN, // AB60..AB63
- LATIN, // AB64
+ LATIN, // AB5C..AB64
GREEK, // AB65
- UNKNOWN, // AB66..ABBF
+ UNKNOWN, // AB66..AB6F
+ CHEROKEE, // AB70..ABBF
MEETEI_MAYEK, // ABC0..ABED
UNKNOWN, // ABEE..ABEF
MEETEI_MAYEK, // ABF0..ABF9
@@ -6505,7 +6681,7 @@
COMMON, // FE10..FE19
UNKNOWN, // FE1A..FE1F
INHERITED, // FE20..FE2D
- UNKNOWN, // FE2E..FE2F
+ CYRILLIC, // FE2E..FE2F
COMMON, // FE30..FE52
UNKNOWN, // FE53
COMMON, // FE54..FE66
@@ -6627,7 +6803,12 @@
NABATAEAN, // 10880..1089E
UNKNOWN, // 1089F..108A6
NABATAEAN, // 108A7..108AF
- UNKNOWN, // 108B0..108FF
+ UNKNOWN, // 108B0..108DF
+ HATRAN, // 108E0..108F2
+ UNKNOWN, // 108F3
+ HATRAN, // 108F4..108F5
+ UNKNOWN, // 108F6..108FA
+ HATRAN, // 108FB..108FF
PHOENICIAN, // 10900..1091B
UNKNOWN, // 1091C..1091E
PHOENICIAN, // 1091F
@@ -6637,9 +6818,10 @@
UNKNOWN, // 10940..1097F
MEROITIC_HIEROGLYPHS, // 10980..1099F
MEROITIC_CURSIVE, // 109A0..109B7
- UNKNOWN, // 109B8..109BD
- MEROITIC_CURSIVE, // 109BE..109BF
- UNKNOWN, // 109C0..109FF
+ UNKNOWN, // 109B8..109BB
+ MEROITIC_CURSIVE, // 109BC..109CF
+ UNKNOWN, // 109D0..109D1
+ MEROITIC_CURSIVE, // 109D2..109FF
KHAROSHTHI, // 10A00..10A03
UNKNOWN, // 10A04
KHAROSHTHI, // 10A05..10A06
@@ -6679,7 +6861,13 @@
PSALTER_PAHLAVI, // 10BA9..10BAF
UNKNOWN, // 10BB0..10BFF
OLD_TURKIC, // 10C00..10C48
- UNKNOWN, // 10C49..10E5F
+ UNKNOWN, // 10C49..10C7F
+ OLD_HUNGARIAN, // 10C80..10CB2
+ UNKNOWN, // 10CB3..10CBF
+ OLD_HUNGARIAN, // 10CC0..10CF2
+ UNKNOWN, // 10CF3..10CF9
+ OLD_HUNGARIAN, // 10CFA..10CFF
+ UNKNOWN, // 10D00..10E5F
ARABIC, // 10E60..10E7E
UNKNOWN, // 10E7F..10FFF
BRAHMI, // 11000..1104D
@@ -6699,23 +6887,31 @@
UNKNOWN, // 11144..1114F
MAHAJANI, // 11150..11176
UNKNOWN, // 11177..1117F
- SHARADA, // 11180..111C8
- UNKNOWN, // 111C9..111CC
- SHARADA, // 111CD
+ SHARADA, // 11180..111CD
UNKNOWN, // 111CE..111CF
- SHARADA, // 111D0..111DA
- UNKNOWN, // 111DB..111E0
+ SHARADA, // 111D0..111DF
+ UNKNOWN, // 111E0
SINHALA, // 111E1..111F4
UNKNOWN, // 111F5..111FF
KHOJKI, // 11200..11211
UNKNOWN, // 11212
KHOJKI, // 11213..1123D
- UNKNOWN, // 1123E..112AF
+ UNKNOWN, // 1123E..1127F
+ MULTANI, // 11280..11286
+ UNKNOWN, // 11287
+ MULTANI, // 11288
+ UNKNOWN, // 11289
+ MULTANI, // 1128A..1128D
+ UNKNOWN, // 1128E
+ MULTANI, // 1128F..1129D
+ UNKNOWN, // 1129E
+ MULTANI, // 1129F..112A9
+ UNKNOWN, // 112AA..112AF
KHUDAWADI, // 112B0..112EA
UNKNOWN, // 112EB..112EF
KHUDAWADI, // 112F0..112F9
- UNKNOWN, // 112FA..11300
- GRANTHA, // 11301..11303
+ UNKNOWN, // 112FA..112FF
+ GRANTHA, // 11300..11303
UNKNOWN, // 11304
GRANTHA, // 11305..1130C
UNKNOWN, // 1130D..1130E
@@ -6734,7 +6930,9 @@
GRANTHA, // 11347..11348
UNKNOWN, // 11349..1134A
GRANTHA, // 1134B..1134D
- UNKNOWN, // 1134E..11356
+ UNKNOWN, // 1134E..1134F
+ GRANTHA, // 11350
+ UNKNOWN, // 11351..11356
GRANTHA, // 11357
UNKNOWN, // 11358..1135C
GRANTHA, // 1135D..11363
@@ -6749,8 +6947,8 @@
UNKNOWN, // 114DA..1157F
SIDDHAM, // 11580..115B5
UNKNOWN, // 115B6..115B7
- SIDDHAM, // 115B8..115C9
- UNKNOWN, // 115CA..115FF
+ SIDDHAM, // 115B8..115DD
+ UNKNOWN, // 115DE..115FF
MODI, // 11600..11644
UNKNOWN, // 11645..1164F
MODI, // 11650..11659
@@ -6758,21 +6956,31 @@
TAKRI, // 11680..116B7
UNKNOWN, // 116B8..116BF
TAKRI, // 116C0..116C9
- UNKNOWN, // 116CA..1189F
+ UNKNOWN, // 116CA..116FF
+ AHOM, // 11700..11719
+ UNKNOWN, // 1171A..1171C
+ AHOM, // 1171D..1172B
+ UNKNOWN, // 1172C..1172F
+ AHOM, // 11730..1173F
+ UNKNOWN, // 11740..1189F
WARANG_CITI, // 118A0..118F2
UNKNOWN, // 118F3..118FE
WARANG_CITI, // 118FF
UNKNOWN, // 11900..11ABF
PAU_CIN_HAU, // 11AC0..11AF8
UNKNOWN, // 11AF9..11FFF
- CUNEIFORM, // 12000..12398
- UNKNOWN, // 12399..123FF
+ CUNEIFORM, // 12000..12399
+ UNKNOWN, // 1239A..123FF
CUNEIFORM, // 12400..1246E
UNKNOWN, // 1246F
CUNEIFORM, // 12470..12474
- UNKNOWN, // 12475..12FFF
+ UNKNOWN, // 12475..1247F
+ CUNEIFORM, // 12480..12543
+ UNKNOWN, // 12544..12FFF
EGYPTIAN_HIEROGLYPHS, // 13000..1342E
- UNKNOWN, // 1342F..167FF
+ UNKNOWN, // 1342F..143FF
+ ANATOLIAN_HIEROGLYPHS, // 14400..14646
+ UNKNOWN, // 14647..167FF
BAMUM, // 16800..16A38
UNKNOWN, // 16A39..16A3F
MRO, // 16A40..16A5E
@@ -6827,8 +7035,8 @@
INHERITED, // 1D185..1D18B
COMMON, // 1D18C..1D1A9
INHERITED, // 1D1AA..1D1AD
- COMMON, // 1D1AE..1D1DD
- UNKNOWN, // 1D1DE..1D1FF
+ COMMON, // 1D1AE..1D1E8
+ UNKNOWN, // 1D1E9..1D1FF
GREEK, // 1D200..1D245
UNKNOWN, // 1D246..1D2FF
COMMON, // 1D300..1D356
@@ -6876,7 +7084,12 @@
COMMON, // 1D6A8..1D7CB
UNKNOWN, // 1D7CC..1D7CD
COMMON, // 1D7CE..1D7FF
- UNKNOWN, // 1D800..1E7FF
+ SIGNWRITING, // 1D800..1DA8B
+ UNKNOWN, // 1DA8C..1DA9A
+ SIGNWRITING, // 1DA9B..1DA9F
+ UNKNOWN, // 1DAA0
+ SIGNWRITING, // 1DAA1..1DAAF
+ UNKNOWN, // 1DAB0..1E7FF
MENDE_KIKAKUI, // 1E800..1E8C4
UNKNOWN, // 1E8C5..1E8C6
MENDE_KIKAKUI, // 1E8C7..1E8D6
@@ -6979,26 +7192,12 @@
UNKNOWN, // 1F249..1F24F
COMMON, // 1F250..1F251
UNKNOWN, // 1F252..1F2FF
- COMMON, // 1F300..1F32C
- UNKNOWN, // 1F32D..1F32F
- COMMON, // 1F330..1F37D
- UNKNOWN, // 1F37E..1F37F
- COMMON, // 1F380..1F3CE
- UNKNOWN, // 1F3CF..1F3D3
- COMMON, // 1F3D4..1F3F7
- UNKNOWN, // 1F3F8..1F3FF
- COMMON, // 1F400..1F4FE
- UNKNOWN, // 1F4FF
- COMMON, // 1F500..1F54A
- UNKNOWN, // 1F54B..1F54F
- COMMON, // 1F550..1F579
+ COMMON, // 1F300..1F579
UNKNOWN, // 1F57A
COMMON, // 1F57B..1F5A3
UNKNOWN, // 1F5A4
- COMMON, // 1F5A5..1F642
- UNKNOWN, // 1F643..1F644
- COMMON, // 1F645..1F6CF
- UNKNOWN, // 1F6D0..1F6DF
+ COMMON, // 1F5A5..1F6D0
+ UNKNOWN, // 1F6D1..1F6DF
COMMON, // 1F6E0..1F6EC
UNKNOWN, // 1F6ED..1F6EF
COMMON, // 1F6F0..1F6F3
@@ -7016,13 +7215,21 @@
COMMON, // 1F860..1F887
UNKNOWN, // 1F888..1F88F
COMMON, // 1F890..1F8AD
- UNKNOWN, // 1F8AE..1FFFF
+ UNKNOWN, // 1F8AE..1F90F
+ COMMON, // 1F910..1F918
+ UNKNOWN, // 1F919..1F97F
+ COMMON, // 1F980..1F984
+ UNKNOWN, // 1F985..1F9BF
+ COMMON, // 1F9C0
+ UNKNOWN, // 1F9C1..1FFFF
HAN, // 20000..2A6D6
UNKNOWN, // 2A6D7..2A6FF
HAN, // 2A700..2B734
UNKNOWN, // 2B735..2B73F
HAN, // 2B740..2B81D
- UNKNOWN, // 2B81E..2F7FF
+ UNKNOWN, // 2B81E..2B81F
+ HAN, // 2B820..2CEA1
+ UNKNOWN, // 2CEA2..2F7FF
HAN, // 2F800..2FA1D
UNKNOWN, // 2FA1E..E0000
COMMON, // E0001
@@ -7035,8 +7242,9 @@
private static HashMap<String, Character.UnicodeScript> aliases;
static {
- aliases = new HashMap<>(128);
+ aliases = new HashMap<>(134);
aliases.put("AGHB", CAUCASIAN_ALBANIAN);
+ aliases.put("AHOM", AHOM);
aliases.put("ARAB", ARABIC);
aliases.put("ARMI", IMPERIAL_ARAMAIC);
aliases.put("ARMN", ARMENIAN);
@@ -7075,11 +7283,14 @@
aliases.put("HANG", HANGUL);
aliases.put("HANI", HAN);
aliases.put("HANO", HANUNOO);
+ aliases.put("HATR", HATRAN);
aliases.put("HEBR", HEBREW);
aliases.put("HIRA", HIRAGANA);
+ aliases.put("HLUW", ANATOLIAN_HIEROGLYPHS);
aliases.put("HMNG", PAHAWH_HMONG);
// it appears we don't have the KATAKANA_OR_HIRAGANA
//aliases.put("HRKT", KATAKANA_OR_HIRAGANA);
+ aliases.put("HUNG", OLD_HUNGARIAN);
aliases.put("ITAL", OLD_ITALIC);
aliases.put("JAVA", JAVANESE);
aliases.put("KALI", KAYAH_LI);
@@ -7110,6 +7321,7 @@
aliases.put("MONG", MONGOLIAN);
aliases.put("MROO", MRO);
aliases.put("MTEI", MEETEI_MAYEK);
+ aliases.put("MULT", MULTANI);
aliases.put("MYMR", MYANMAR);
aliases.put("NARB", OLD_NORTH_ARABIAN);
aliases.put("NBAT", NABATAEAN);
@@ -7133,6 +7345,7 @@
aliases.put("SAMR", SAMARITAN);
aliases.put("SARB", OLD_SOUTH_ARABIAN);
aliases.put("SAUR", SAURASHTRA);
+ aliases.put("SGNW", SIGNWRITING);
aliases.put("SHAW", SHAVIAN);
aliases.put("SHRD", SHARADA);
aliases.put("SIDD", SIDDHAM);
@@ -9356,7 +9569,7 @@
* <td>{@code FORM FEED}</td></tr>
* <tr><td>{@code '\r'}</td> <td>{@code U+000D}</td>
* <td>{@code CARRIAGE RETURN}</td></tr>
- * <tr><td>{@code ' '}</td> <td>{@code U+0020}</td>
+ * <tr><td>{@code ' '}</td> <td>{@code U+0020}</td>
* <td>{@code SPACE}</td></tr>
* </table>
*
--- a/jdk/src/java.base/share/classes/java/lang/FdLibm.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/FdLibm.java Tue Oct 20 08:24:37 2015 -0700
@@ -100,6 +100,64 @@
}
/**
+ * cbrt(x)
+ * Return cube root of x
+ */
+ public static class Cbrt {
+ // unsigned
+ private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+ private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+ private static final double C = 0x1.15f15f15f15f1p-1; // 19/35 ~= 5.42857142857142815906e-01
+ private static final double D = -0x1.691de2532c834p-1; // -864/1225 ~= 7.05306122448979611050e-01
+ private static final double E = 0x1.6a0ea0ea0ea0fp0; // 99/70 ~= 1.41428571428571436819e+00
+ private static final double F = 0x1.9b6db6db6db6ep0; // 45/28 ~= 1.60714285714285720630e+00
+ private static final double G = 0x1.6db6db6db6db7p-2; // 5/14 ~= 3.57142857142857150787e-01
+
+ public static strictfp double compute(double x) {
+ double t = 0.0;
+ double sign;
+
+ if (x == 0.0 || !Double.isFinite(x))
+ return x; // Handles signed zeros properly
+
+ sign = (x < 0.0) ? -1.0: 1.0;
+
+ x = Math.abs(x); // x <- |x|
+
+ // Rough cbrt to 5 bits
+ if (x < 0x1.0p-1022) { // subnormal number
+ t = 0x1.0p54; // set t= 2**54
+ t *= x;
+ t = __HI(t, __HI(t)/3 + B2);
+ } else {
+ int hx = __HI(x); // high word of x
+ t = __HI(t, hx/3 + B1);
+ }
+
+ // New cbrt to 23 bits, may be implemented in single precision
+ double r, s, w;
+ r = t * t/x;
+ s = C + r*t;
+ t *= G + F/(s + E + D/s);
+
+ // Chopped to 20 bits and make it larger than cbrt(x)
+ t = __LO(t, 0);
+ t = __HI(t, __HI(t) + 0x00000001);
+
+ // 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-s is exact
+ t = t + t*r;
+
+ // Restore the original sign bit
+ return sign * t;
+ }
+ }
+
+ /**
* hypot(x,y)
*
* Method :
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java Tue Oct 20 08:24:37 2015 -0700
@@ -307,7 +307,9 @@
* @return the cube root of {@code a}.
* @since 1.5
*/
- public static native double cbrt(double a);
+ public static double cbrt(double a) {
+ return FdLibm.Cbrt.compute(a);
+ }
/**
* Computes the remainder operation on two arguments as prescribed
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -834,7 +834,7 @@
static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
try {
- return LOOKUP.findStatic(cbmh, "make", MethodType.fromMethodDescriptorString(makeSignature(types, false), null));
+ return LOOKUP.findStatic(cbmh, "make", MethodType.fromDescriptor(makeSignature(types, false), null));
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
throw newInternalError(e);
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -141,7 +141,7 @@
synchronized (this) {
if (type instanceof String) {
String sig = (String) type;
- MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
+ MethodType res = MethodType.fromDescriptor(sig, getClassLoader());
type = res;
} else if (type instanceof Object[]) {
Object[] typeInfo = (Object[]) type;
@@ -206,7 +206,7 @@
synchronized (this) {
if (type instanceof String) {
String sig = (String) type;
- MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
+ MethodType mtype = MethodType.fromDescriptor("()"+sig, getClassLoader());
Class<?> res = mtype.returnType();
type = res;
}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Tue Oct 20 08:24:37 2015 -0700
@@ -383,7 +383,7 @@
if (type instanceof MethodType)
return (MethodType) type;
else
- return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader());
+ return MethodType.fromDescriptor((String)type, callerClass.getClassLoader());
}
// Tracing logic:
static MemberName linkMethodTracing(Class<?> callerClass, int refKind,
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1058,6 +1058,23 @@
public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
throws IllegalArgumentException, TypeNotPresentException
{
+ return fromDescriptor(descriptor,
+ (loader == null) ? ClassLoader.getSystemClassLoader() : loader);
+ }
+
+ /**
+ * Same as {@link #fromMethodDescriptorString(String, ClassLoader)}, but
+ * {@code null} ClassLoader means the bootstrap loader is used here.
+ * <p>
+ * IMPORTANT: This method is preferable for JDK internal use as it more
+ * correctly interprets {@code null} ClassLoader than
+ * {@link #fromMethodDescriptorString(String, ClassLoader)}.
+ * Use of this method also avoids early initialization issues when system
+ * ClassLoader is not initialized yet.
+ */
+ static MethodType fromDescriptor(String descriptor, ClassLoader loader)
+ throws IllegalArgumentException, TypeNotPresentException
+ {
if (!descriptor.startsWith("(") || // also generates NPE if needed
descriptor.indexOf(')') < 0 ||
descriptor.indexOf('.') >= 0)
--- a/jdk/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -131,7 +131,7 @@
}
private static String boxingDescriptor(Wrapper w) {
- return String.format("(%s)L%s;", w.basicTypeChar(), wrapperName(w));
+ return "(" + w.basicTypeChar() + ")L" + wrapperName(w) + ";";
}
private static String unboxingDescriptor(Wrapper w) {
--- a/jdk/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java Tue Oct 20 08:24:37 2015 -0700
@@ -138,6 +138,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the algorithm this
* parameter generator is associated with.
* See the AlgorithmParameterGenerator section in the <a href=
--- a/jdk/src/java.base/share/classes/java/security/AlgorithmParameters.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/AlgorithmParameters.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,6 +126,13 @@
* {@code init}, using an appropriate parameter specification or
* parameter encoding.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the algorithm requested.
* See the AlgorithmParameters section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#AlgorithmParameters">
--- a/jdk/src/java.base/share/classes/java/security/KeyFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/KeyFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -153,6 +153,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the requested key algorithm.
* See the KeyFactory section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyFactory">
--- a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java Tue Oct 20 08:24:37 2015 -0700
@@ -195,6 +195,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard string name of the algorithm.
* See the KeyPairGenerator section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyPairGenerator">
--- a/jdk/src/java.base/share/classes/java/security/KeyStore.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/KeyStore.java Tue Oct 20 08:24:37 2015 -0700
@@ -841,6 +841,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param type the type of keystore.
* See the KeyStore section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyStore">
--- a/jdk/src/java.base/share/classes/java/security/MessageDigest.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/MessageDigest.java Tue Oct 20 08:24:37 2015 -0700
@@ -146,6 +146,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the algorithm requested.
* See the MessageDigest section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#MessageDigest">
--- a/jdk/src/java.base/share/classes/java/security/Policy.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/Policy.java Tue Oct 20 08:24:37 2015 -0700
@@ -355,6 +355,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param type the specified Policy type. See the Policy section in the
* <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
--- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -268,6 +268,13 @@
* This self-seeding will not occur if {@code setSeed} was
* previously called.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the RNG algorithm.
* See the SecureRandom section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SecureRandom">
--- a/jdk/src/java.base/share/classes/java/security/Signature.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/Signature.java Tue Oct 20 08:24:37 2015 -0700
@@ -203,6 +203,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the algorithm requested.
* See the Signature section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Signature">
--- a/jdk/src/java.base/share/classes/java/security/cert/CertPathBuilder.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertPathBuilder.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -142,6 +142,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the requested {@code CertPathBuilder}
* algorithm. See the CertPathBuilder section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder">
--- a/jdk/src/java.base/share/classes/java/security/cert/CertPathValidator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertPathValidator.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -143,6 +143,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the name of the requested {@code CertPathValidator}
* algorithm. See the CertPathValidator section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathValidator">
--- a/jdk/src/java.base/share/classes/java/security/cert/CertStore.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertStore.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -201,6 +201,13 @@
* Note that the specified {@code CertStoreParameters} object is
* cloned.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param type the name of the requested {@code CertStore} type.
* See the CertStore section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#CertStore">
--- a/jdk/src/java.base/share/classes/java/security/cert/CertificateFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertificateFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -163,6 +163,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param type the name of the requested certificate type.
* See the CertificateFactory section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#CertificateFactory">
--- a/jdk/src/java.base/share/classes/java/util/AbstractQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/AbstractQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -38,16 +38,16 @@
/**
* This class provides skeletal implementations of some {@link Queue}
* operations. The implementations in this class are appropriate when
- * the base implementation does <em>not</em> allow <tt>null</tt>
+ * the base implementation does <em>not</em> allow {@code null}
* elements. Methods {@link #add add}, {@link #remove remove}, and
* {@link #element element} are based on {@link #offer offer}, {@link
* #poll poll}, and {@link #peek peek}, respectively, but throw
- * exceptions instead of indicating failure via <tt>false</tt> or
- * <tt>null</tt> returns.
+ * exceptions instead of indicating failure via {@code false} or
+ * {@code null} returns.
*
- * <p>A <tt>Queue</tt> implementation that extends this class must
+ * <p>A {@code Queue} implementation that extends this class must
* minimally define a method {@link Queue#offer} which does not permit
- * insertion of <tt>null</tt> elements, along with methods {@link
+ * insertion of {@code null} elements, along with methods {@link
* Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and
* {@link Collection#iterator}. Typically, additional methods will be
* overridden as well. If these requirements cannot be met, consider
@@ -59,7 +59,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public abstract class AbstractQueue<E>
extends AbstractCollection<E>
@@ -74,14 +74,14 @@
/**
* Inserts the specified element into this queue if it is possible to do so
* immediately without violating capacity restrictions, returning
- * <tt>true</tt> upon success and throwing an <tt>IllegalStateException</tt>
+ * {@code true} upon success and throwing an {@code IllegalStateException}
* if no space is currently available.
*
- * <p>This implementation returns <tt>true</tt> if <tt>offer</tt> succeeds,
- * else throws an <tt>IllegalStateException</tt>.
+ * <p>This implementation returns {@code true} if {@code offer} succeeds,
+ * else throws an {@code IllegalStateException}.
*
* @param e the element to add
- * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
@@ -103,7 +103,7 @@
* from {@link #poll poll} only in that it throws an exception if this
* queue is empty.
*
- * <p>This implementation returns the result of <tt>poll</tt>
+ * <p>This implementation returns the result of {@code poll}
* unless the queue is empty.
*
* @return the head of this queue
@@ -122,7 +122,7 @@
* differs from {@link #peek peek} only in that it throws an exception if
* this queue is empty.
*
- * <p>This implementation returns the result of <tt>peek</tt>
+ * <p>This implementation returns the result of {@code peek}
* unless the queue is empty.
*
* @return the head of this queue
@@ -141,7 +141,7 @@
* The queue will be empty after this call returns.
*
* <p>This implementation repeatedly invokes {@link #poll poll} until it
- * returns <tt>null</tt>.
+ * returns {@code null}.
*/
public void clear() {
while (poll() != null)
@@ -151,7 +151,7 @@
/**
* Adds all of the elements in the specified collection to this
* queue. Attempts to addAll of a queue to itself result in
- * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * {@code IllegalArgumentException}. Further, the behavior of
* this operation is undefined if the specified collection is
* modified while the operation is in progress.
*
@@ -159,12 +159,12 @@
* and adds each element returned by the iterator to this
* queue, in turn. A runtime exception encountered while
* trying to add an element (including, in particular, a
- * <tt>null</tt> element) may result in only some of the elements
+ * {@code null} element) may result in only some of the elements
* having been successfully added when the associated exception is
* thrown.
*
* @param c collection containing elements to be added to this queue
- * @return <tt>true</tt> if this queue changed as a result of the call
+ * @return {@code true} if this queue changed as a result of the call
* @throws ClassCastException if the class of an element of the specified
* collection prevents it from being added to this queue
* @throws NullPointerException if the specified collection contains a
--- a/jdk/src/java.base/share/classes/java/util/ArrayDeque.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/ArrayDeque.java Tue Oct 20 08:24:37 2015 -0700
@@ -47,16 +47,18 @@
* when used as a queue.
*
* <p>Most {@code ArrayDeque} operations run in amortized constant time.
- * Exceptions include {@link #remove(Object) remove}, {@link
- * #removeFirstOccurrence removeFirstOccurrence}, {@link #removeLastOccurrence
- * removeLastOccurrence}, {@link #contains contains}, {@link #iterator
- * iterator.remove()}, and the bulk operations, all of which run in linear
- * time.
+ * Exceptions include
+ * {@link #remove(Object) remove},
+ * {@link #removeFirstOccurrence removeFirstOccurrence},
+ * {@link #removeLastOccurrence removeLastOccurrence},
+ * {@link #contains contains},
+ * {@link #iterator iterator.remove()},
+ * and the bulk operations, all of which run in linear time.
*
- * <p>The iterators returned by this class's {@code iterator} method are
- * <i>fail-fast</i>: If the deque is modified at any time after the iterator
- * is created, in any way except through the iterator's own {@code remove}
- * method, the iterator will generally throw a {@link
+ * <p>The iterators returned by this class's {@link #iterator() iterator}
+ * method are <em>fail-fast</em>: If the deque is modified at any time after
+ * the iterator is created, in any way except through the iterator's own
+ * {@code remove} method, the iterator will generally throw a {@link
* ConcurrentModificationException}. Thus, in the face of concurrent
* modification, the iterator fails quickly and cleanly, rather than risking
* arbitrary, non-deterministic behavior at an undetermined time in the
@@ -80,7 +82,7 @@
*
* @author Josh Bloch and Doug Lea
* @since 1.6
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
*/
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
@@ -136,8 +138,8 @@
initialCapacity |= (initialCapacity >>> 16);
initialCapacity++;
- if (initialCapacity < 0) // Too many elements, must back off
- initialCapacity >>>= 1;// Good luck allocating 2 ^ 30 elements
+ if (initialCapacity < 0) // Too many elements, must back off
+ initialCapacity >>>= 1; // Good luck allocating 2^30 elements
}
elements = new Object[initialCapacity];
}
@@ -163,24 +165,6 @@
}
/**
- * Copies the elements from our element array into the specified array,
- * in order (from first to last element in the deque). It is assumed
- * that the array is large enough to hold all elements in the deque.
- *
- * @return its argument
- */
- private <T> T[] copyElements(T[] a) {
- if (head < tail) {
- System.arraycopy(elements, head, a, 0, size());
- } else if (head > tail) {
- int headPortionLen = elements.length - head;
- System.arraycopy(elements, head, a, 0, headPortionLen);
- System.arraycopy(elements, 0, a, headPortionLen, tail);
- }
- return a;
- }
-
- /**
* Constructs an empty array deque with an initial capacity
* sufficient to hold 16 elements.
*/
@@ -292,25 +276,27 @@
}
public E pollFirst() {
- int h = head;
+ final Object[] elements = this.elements;
+ final int h = head;
@SuppressWarnings("unchecked")
E result = (E) elements[h];
// Element is null if deque empty
- if (result == null)
- return null;
- elements[h] = null; // Must null out slot
- head = (h + 1) & (elements.length - 1);
+ if (result != null) {
+ elements[h] = null; // Must null out slot
+ head = (h + 1) & (elements.length - 1);
+ }
return result;
}
public E pollLast() {
- int t = (tail - 1) & (elements.length - 1);
+ final Object[] elements = this.elements;
+ final int t = (tail - 1) & (elements.length - 1);
@SuppressWarnings("unchecked")
E result = (E) elements[t];
- if (result == null)
- return null;
- elements[t] = null;
- tail = t;
+ if (result != null) {
+ elements[t] = null;
+ tail = t;
+ }
return result;
}
@@ -360,17 +346,15 @@
* @return {@code true} if the deque contained the specified element
*/
public boolean removeFirstOccurrence(Object o) {
- if (o == null)
- return false;
- int mask = elements.length - 1;
- int i = head;
- Object x;
- while ( (x = elements[i]) != null) {
- if (o.equals(x)) {
- delete(i);
- return true;
+ if (o != null) {
+ int mask = elements.length - 1;
+ int i = head;
+ for (Object x; (x = elements[i]) != null; i = (i + 1) & mask) {
+ if (o.equals(x)) {
+ delete(i);
+ return true;
+ }
}
- i = (i + 1) & mask;
}
return false;
}
@@ -388,17 +372,15 @@
* @return {@code true} if the deque contained the specified element
*/
public boolean removeLastOccurrence(Object o) {
- if (o == null)
- return false;
- int mask = elements.length - 1;
- int i = (tail - 1) & mask;
- Object x;
- while ( (x = elements[i]) != null) {
- if (o.equals(x)) {
- delete(i);
- return true;
+ if (o != null) {
+ int mask = elements.length - 1;
+ int i = (tail - 1) & mask;
+ for (Object x; (x = elements[i]) != null; i = (i - 1) & mask) {
+ if (o.equals(x)) {
+ delete(i);
+ return true;
+ }
}
- i = (i - 1) & mask;
}
return false;
}
@@ -535,7 +517,7 @@
*
* @return true if elements moved backwards
*/
- private boolean delete(int i) {
+ boolean delete(int i) {
checkInvariants();
final Object[] elements = this.elements;
final int mask = elements.length - 1;
@@ -671,12 +653,12 @@
}
}
+ /**
+ * This class is nearly a mirror-image of DeqIterator, using tail
+ * instead of head for initial cursor, and head instead of tail
+ * for fence.
+ */
private class DescendingIterator implements Iterator<E> {
- /*
- * This class is nearly a mirror-image of DeqIterator, using
- * tail instead of head for initial cursor, and head instead of
- * tail for fence.
- */
private int cursor = tail;
private int fence = head;
private int lastRet = -1;
@@ -717,15 +699,13 @@
* @return {@code true} if this deque contains the specified element
*/
public boolean contains(Object o) {
- if (o == null)
- return false;
- int mask = elements.length - 1;
- int i = head;
- Object x;
- while ( (x = elements[i]) != null) {
- if (o.equals(x))
- return true;
- i = (i + 1) & mask;
+ if (o != null) {
+ int mask = elements.length - 1;
+ int i = head;
+ for (Object x; (x = elements[i]) != null; i = (i + 1) & mask) {
+ if (o.equals(x))
+ return true;
+ }
}
return false;
}
@@ -779,7 +759,14 @@
* @return an array containing all of the elements in this deque
*/
public Object[] toArray() {
- return copyElements(new Object[size()]);
+ final int head = this.head;
+ final int tail = this.tail;
+ boolean wrap = (tail < head);
+ int end = wrap ? tail + elements.length : tail;
+ Object[] a = Arrays.copyOfRange(elements, head, end);
+ if (wrap)
+ System.arraycopy(elements, 0, a, elements.length - head, tail);
+ return a;
}
/**
@@ -804,7 +791,7 @@
* The following code can be used to dump the deque into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -820,13 +807,22 @@
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- int size = size();
- if (a.length < size)
- a = (T[])java.lang.reflect.Array.newInstance(
- a.getClass().getComponentType(), size);
- copyElements(a);
- if (a.length > size)
- a[size] = null;
+ final int head = this.head;
+ final int tail = this.tail;
+ boolean wrap = (tail < head);
+ int size = (tail - head) + (wrap ? elements.length : 0);
+ int firstLeg = size - (wrap ? tail : 0);
+ int len = a.length;
+ if (size > len) {
+ a = (T[]) Arrays.copyOfRange(elements, head, head + size,
+ a.getClass());
+ } else {
+ System.arraycopy(elements, head, a, 0, firstLeg);
+ if (size < len)
+ a[size] = null;
+ }
+ if (wrap)
+ System.arraycopy(elements, 0, a, firstLeg, tail);
return a;
}
@@ -853,6 +849,8 @@
/**
* Saves this deque to a stream (that is, serializes it).
*
+ * @param s the stream
+ * @throws java.io.IOException if an I/O error occurs
* @serialData The current size ({@code int}) of the deque,
* followed by all of its elements (each an object reference) in
* first-to-last order.
@@ -872,6 +870,10 @@
/**
* Reconstitutes this deque from a stream (that is, deserializes it).
+ * @param s the stream
+ * @throws ClassNotFoundException if the class of a serialized object
+ * could not be found
+ * @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -910,7 +912,7 @@
private int fence; // -1 until first use
private int index; // current index, modified on traverse/split
- /** Creates new spliterator covering the given array and range */
+ /** Creates new spliterator covering the given array and range. */
DeqSpliterator(ArrayDeque<E> deq, int origin, int fence) {
this.deq = deq;
this.index = origin;
@@ -932,7 +934,7 @@
if (h > t)
t += n;
int m = ((h + t) >>> 1) & (n - 1);
- return new DeqSpliterator<>(deq, h, index = m);
+ return new DeqSpliterator<E>(deq, h, index = m);
}
return null;
}
@@ -957,7 +959,7 @@
throw new NullPointerException();
Object[] a = deq.elements;
int m = a.length - 1, f = getFence(), i = index;
- if (i != fence) {
+ if (i != f) {
@SuppressWarnings("unchecked") E e = (E)a[i];
index = (i + 1) & m;
if (e == null)
--- a/jdk/src/java.base/share/classes/java/util/ArrayPrefixHelpers.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/ArrayPrefixHelpers.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,4 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,20 +21,26 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package java.util;
/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-import java.util.concurrent.ForkJoinPool;
+package java.util;
+
import java.util.concurrent.CountedCompleter;
+import java.util.concurrent.ForkJoinPool;
import java.util.function.BinaryOperator;
+import java.util.function.DoubleBinaryOperator;
import java.util.function.IntBinaryOperator;
import java.util.function.LongBinaryOperator;
-import java.util.function.DoubleBinaryOperator;
/**
* ForkJoin tasks to perform Arrays.parallelPrefix operations.
@@ -44,7 +49,7 @@
* @since 1.8
*/
class ArrayPrefixHelpers {
- private ArrayPrefixHelpers() {}; // non-instantiable
+ private ArrayPrefixHelpers() {} // non-instantiable
/*
* Parallel prefix (aka cumulate, scan) task classes
@@ -113,8 +118,8 @@
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
- (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
- <= MIN_PARTITION ? MIN_PARTITION : p;
+ (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+ <= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
@@ -141,9 +146,9 @@
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
- new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
- t = lt = t.left =
- new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
+ new CumulateTask<T>(t, fn, a, org, fnc, th, mid, h);
+ t = lt = t.left =
+ new CumulateTask<T>(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
T pin = t.in;
@@ -183,7 +188,7 @@
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
- state = ((b & CUMULATE) != 0? FINISHED :
+ state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
@@ -265,8 +270,8 @@
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
- (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
- <= MIN_PARTITION ? MIN_PARTITION : p;
+ (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+ <= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
@@ -293,9 +298,9 @@
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
- new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
- t = lt = t.left =
- new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
+ new LongCumulateTask(t, fn, a, org, fnc, th, mid, h);
+ t = lt = t.left =
+ new LongCumulateTask(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
long pin = t.in;
@@ -335,7 +340,7 @@
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
- state = ((b & CUMULATE) != 0? FINISHED :
+ state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
@@ -415,8 +420,8 @@
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
- (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
- <= MIN_PARTITION ? MIN_PARTITION : p;
+ (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+ <= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
@@ -443,9 +448,9 @@
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
- new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
- t = lt = t.left =
- new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
+ new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
+ t = lt = t.left =
+ new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
double pin = t.in;
@@ -485,7 +490,7 @@
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
- state = ((b & CUMULATE) != 0? FINISHED :
+ state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
@@ -565,8 +570,8 @@
this.lo = this.origin = lo; this.hi = this.fence = hi;
int p;
this.threshold =
- (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
- <= MIN_PARTITION ? MIN_PARTITION : p;
+ (p = (hi - lo) / (ForkJoinPool.getCommonPoolParallelism() << 3))
+ <= MIN_PARTITION ? MIN_PARTITION : p;
}
/** Subtask constructor */
@@ -593,9 +598,9 @@
if (lt == null) { // first pass
int mid = (l + h) >>> 1;
f = rt = t.right =
- new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
- t = lt = t.left =
- new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
+ new IntCumulateTask(t, fn, a, org, fnc, th, mid, h);
+ t = lt = t.left =
+ new IntCumulateTask(t, fn, a, org, fnc, th, l, mid);
}
else { // possibly refork
int pin = t.in;
@@ -635,7 +640,7 @@
for (int b;;) {
if (((b = t.getPendingCount()) & FINISHED) != 0)
break outer; // already done
- state = ((b & CUMULATE) != 0? FINISHED :
+ state = ((b & CUMULATE) != 0 ? FINISHED :
(l > org) ? SUMMED : (SUMMED|FINISHED));
if (t.compareAndSetPendingCount(b, b|state))
break;
--- a/jdk/src/java.base/share/classes/java/util/Collections.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java Tue Oct 20 08:24:37 2015 -0700
@@ -537,8 +537,9 @@
* Copies all of the elements from one list into another. After the
* operation, the index of each copied element in the destination list
* will be identical to its index in the source list. The destination
- * list must be at least as long as the source list. If it is longer, the
- * remaining elements in the destination list are unaffected. <p>
+ * list's size must be greater than or equal to the source list's size.
+ * If it is greater, the remaining elements in the destination list are
+ * unaffected. <p>
*
* This method runs in linear time.
*
--- a/jdk/src/java.base/share/classes/java/util/Deque.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Deque.java Tue Oct 20 08:24:37 2015 -0700
@@ -188,7 +188,7 @@
* @author Doug Lea
* @author Josh Bloch
* @since 1.6
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
*/
public interface Deque<E> extends Queue<E> {
/**
@@ -344,8 +344,7 @@
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>
- * (if such an element exists).
+ * {@code Objects.equals(o, e)} (if such an element exists).
* Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
@@ -353,10 +352,10 @@
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean removeFirstOccurrence(Object o);
@@ -364,8 +363,7 @@
* Removes the last occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the last element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>
- * (if such an element exists).
+ * {@code Objects.equals(o, e)} (if such an element exists).
* Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
@@ -373,10 +371,10 @@
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean removeLastOccurrence(Object o);
@@ -521,8 +519,7 @@
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
* More formally, removes the first element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>
- * (if such an element exists).
+ * {@code Objects.equals(o, e)} (if such an element exists).
* Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
@@ -532,27 +529,26 @@
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean remove(Object o);
/**
* Returns {@code true} if this deque contains the specified element.
* More formally, returns {@code true} if and only if this deque contains
- * at least one element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>.
+ * at least one element {@code e} such that {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this deque is to be tested
* @return {@code true} if this deque contains the specified element
- * @throws ClassCastException if the type of the specified element
+ * @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null and this
* deque does not permit null elements
- * (<a href="Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean contains(Object o);
@@ -561,7 +557,7 @@
*
* @return the number of elements in this deque
*/
- public int size();
+ int size();
/**
* Returns an iterator over the elements in this deque in proper sequence.
--- a/jdk/src/java.base/share/classes/java/util/NavigableMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/NavigableMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -38,30 +38,32 @@
/**
* A {@link SortedMap} extended with navigation methods returning the
* closest matches for given search targets. Methods
- * {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
- * and {@code higherEntry} return {@code Map.Entry} objects
+ * {@link #lowerEntry}, {@link #floorEntry}, {@link #ceilingEntry},
+ * and {@link #higherEntry} return {@code Map.Entry} objects
* associated with keys respectively less than, less than or equal,
* greater than or equal, and greater than a given key, returning
* {@code null} if there is no such key. Similarly, methods
- * {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
- * {@code higherKey} return only the associated keys. All of these
+ * {@link #lowerKey}, {@link #floorKey}, {@link #ceilingKey}, and
+ * {@link #higherKey} return only the associated keys. All of these
* methods are designed for locating, not traversing entries.
*
* <p>A {@code NavigableMap} may be accessed and traversed in either
- * ascending or descending key order. The {@code descendingMap}
+ * ascending or descending key order. The {@link #descendingMap}
* method returns a view of the map with the senses of all relational
* and directional methods inverted. The performance of ascending
* operations and views is likely to be faster than that of descending
- * ones. Methods {@code subMap}, {@code headMap},
- * and {@code tailMap} differ from the like-named {@code
- * SortedMap} methods in accepting additional arguments describing
- * whether lower and upper bounds are inclusive versus exclusive.
- * Submaps of any {@code NavigableMap} must implement the {@code
- * NavigableMap} interface.
+ * ones. Methods
+ * {@link #subMap(Object, boolean, Object, boolean) subMap(K, boolean, K, boolean)},
+ * {@link #headMap(Object, boolean) headMap(K, boolean)}, and
+ * {@link #tailMap(Object, boolean) tailMap(K, boolean)}
+ * differ from the like-named {@code SortedMap} methods in accepting
+ * additional arguments describing whether lower and upper bounds are
+ * inclusive versus exclusive. Submaps of any {@code NavigableMap}
+ * must implement the {@code NavigableMap} interface.
*
- * <p>This interface additionally defines methods {@code firstEntry},
- * {@code pollFirstEntry}, {@code lastEntry}, and
- * {@code pollLastEntry} that return and/or remove the least and
+ * <p>This interface additionally defines methods {@link #firstEntry},
+ * {@link #pollFirstEntry}, {@link #lastEntry}, and
+ * {@link #pollLastEntry} that return and/or remove the least and
* greatest mappings, if any exist, else returning {@code null}.
*
* <p>Implementations of entry-returning methods are expected to
@@ -80,7 +82,7 @@
* implement {@code NavigableMap}, but extensions and implementations
* of this interface are encouraged to override these methods to return
* {@code NavigableMap}. Similarly,
- * {@link #keySet()} can be overriden to return {@code NavigableSet}.
+ * {@link #keySet()} can be overridden to return {@link NavigableSet}.
*
* <p>This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -254,7 +256,7 @@
* operation), the results of the iteration are undefined.
*
* <p>The returned map has an ordering equivalent to
- * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code m.descendingMap().descendingMap()} returns a
* view of {@code m} essentially equivalent to {@code m}.
*
--- a/jdk/src/java.base/share/classes/java/util/NavigableSet.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/NavigableSet.java Tue Oct 20 08:24:37 2015 -0700
@@ -37,26 +37,30 @@
/**
* A {@link SortedSet} extended with navigation methods reporting
- * closest matches for given search targets. Methods {@code lower},
- * {@code floor}, {@code ceiling}, and {@code higher} return elements
+ * closest matches for given search targets. Methods {@link #lower},
+ * {@link #floor}, {@link #ceiling}, and {@link #higher} return elements
* respectively less than, less than or equal, greater than or equal,
* and greater than a given element, returning {@code null} if there
- * is no such element. A {@code NavigableSet} may be accessed and
- * traversed in either ascending or descending order. The {@code
- * descendingSet} method returns a view of the set with the senses of
- * all relational and directional methods inverted. The performance of
- * ascending operations and views is likely to be faster than that of
- * descending ones. This interface additionally defines methods
- * {@code pollFirst} and {@code pollLast} that return and remove the
- * lowest and highest element, if one exists, else returning {@code
- * null}. Methods {@code subSet}, {@code headSet},
- * and {@code tailSet} differ from the like-named {@code
- * SortedSet} methods in accepting additional arguments describing
- * whether lower and upper bounds are inclusive versus exclusive.
- * Subsets of any {@code NavigableSet} must implement the {@code
- * NavigableSet} interface.
+ * is no such element.
*
- * <p> The return values of navigation methods may be ambiguous in
+ * <p>A {@code NavigableSet} may be accessed and traversed in either
+ * ascending or descending order. The {@link #descendingSet} method
+ * returns a view of the set with the senses of all relational and
+ * directional methods inverted. The performance of ascending
+ * operations and views is likely to be faster than that of descending
+ * ones. This interface additionally defines methods {@link
+ * #pollFirst} and {@link #pollLast} that return and remove the lowest
+ * and highest element, if one exists, else returning {@code null}.
+ * Methods
+ * {@link #subSet(Object, boolean, Object, boolean) subSet(E, boolean, E, boolean)},
+ * {@link #headSet(Object, boolean) headSet(E, boolean)}, and
+ * {@link #tailSet(Object, boolean) tailSet(E, boolean)}
+ * differ from the like-named {@code SortedSet} methods in accepting
+ * additional arguments describing whether lower and upper bounds are
+ * inclusive versus exclusive. Subsets of any {@code NavigableSet}
+ * must implement the {@code NavigableSet} interface.
+ *
+ * <p>The return values of navigation methods may be ambiguous in
* implementations that permit {@code null} elements. However, even
* in this case the result can be disambiguated by checking
* {@code contains(null)}. To avoid such issues, implementations of
@@ -172,7 +176,7 @@
* the iteration are undefined.
*
* <p>The returned set has an ordering equivalent to
- * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code s.descendingSet().descendingSet()} returns a
* view of {@code s} essentially equivalent to {@code s}.
*
--- a/jdk/src/java.base/share/classes/java/util/Optional.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Optional.java Tue Oct 20 08:24:37 2015 -0700
@@ -31,21 +31,22 @@
import java.util.stream.Stream;
/**
- * A container object which may or may not contain a non-null value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code get()} will return the value.
+ * A container object which may or may not contain a non-{@code null} value.
+ * If a value is present, {@code isPresent()} returns {@code true} and
+ * {@code get()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(java.lang.Object) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (perform an
- * action if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (performs an
+ * action if a value is present).
*
* <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
* ({@code ==}), identity hash code, or synchronization) on instances of
* {@code Optional} may have unpredictable results and should be avoided.
*
+ * @param <T> the type of value
* @since 1.8
*/
public final class Optional<T> {
@@ -71,14 +72,15 @@
/**
* Returns an empty {@code Optional} instance. No value is present for this
- * Optional.
+ * {@code Optional}.
*
- * @apiNote Though it may be tempting to do so, avoid testing if an object
- * is empty by comparing with {@code ==} against instances returned by
- * {@code Option.empty()}. There is no guarantee that it is a singleton.
+ * @apiNote
+ * Though it may be tempting to do so, avoid testing if an object is empty
+ * by comparing with {@code ==} against instances returned by
+ * {@code Optional.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
- * @param <T> Type of the non-existent value
+ * @param <T> The type of the non-existent value
* @return an empty {@code Optional}
*/
public static<T> Optional<T> empty() {
@@ -88,47 +90,47 @@
}
/**
- * Constructs an instance with the value present.
+ * Constructs an instance with the described value.
*
- * @param value the non-null value to be present
- * @throws NullPointerException if value is null
+ * @param value the non-{@code null} value to describe
+ * @throws NullPointerException if value is {@code null}
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
/**
- * Returns an {@code Optional} with the specified present non-null value.
+ * Returns an {@code Optional} describing the given non-{@code null}
+ * value.
*
- * @param <T> the class of the value
- * @param value the value to be present, which must be non-null
+ * @param value the value to describe, which must be non-{@code null}
+ * @param <T> the type of the value
* @return an {@code Optional} with the value present
- * @throws NullPointerException if value is null
+ * @throws NullPointerException if value is {@code null}
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
- * Returns an {@code Optional} describing the specified value, if non-null,
- * otherwise returns an empty {@code Optional}.
+ * Returns an {@code Optional} describing the given value, if
+ * non-{@code null}, otherwise returns an empty {@code Optional}.
*
- * @param <T> the class of the value
- * @param value the possibly-null value to describe
+ * @param value the possibly-{@code null} value to describe
+ * @param <T> the type of the value
* @return an {@code Optional} with a present value if the specified value
- * is non-null, otherwise an empty {@code Optional}
+ * is non-{@code null}, otherwise an empty {@code Optional}
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
- * If a value is present in this {@code Optional}, returns the value,
- * otherwise throws {@code NoSuchElementException}.
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
*
- * @return the non-null value held by this {@code Optional}
- * @throws NoSuchElementException if there is no value present
- *
+ * @return the non-{@code null} value described by this {@code Optional}
+ * @throws NoSuchElementException if no value is present
* @see Optional#isPresent()
*/
public T get() {
@@ -139,21 +141,21 @@
}
/**
- * Return {@code true} if there is a value present, otherwise {@code false}.
+ * If a value is present, returns {@code true}, otherwise {@code false}.
*
- * @return {@code true} if there is a value present, otherwise {@code false}
+ * @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise do nothing.
+ * If a value is present, performs the given action with the value,
+ * otherwise does nothing.
*
- * @param action the action to be performed if a value is present
- * @throws NullPointerException if a value is present and {@code action} is
- * null
+ * @param action the action to be performed, if a value is present
+ * @throws NullPointerException if value is present and the given action is
+ * {@code null}
*/
public void ifPresent(Consumer<? super T> action) {
if (value != null) {
@@ -162,15 +164,16 @@
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise perform the given empty-based action.
+ * If a value is present, performs the given action with the value,
+ * otherwise performs the given empty-based action.
*
- * @param action the action to be performed if a value is present
- * @param emptyAction the empty-based action to be performed if a value is
- * not present
- * @throws NullPointerException if a value is present and {@code action} is
- * null, or a value is not present and {@code emptyAction} is null.
- * @since 1.9
+ * @param action the action to be performed, if a value is present
+ * @param emptyAction the empty-based action to be performed, if no value is
+ * present
+ * @throws NullPointerException if a value is present and the given action
+ * is {@code null}, or no value is present and the given empty-based
+ * action is {@code null}.
+ * @since 9
*/
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
if (value != null) {
@@ -182,14 +185,14 @@
/**
* If a value is present, and the value matches the given predicate,
- * return an {@code Optional} describing the value, otherwise return an
+ * returns an {@code Optional} describing the value, otherwise returns an
* empty {@code Optional}.
*
- * @param predicate a predicate to apply to the value, if present
- * @return an {@code Optional} describing the value of this {@code Optional}
- * if a value is present and the value matches the given predicate,
- * otherwise an empty {@code Optional}
- * @throws NullPointerException if the predicate is null
+ * @param predicate the predicate to apply to a value, if present
+ * @return an {@code Optional} describing the value of this
+ * {@code Optional}, if a value is present and the value matches the
+ * given predicate, otherwise an empty {@code Optional}
+ * @throws NullPointerException if the predicate is {@code null}
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
@@ -201,14 +204,18 @@
}
/**
- * If a value is present, apply the provided mapping function to it,
- * and if the result is non-null, return an {@code Optional} describing the
- * result. Otherwise return an empty {@code Optional}.
+ * If a value is present, returns an {@code Optional} describing (as if by
+ * {@link #ofNullable}) the result of applying the given mapping function to
+ * the value, otherwise returns an empty {@code Optional}.
*
- * @apiNote This method supports post-processing on optional values, without
+ * <p>If the mapping function returns a {@code null} result then this method
+ * returns an empty {@code Optional}.
+ *
+ * @apiNote
+ * This method supports post-processing on {@code Optional} values, without
* the need to explicitly check for a return status. For example, the
- * following code traverses a stream of file names, selects one that has
- * not yet been processed, and then opens that file, returning an
+ * following code traverses a stream of file names, selects one that has not
+ * yet been processed, and then opens that file, returning an
* {@code Optional<FileInputStream>}:
*
* <pre>{@code
@@ -222,12 +229,12 @@
* {@code map} returns an {@code Optional<FileInputStream>} for the desired
* file if one exists.
*
- * @param <U> The type of the result of the mapping function
- * @param mapper a mapping function to apply to the value, if present
+ * @param mapper the mapping function to apply to a value, if present
+ * @param <U> The type of the value returned from the mapping function
* @return an {@code Optional} describing the result of applying a mapping
- * function to the value of this {@code Optional}, if a value is present,
- * otherwise an empty {@code Optional}
- * @throws NullPointerException if the mapping function is null
+ * function to the value of this {@code Optional}, if a value is
+ * present, otherwise an empty {@code Optional}
+ * @throws NullPointerException if the mapping function is {@code null}
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
@@ -239,21 +246,23 @@
}
/**
- * If a value is present, apply the provided {@code Optional}-bearing
- * mapping function to it, return that result, otherwise return an empty
- * {@code Optional}. This method is similar to {@link #map(Function)},
- * but the provided mapper is one whose result is already an {@code Optional},
- * and if invoked, {@code flatMap} does not wrap it with an additional
+ * If a value is present, returns the result of applying the given
+ * {@code Optional}-bearing mapping function to the value, otherwise returns
+ * an empty {@code Optional}.
+ *
+ * <p>This method is similar to {@link #map(Function)}, but the mapping
+ * function is one whose result is already an {@code Optional}, and if
+ * invoked, {@code flatMap} does not wrap it within an additional
* {@code Optional}.
*
- * @param <U> The type parameter to the {@code Optional} returned by
- * @param mapper a mapping function to apply to the value, if present
- * the mapping function
+ * @param <U> The type of value of the {@code Optional} returned by the
+ * mapping function
+ * @param mapper the mapping function to apply to a value, if present
* @return the result of applying an {@code Optional}-bearing mapping
- * function to the value of this {@code Optional}, if a value is present,
- * otherwise an empty {@code Optional}
- * @throws NullPointerException if the mapping function is null or returns
- * a null result
+ * function to the value of this {@code Optional}, if a value is
+ * present, otherwise an empty {@code Optional}
+ * @throws NullPointerException if the mapping function is {@code null} or
+ * returns a {@code null} result
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
@@ -265,19 +274,41 @@
}
/**
- * If a value is present return a sequential {@link Stream} containing only
- * that value, otherwise return an empty {@code Stream}.
+ * If a value is present, returns an {@code Optional} describing the value,
+ * otherwise returns an {@code Optional} produced by the supplying function.
*
- * @apiNote This method can be used to transform a {@code Stream} of
- * optional elements to a {@code Stream} of present value elements:
+ * @param supplier the supplying function that produces an {@code Optional}
+ * to be returned
+ * @return returns an {@code Optional} describing the value of this
+ * {@code Optional}, if a value is present, otherwise an
+ * {@code Optional} produced by the supplying function.
+ * @throws NullPointerException if the supplying function is {@code null} or
+ * produces a {@code null} result
+ * @since 9
+ */
+ public Optional<T> or(Supplier<Optional<T>> supplier) {
+ Objects.requireNonNull(supplier);
+ if (isPresent()) {
+ return this;
+ } else {
+ return Objects.requireNonNull(supplier.get());
+ }
+ }
+
+ /**
+ * If a value is present, returns a sequential {@link Stream} containing
+ * only that value, otherwise returns an empty {@code Stream}.
*
+ * @apiNote
+ * This method can be used to transform a {@code Stream} of optional
+ * elements to a {@code Stream} of present value elements:
* <pre>{@code
* Stream<Optional<T>> os = ..
* Stream<T> s = os.flatMap(Optional::stream)
* }</pre>
*
* @return the optional value as a {@code Stream}
- * @since 1.9
+ * @since 9
*/
public Stream<T> stream() {
if (!isPresent()) {
@@ -288,10 +319,11 @@
}
/**
- * Return the value if present, otherwise return {@code other}.
+ * If a value is present, returns the value, otherwise returns
+ * {@code other}.
*
- * @param other the value to be returned if there is no value present, may
- * be null
+ * @param other the value to be returned, if no value is present.
+ * May be {@code null}.
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
@@ -299,34 +331,35 @@
}
/**
- * Return the value if present, otherwise invoke {@code other} and return
- * the result of that invocation.
+ * If a value is present, returns the value, otherwise returns the result
+ * produced by the supplying function.
*
- * @param other a {@code Supplier} whose result is returned if no value
- * is present
- * @return the value if present otherwise the result of {@code other.get()}
- * @throws NullPointerException if value is not present and {@code other} is
- * null
+ * @param supplier the supplying function that produces a value to be returned
+ * @return the value, if present, otherwise the result produced by the
+ * supplying function
+ * @throws NullPointerException if no value is present and the supplying
+ * function is {@code null}
*/
- public T orElseGet(Supplier<? extends T> other) {
- return value != null ? value : other.get();
+ public T orElseGet(Supplier<? extends T> supplier) {
+ return value != null ? value : supplier.get();
}
/**
- * Return the contained value, if present, otherwise throw an exception
- * to be created by the provided supplier.
+ * If a value is present, returns the value, otherwise throws an exception
+ * produced by the exception supplying function.
*
- * @apiNote A method reference to the exception constructor with an empty
- * argument list can be used as the supplier. For example,
+ * @apiNote
+ * A method reference to the exception constructor with an empty argument
+ * list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
- * @param exceptionSupplier The supplier which will return the exception to
- * be thrown
- * @return the present value
- * @throws X if there is no value present
- * @throws NullPointerException if no value is present and
- * {@code exceptionSupplier} is null
+ * @param exceptionSupplier the supplying function that produces an
+ * exception to be thrown
+ * @return the value, if present
+ * @throws X if no value is present
+ * @throws NullPointerException if no value is present and the exception
+ * supplying function is {@code null}
*/
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
@@ -337,8 +370,8 @@
}
/**
- * Indicates whether some other object is "equal to" this Optional. The
- * other object is considered equal if:
+ * Indicates whether some other object is "equal to" this {@code Optional}.
+ * The other object is considered equal if:
* <ul>
* <li>it is also an {@code Optional} and;
* <li>both instances have no value present or;
@@ -347,7 +380,7 @@
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
- * otherwise {@code false}
+ * otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
@@ -364,10 +397,11 @@
}
/**
- * Returns the hash code value of the present value, if any, or 0 (zero) if
- * no value is present.
+ * Returns the hash code of the value, if present, otherwise {@code 0}
+ * (zero) if no value is present.
*
- * @return hash code value of the present value or 0 if no value is present
+ * @return hash code value of the present value or {@code 0} if no value is
+ * present
*/
@Override
public int hashCode() {
@@ -375,13 +409,14 @@
}
/**
- * Returns a non-empty string representation of this Optional suitable for
- * debugging. The exact presentation format is unspecified and may vary
- * between implementations and versions.
+ * Returns a non-empty string representation of this {@code Optional}
+ * suitable for debugging. The exact presentation format is unspecified and
+ * may vary between implementations and versions.
*
- * @implSpec If a value is present the result must include its string
- * representation in the result. Empty and present Optionals must be
- * unambiguously differentiable.
+ * @implSpec
+ * If a value is present the result must include its string representation
+ * in the result. Empty and present {@code Optional}s must be unambiguously
+ * differentiable.
*
* @return the string representation of this instance
*/
--- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Tue Oct 20 08:24:37 2015 -0700
@@ -30,15 +30,15 @@
import java.util.stream.DoubleStream;
/**
- * A container object which may or may not contain a {@code double} value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code getAsDouble()} will return the value.
+ * A container object which may or may not contain a {@code double} value. If a
+ * value is present, {@code isPresent()} returns {@code true} and
+ * {@code getAsDouble()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(double) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (perform an
- * action if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (performs
+ * an action if a value is present).
*
* <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
@@ -71,12 +71,13 @@
}
/**
- * Returns an empty {@code OptionalDouble} instance. No value is present for this
- * OptionalDouble.
+ * Returns an empty {@code OptionalDouble} instance. No value is present
+ * for this {@code OptionalDouble}.
*
- * @apiNote Though it may be tempting to do so, avoid testing if an object
- * is empty by comparing with {@code ==} against instances returned by
- * {@code Option.empty()}. There is no guarantee that it is a singleton.
+ * @apiNote
+ * Though it may be tempting to do so, avoid testing if an object is empty
+ * by comparing with {@code ==} against instances returned by
+ * {@code OptionalDouble.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @return an empty {@code OptionalDouble}.
@@ -86,9 +87,9 @@
}
/**
- * Construct an instance with the value present.
+ * Construct an instance with the described value.
*
- * @param value the double value to be present.
+ * @param value the double value to describe.
*/
private OptionalDouble(double value) {
this.isPresent = true;
@@ -96,9 +97,9 @@
}
/**
- * Return an {@code OptionalDouble} with the specified value present.
+ * Returns an {@code OptionalDouble} describing the given value.
*
- * @param value the value to be present
+ * @param value the value to describe
* @return an {@code OptionalDouble} with the value present
*/
public static OptionalDouble of(double value) {
@@ -106,12 +107,11 @@
}
/**
- * If a value is present in this {@code OptionalDouble}, returns the value,
- * otherwise throws {@code NoSuchElementException}.
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
*
- * @return the value held by this {@code OptionalDouble}
- * @throws NoSuchElementException if there is no value present
- *
+ * @return the value described by this {@code OptionalDouble}
+ * @throws NoSuchElementException if no value is present
* @see OptionalDouble#isPresent()
*/
public double getAsDouble() {
@@ -122,21 +122,21 @@
}
/**
- * Return {@code true} if there is a value present, otherwise {@code false}.
+ * If a value is present, returns {@code true}, otherwise {@code false}.
*
- * @return {@code true} if there is a value present, otherwise {@code false}
+ * @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise do nothing.
+ * If a value is present, performs the given action with the value,
+ * otherwise does nothing.
*
- * @param action the action to be performed if a value is present
- * @throws NullPointerException if a value is present and {@code action} is
- * null
+ * @param action the action to be performed, if a value is present
+ * @throws NullPointerException if value is present and the given action is
+ * {@code null}
*/
public void ifPresent(DoubleConsumer action) {
if (isPresent) {
@@ -145,15 +145,16 @@
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise perform the given empty-based action.
+ * If a value is present, performs the given action with the value,
+ * otherwise performs the given empty-based action.
*
- * @param action the action to be performed if a value is present
- * @param emptyAction the empty-based action to be performed if a value is
- * not present
- * @throws NullPointerException if a value is present and {@code action} is
- * null, or a value is not present and {@code emptyAction} is null.
- * @since 1.9
+ * @param action the action to be performed, if a value is present
+ * @param emptyAction the empty-based action to be performed, if no value is
+ * present
+ * @throws NullPointerException if a value is present and the given action
+ * is {@code null}, or no value is present and the given empty-based
+ * action is {@code null}.
+ * @since 9
*/
public void ifPresentOrElse(DoubleConsumer action, Runnable emptyAction) {
if (isPresent) {
@@ -164,19 +165,20 @@
}
/**
- * If a value is present return a sequential {@link DoubleStream} containing
- * only that value, otherwise return an empty {@code DoubleStream}.
+ * If a value is present, returns a sequential {@link DoubleStream}
+ * containing only that value, otherwise returns an empty
+ * {@code DoubleStream}.
*
- * @apiNote This method can be used to transform a {@code Stream} of
- * optional doubles to a {@code DoubleStream} of present doubles:
- *
+ * @apiNote
+ * This method can be used to transform a {@code Stream} of optional doubles
+ * to a {@code DoubleStream} of present doubles:
* <pre>{@code
* Stream<OptionalDouble> os = ..
* DoubleStream s = os.flatMapToDouble(OptionalDouble::stream)
* }</pre>
*
* @return the optional value as a {@code DoubleStream}
- * @since 1.9
+ * @since 9
*/
public DoubleStream stream() {
if (isPresent) {
@@ -187,9 +189,10 @@
}
/**
- * Return the value if present, otherwise return {@code other}.
+ * If a value is present, returns the value, otherwise returns
+ * {@code other}.
*
- * @param other the value to be returned if there is no value present
+ * @param other the value to be returned, if no value is present
* @return the value, if present, otherwise {@code other}
*/
public double orElse(double other) {
@@ -197,34 +200,35 @@
}
/**
- * Return the value if present, otherwise invoke {@code other} and return
- * the result of that invocation.
+ * If a value is present, returns the value, otherwise returns the result
+ * produced by the supplying function.
*
- * @param other a {@code DoubleSupplier} whose result is returned if no value
- * is present
- * @return the value if present otherwise the result of {@code other.getAsDouble()}
- * @throws NullPointerException if value is not present and {@code other} is
- * null
+ * @param supplier the supplying function that produces a value to be returned
+ * @return the value, if present, otherwise the result produced by the
+ * supplying function
+ * @throws NullPointerException if no value is present and the supplying
+ * function is {@code null}
*/
- public double orElseGet(DoubleSupplier other) {
- return isPresent ? value : other.getAsDouble();
+ public double orElseGet(DoubleSupplier supplier) {
+ return isPresent ? value : supplier.getAsDouble();
}
/**
- * Return the contained value, if present, otherwise throw an exception
- * to be created by the provided supplier.
+ * If a value is present, returns the value, otherwise throws an exception
+ * produced by the exception supplying function.
*
- * @apiNote A method reference to the exception constructor with an empty
- * argument list can be used as the supplier. For example,
+ * @apiNote
+ * A method reference to the exception constructor with an empty argument
+ * list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
- * @param exceptionSupplier The supplier which will return the exception to
- * be thrown
- * @return the present value
- * @throws X if there is no value present
- * @throws NullPointerException if no value is present and
- * {@code exceptionSupplier} is null
+ * @param exceptionSupplier the supplying function that produces an
+ * exception to be thrown
+ * @return the value, if present
+ * @throws X if no value is present
+ * @throws NullPointerException if no value is present and the exception
+ * supplying function is {@code null}
*/
public<X extends Throwable> double orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
@@ -235,17 +239,18 @@
}
/**
- * Indicates whether some other object is "equal to" this OptionalDouble. The
- * other object is considered equal if:
+ * Indicates whether some other object is "equal to" this
+ * {@code OptionalDouble}. The other object is considered equal if:
* <ul>
* <li>it is also an {@code OptionalDouble} and;
* <li>both instances have no value present or;
- * <li>the present values are "equal to" each other via {@code Double.compare() == 0}.
+ * <li>the present values are "equal to" each other via
+ * {@code Double.compare() == 0}.
* </ul>
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
- * otherwise {@code false}
+ * otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
@@ -264,10 +269,11 @@
}
/**
- * Returns the hash code value of the present value, if any, or 0 (zero) if
- * no value is present.
+ * Returns the hash code of the value, if present, otherwise {@code 0}
+ * (zero) if no value is present.
*
- * @return hash code value of the present value or 0 if no value is present
+ * @return hash code value of the present value or {@code 0} if no value is
+ * present
*/
@Override
public int hashCode() {
@@ -275,14 +281,13 @@
}
/**
- * {@inheritDoc}
+ * Returns a non-empty string representation of this {@code OptionalDouble}
+ * suitable for debugging. The exact presentation format is unspecified and
+ * may vary between implementations and versions.
*
- * Returns a non-empty string representation of this object suitable for
- * debugging. The exact presentation format is unspecified and may vary
- * between implementations and versions.
- *
- * @implSpec If a value is present the result must include its string
- * representation in the result. Empty and present instances must be
+ * @implSpec
+ * If a value is present the result must include its string representation
+ * in the result. Empty and present {@code OptionalDouble}s must be
* unambiguously differentiable.
*
* @return the string representation of this instance
--- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java Tue Oct 20 08:24:37 2015 -0700
@@ -30,15 +30,15 @@
import java.util.stream.IntStream;
/**
- * A container object which may or may not contain a {@code int} value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code getAsInt()} will return the value.
+ * A container object which may or may not contain an {@code int} value. If a
+ * value is present, {@code isPresent()} returns {@code true} and
+ * {@code getAsInt()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(int) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (perform an
- * action if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (performs an
+ * action if a value is present).
*
* <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
@@ -71,24 +71,25 @@
}
/**
- * Returns an empty {@code OptionalInt} instance. No value is present for this
- * OptionalInt.
+ * Returns an empty {@code OptionalInt} instance. No value is present for
+ * this {@code OptionalInt}.
*
- * @apiNote Though it may be tempting to do so, avoid testing if an object
- * is empty by comparing with {@code ==} against instances returned by
- * {@code Option.empty()}. There is no guarantee that it is a singleton.
+ * @apiNote
+ * Though it may be tempting to do so, avoid testing if an object is empty
+ * by comparing with {@code ==} against instances returned by
+ * {@code OptionalInt.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
- * @return an empty {@code OptionalInt}
+ * @return an empty {@code OptionalInt}
*/
public static OptionalInt empty() {
return EMPTY;
}
/**
- * Construct an instance with the value present.
+ * Construct an instance with the described value.
*
- * @param value the int value to be present
+ * @param value the int value to describe
*/
private OptionalInt(int value) {
this.isPresent = true;
@@ -96,9 +97,9 @@
}
/**
- * Return an {@code OptionalInt} with the specified value present.
+ * Returns an {@code OptionalInt} describing the given value.
*
- * @param value the value to be present
+ * @param value the value to describe
* @return an {@code OptionalInt} with the value present
*/
public static OptionalInt of(int value) {
@@ -106,12 +107,11 @@
}
/**
- * If a value is present in this {@code OptionalInt}, returns the value,
- * otherwise throws {@code NoSuchElementException}.
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
*
- * @return the value held by this {@code OptionalInt}
- * @throws NoSuchElementException if there is no value present
- *
+ * @return the value described by this {@code OptionalInt}
+ * @throws NoSuchElementException if no value is present
* @see OptionalInt#isPresent()
*/
public int getAsInt() {
@@ -122,21 +122,21 @@
}
/**
- * Return {@code true} if there is a value present, otherwise {@code false}.
+ * If a value is present, returns {@code true}, otherwise {@code false}.
*
- * @return {@code true} if there is a value present, otherwise {@code false}
+ * @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise do nothing.
+ * If a value is present, performs the given action with the value,
+ * otherwise does nothing.
*
- * @param action the action to be performed if a value is present
- * @throws NullPointerException if value is present and {@code action} is
- * null
+ * @param action the action to be performed, if a value is present
+ * @throws NullPointerException if value is present and the given action is
+ * {@code null}
*/
public void ifPresent(IntConsumer action) {
if (isPresent) {
@@ -145,15 +145,16 @@
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise perform the given empty-based action.
+ * If a value is present, performs the given action with the value,
+ * otherwise performs the given empty-based action.
*
- * @param action the action to be performed if a value is present
- * @param emptyAction the empty-based action to be performed if a value is
- * not present
- * @throws NullPointerException if a value is present and {@code action} is
- * null, or a value is not present and {@code emptyAction} is null.
- * @since 1.9
+ * @param action the action to be performed, if a value is present
+ * @param emptyAction the empty-based action to be performed, if no value is
+ * present
+ * @throws NullPointerException if a value is present and the given action
+ * is {@code null}, or no value is present and the given empty-based
+ * action is {@code null}.
+ * @since 9
*/
public void ifPresentOrElse(IntConsumer action, Runnable emptyAction) {
if (isPresent) {
@@ -164,19 +165,19 @@
}
/**
- * If a value is present return a sequential {@link IntStream} containing
- * only that value, otherwise return an empty {@code IntStream}.
+ * If a value is present, returns a sequential {@link IntStream} containing
+ * only that value, otherwise returns an empty {@code IntStream}.
*
- * @apiNote This method can be used to transform a {@code Stream} of
- * optional integers to an {@code IntStream} of present integers:
- *
+ * @apiNote
+ * This method can be used to transform a {@code Stream} of optional
+ * integers to an {@code IntStream} of present integers:
* <pre>{@code
* Stream<OptionalInt> os = ..
* IntStream s = os.flatMapToInt(OptionalInt::stream)
* }</pre>
*
* @return the optional value as an {@code IntStream}
- * @since 1.9
+ * @since 9
*/
public IntStream stream() {
if (isPresent) {
@@ -187,9 +188,10 @@
}
/**
- * Return the value if present, otherwise return {@code other}.
+ * If a value is present, returns the value, otherwise returns
+ * {@code other}.
*
- * @param other the value to be returned if there is no value present
+ * @param other the value to be returned, if no value is present
* @return the value, if present, otherwise {@code other}
*/
public int orElse(int other) {
@@ -197,34 +199,35 @@
}
/**
- * Return the value if present, otherwise invoke {@code other} and return
- * the result of that invocation.
+ * If a value is present, returns the value, otherwise returns the result
+ * produced by the supplying function.
*
- * @param other a {@code IntSupplier} whose result is returned if no value
- * is present
- * @return the value if present otherwise the result of {@code other.getAsInt()}
- * @throws NullPointerException if value is not present and {@code other} is
- * null
+ * @param supplier the supplying function that produces a value to be returned
+ * @return the value, if present, otherwise the result produced by the
+ * supplying function
+ * @throws NullPointerException if no value is present and the supplying
+ * function is {@code null}
*/
- public int orElseGet(IntSupplier other) {
- return isPresent ? value : other.getAsInt();
+ public int orElseGet(IntSupplier supplier) {
+ return isPresent ? value : supplier.getAsInt();
}
/**
- * Return the contained value, if present, otherwise throw an exception
- * to be created by the provided supplier.
+ * If a value is present, returns the value, otherwise throws an exception
+ * produced by the exception supplying function.
*
- * @apiNote A method reference to the exception constructor with an empty
- * argument list can be used as the supplier. For example,
+ * @apiNote
+ * A method reference to the exception constructor with an empty argument
+ * list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
- * @param exceptionSupplier The supplier which will return the exception to
- * be thrown
- * @return the present value
- * @throws X if there is no value present
- * @throws NullPointerException if no value is present and
- * {@code exceptionSupplier} is null
+ * @param exceptionSupplier the supplying function that produces an
+ * exception to be thrown
+ * @return the value, if present
+ * @throws X if no value is present
+ * @throws NullPointerException if no value is present and the exception
+ * supplying function is {@code null}
*/
public<X extends Throwable> int orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
@@ -235,8 +238,8 @@
}
/**
- * Indicates whether some other object is "equal to" this OptionalInt. The
- * other object is considered equal if:
+ * Indicates whether some other object is "equal to" this
+ * {@code OptionalInt}. The other object is considered equal if:
* <ul>
* <li>it is also an {@code OptionalInt} and;
* <li>both instances have no value present or;
@@ -245,7 +248,7 @@
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
- * otherwise {@code false}
+ * otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
@@ -264,10 +267,11 @@
}
/**
- * Returns the hash code value of the present value, if any, or 0 (zero) if
- * no value is present.
+ * Returns the hash code of the value, if present, otherwise {@code 0}
+ * (zero) if no value is present.
*
- * @return hash code value of the present value or 0 if no value is present
+ * @return hash code value of the present value or {@code 0} if no value is
+ * present
*/
@Override
public int hashCode() {
@@ -275,14 +279,13 @@
}
/**
- * {@inheritDoc}
+ * Returns a non-empty string representation of this {@code OptionalInt}
+ * suitable for debugging. The exact presentation format is unspecified and
+ * may vary between implementations and versions.
*
- * Returns a non-empty string representation of this object suitable for
- * debugging. The exact presentation format is unspecified and may vary
- * between implementations and versions.
- *
- * @implSpec If a value is present the result must include its string
- * representation in the result. Empty and present instances must be
+ * @implSpec
+ * If a value is present the result must include its string representation
+ * in the result. Empty and present {@code OptionalInt}s must be
* unambiguously differentiable.
*
* @return the string representation of this instance
--- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java Tue Oct 20 08:24:37 2015 -0700
@@ -30,15 +30,15 @@
import java.util.stream.LongStream;
/**
- * A container object which may or may not contain a {@code long} value.
- * If a value is present, {@code isPresent()} will return {@code true} and
- * {@code getAsLong()} will return the value.
+ * A container object which may or may not contain a {@code long} value. If a
+ * value is present, {@code isPresent()} returns {@code true} and
+ * {@code getAsLong()} returns the value.
*
* <p>Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(long) orElse()}
- * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (perform an
- * action if the value is present).
+ * (returns a default value if no value is present) and
+ * {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (performs an
+ * action if a value is present).
*
* <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
* class; use of identity-sensitive operations (including reference equality
@@ -71,24 +71,25 @@
}
/**
- * Returns an empty {@code OptionalLong} instance. No value is present for this
- * OptionalLong.
+ * Returns an empty {@code OptionalLong} instance. No value is present for
+ * this {@code OptionalLong}.
*
- * @apiNote Though it may be tempting to do so, avoid testing if an object
- * is empty by comparing with {@code ==} against instances returned by
- * {@code Option.empty()}. There is no guarantee that it is a singleton.
+ * @apiNote
+ * Though it may be tempting to do so, avoid testing if an object is empty
+ * by comparing with {@code ==} against instances returned by
+ * {@code OptionalLong.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
- * @return an empty {@code OptionalLong}.
+ * @return an empty {@code OptionalLong}.
*/
public static OptionalLong empty() {
return EMPTY;
}
/**
- * Construct an instance with the value present.
+ * Construct an instance with the described value.
*
- * @param value the long value to be present
+ * @param value the long value to describe
*/
private OptionalLong(long value) {
this.isPresent = true;
@@ -96,9 +97,9 @@
}
/**
- * Return an {@code OptionalLong} with the specified value present.
+ * Returns an {@code OptionalLong} describing the given value.
*
- * @param value the value to be present
+ * @param value the value to describe
* @return an {@code OptionalLong} with the value present
*/
public static OptionalLong of(long value) {
@@ -106,12 +107,11 @@
}
/**
- * If a value is present in this {@code OptionalLong}, returns the value,
- * otherwise throws {@code NoSuchElementException}.
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
*
- * @return the value held by this {@code OptionalLong}
- * @throws NoSuchElementException if there is no value present
- *
+ * @return the value described by this {@code OptionalLong}
+ * @throws NoSuchElementException if no value is present
* @see OptionalLong#isPresent()
*/
public long getAsLong() {
@@ -122,21 +122,21 @@
}
/**
- * Return {@code true} if there is a value present, otherwise {@code false}.
+ * If a value is present, returns {@code true}, otherwise {@code false}.
*
- * @return {@code true} if there is a value present, otherwise {@code false}
+ * @return {@code true} if a value is present, otherwise {@code false}
*/
public boolean isPresent() {
return isPresent;
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise do nothing.
+ * If a value is present, performs the given action with the value,
+ * otherwise does nothing.
*
- * @param action the action to be performed if a value is present
- * @throws NullPointerException if a value is present and {@code action} is
- * null
+ * @param action the action to be performed, if a value is present
+ * @throws NullPointerException if value is present and the given action is
+ * {@code null}
*/
public void ifPresent(LongConsumer action) {
if (isPresent) {
@@ -145,15 +145,16 @@
}
/**
- * If a value is present, perform the given action with the value,
- * otherwise perform the given empty-based action.
+ * If a value is present, performs the given action with the value,
+ * otherwise performs the given empty-based action.
*
- * @param action the action to be performed if a value is present
- * @param emptyAction the empty-based action to be performed if a value is
- * not present
- * @throws NullPointerException if a value is present and {@code action} is
- * null, or a value is not present and {@code emptyAction} is null.
- * @since 1.9
+ * @param action the action to be performed, if a value is present
+ * @param emptyAction the empty-based action to be performed, if no value is
+ * present
+ * @throws NullPointerException if a value is present and the given action
+ * is {@code null}, or no value is present and the given empty-based
+ * action is {@code null}.
+ * @since 9
*/
public void ifPresentOrElse(LongConsumer action, Runnable emptyAction) {
if (isPresent) {
@@ -164,19 +165,19 @@
}
/**
- * If a value is present return a sequential {@link LongStream} containing
- * only that value, otherwise return an empty {@code LongStream}.
+ * If a value is present, returns a sequential {@link LongStream} containing
+ * only that value, otherwise returns an empty {@code LongStream}.
*
- * @apiNote This method can be used to transform a {@code Stream} of
- * optional longs to a {@code LongStream} of present longs:
- *
+ * @apiNote
+ * This method can be used to transform a {@code Stream} of optional longs
+ * to an {@code LongStream} of present longs:
* <pre>{@code
* Stream<OptionalLong> os = ..
* LongStream s = os.flatMapToLong(OptionalLong::stream)
* }</pre>
*
- * @return the optional value as a {@code LongStream}
- * @since 1.9
+ * @return the optional value as an {@code LongStream}
+ * @since 9
*/
public LongStream stream() {
if (isPresent) {
@@ -187,9 +188,10 @@
}
/**
- * Return the value if present, otherwise return {@code other}.
+ * If a value is present, returns the value, otherwise returns
+ * {@code other}.
*
- * @param other the value to be returned if there is no value present
+ * @param other the value to be returned, if no value is present
* @return the value, if present, otherwise {@code other}
*/
public long orElse(long other) {
@@ -197,34 +199,35 @@
}
/**
- * Return the value if present, otherwise invoke {@code other} and return
- * the result of that invocation.
+ * If a value is present, returns the value, otherwise returns the result
+ * produced by the supplying function.
*
- * @param other a {@code LongSupplier} whose result is returned if no value
- * is present
- * @return the value if present otherwise the result of {@code other.getAsLong()}
- * @throws NullPointerException if value is not present and {@code other} is
- * null
+ * @param supplier the supplying function that produces a value to be returned
+ * @return the value, if present, otherwise the result produced by the
+ * supplying function
+ * @throws NullPointerException if no value is present and the supplying
+ * function is {@code null}
*/
- public long orElseGet(LongSupplier other) {
- return isPresent ? value : other.getAsLong();
+ public long orElseGet(LongSupplier supplier) {
+ return isPresent ? value : supplier.getAsLong();
}
/**
- * Return the contained value, if present, otherwise throw an exception
- * to be created by the provided supplier.
+ * If a value is present, returns the value, otherwise throws an exception
+ * produced by the exception supplying function.
*
- * @apiNote A method reference to the exception constructor with an empty
- * argument list can be used as the supplier. For example,
+ * @apiNote
+ * A method reference to the exception constructor with an empty argument
+ * list can be used as the supplier. For example,
* {@code IllegalStateException::new}
*
* @param <X> Type of the exception to be thrown
- * @param exceptionSupplier The supplier which will return the exception to
- * be thrown
- * @return the present value
- * @throws X if there is no value present
- * @throws NullPointerException if no value is present and
- * {@code exceptionSupplier} is null
+ * @param exceptionSupplier the supplying function that produces an
+ * exception to be thrown
+ * @return the value, if present
+ * @throws X if no value is present
+ * @throws NullPointerException if no value is present and the exception
+ * supplying function is {@code null}
*/
public<X extends Throwable> long orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
@@ -235,8 +238,8 @@
}
/**
- * Indicates whether some other object is "equal to" this OptionalLong. The
- * other object is considered equal if:
+ * Indicates whether some other object is "equal to" this
+ * {@code OptionalLong}. The other object is considered equal if:
* <ul>
* <li>it is also an {@code OptionalLong} and;
* <li>both instances have no value present or;
@@ -245,7 +248,7 @@
*
* @param obj an object to be tested for equality
* @return {@code true} if the other object is "equal to" this object
- * otherwise {@code false}
+ * otherwise {@code false}
*/
@Override
public boolean equals(Object obj) {
@@ -264,10 +267,11 @@
}
/**
- * Returns the hash code value of the present value, if any, or 0 (zero) if
- * no value is present.
+ * Returns the hash code of the value, if present, otherwise {@code 0}
+ * (zero) if no value is present.
*
- * @return hash code value of the present value or 0 if no value is present
+ * @return hash code value of the present value or {@code 0} if no value is
+ * present
*/
@Override
public int hashCode() {
@@ -275,14 +279,13 @@
}
/**
- * {@inheritDoc}
+ * Returns a non-empty string representation of this {@code OptionalLong}
+ * suitable for debugging. The exact presentation format is unspecified and
+ * may vary between implementations and versions.
*
- * Returns a non-empty string representation of this object suitable for
- * debugging. The exact presentation format is unspecified and may vary
- * between implementations and versions.
- *
- * @implSpec If a value is present the result must include its string
- * representation in the result. Empty and present instances must be
+ * @implSpec
+ * If a value is present the result must include its string representation
+ * in the result. Empty and present {@code OptionalLong}s must be
* unambiguously differentiable.
*
* @return the string representation of this instance
--- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -77,7 +77,7 @@
*
* @since 1.5
* @author Josh Bloch, Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class PriorityQueue<E> extends AbstractQueue<E>
implements java.io.Serializable {
@@ -99,7 +99,7 @@
/**
* The number of elements in the priority queue.
*/
- private int size = 0;
+ int size;
/**
* The comparator, or null if priority queue uses elements'
@@ -111,7 +111,7 @@
* The number of times this priority queue has been
* <i>structurally modified</i>. See AbstractList for gory details.
*/
- transient int modCount = 0; // non-private to simplify nested class access
+ transient int modCount; // non-private to simplify nested class access
/**
* Creates a {@code PriorityQueue} with the default initial
@@ -448,7 +448,7 @@
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -489,7 +489,7 @@
* Index (into queue array) of element to be returned by
* subsequent call to next.
*/
- private int cursor = 0;
+ private int cursor;
/**
* Index of element returned by most recent call to next,
@@ -509,13 +509,13 @@
* We expect that most iterations, even those involving removals,
* will not need to store elements in this field.
*/
- private ArrayDeque<E> forgetMeNot = null;
+ private ArrayDeque<E> forgetMeNot;
/**
* Element returned by the most recent call to next iff that
* element was drawn from the forgetMeNot list.
*/
- private E lastRetElt = null;
+ private E lastRetElt;
/**
* The modCount value that the iterator believes that the backing
@@ -609,7 +609,7 @@
* avoid missing traversing elements.
*/
@SuppressWarnings("unchecked")
- private E removeAt(int i) {
+ E removeAt(int i) {
// assert i >= 0 && i < size;
modCount++;
int s = --size;
@@ -756,6 +756,7 @@
* emitted (int), followed by all of its elements
* (each an {@code Object}) in the proper order.
* @param s the stream
+ * @throws java.io.IOException if an I/O error occurs
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -775,6 +776,9 @@
* (that is, deserializes it).
*
* @param s the stream
+ * @throws ClassNotFoundException if the class of a serialized object
+ * could not be found
+ * @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -822,9 +826,9 @@
private int fence; // -1 until first use
private int expectedModCount; // initialized when fence set
- /** Creates new spliterator covering the given range */
+ /** Creates new spliterator covering the given range. */
PriorityQueueSpliterator(PriorityQueue<E> pq, int origin, int fence,
- int expectedModCount) {
+ int expectedModCount) {
this.pq = pq;
this.index = origin;
this.fence = fence;
--- a/jdk/src/java.base/share/classes/java/util/Queue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Queue.java Tue Oct 20 08:24:37 2015 -0700
@@ -139,7 +139,7 @@
* @see java.util.concurrent.PriorityBlockingQueue
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public interface Queue<E> extends Collection<E> {
/**
--- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java Tue Oct 20 08:24:37 2015 -0700
@@ -26,13 +26,13 @@
package java.util;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
import java.util.function.LongConsumer;
-import java.util.function.DoubleConsumer;
-import java.util.stream.StreamSupport;
+import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
-import java.util.stream.DoubleStream;
+import java.util.stream.StreamSupport;
/**
* A generator of uniform pseudorandom values applicable for use in
@@ -52,15 +52,15 @@
* types and ranges, but similar properties are expected to hold, at
* least approximately, for others as well. The <em>period</em>
* (length of any series of generated values before it repeats) is at
- * least 2<sup>64</sup>. </li>
+ * least 2<sup>64</sup>.
*
- * <li> Method {@link #split} constructs and returns a new
+ * <li>Method {@link #split} constructs and returns a new
* SplittableRandom instance that shares no mutable state with the
* current instance. However, with very high probability, the
* values collectively generated by the two objects have the same
* statistical properties as if the same quantity of values were
* generated by a single thread using a single {@code
- * SplittableRandom} object. </li>
+ * SplittableRandom} object.
*
* <li>Instances of SplittableRandom are <em>not</em> thread-safe.
* They are designed to be split, not shared, across threads. For
@@ -71,7 +71,7 @@
*
* <li>This class provides additional methods for generating random
* streams, that employ the above techniques when used in {@code
- * stream.parallel()} mode.</li>
+ * stream.parallel()} mode.
*
* </ul>
*
@@ -240,9 +240,9 @@
}
// IllegalArgumentException messages
- static final String BadBound = "bound must be positive";
- static final String BadRange = "bound must be greater than origin";
- static final String BadSize = "size must be non-negative";
+ static final String BAD_BOUND = "bound must be positive";
+ static final String BAD_RANGE = "bound must be greater than origin";
+ static final String BAD_SIZE = "size must be non-negative";
/*
* Internal versions of nextX methods used by streams, as well as
@@ -416,7 +416,7 @@
*/
public int nextInt(int bound) {
if (bound <= 0)
- throw new IllegalArgumentException(BadBound);
+ throw new IllegalArgumentException(BAD_BOUND);
// Specialize internalNextInt for origin 0
int r = mix32(nextSeed());
int m = bound - 1;
@@ -444,7 +444,7 @@
*/
public int nextInt(int origin, int bound) {
if (origin >= bound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return internalNextInt(origin, bound);
}
@@ -468,7 +468,7 @@
*/
public long nextLong(long bound) {
if (bound <= 0)
- throw new IllegalArgumentException(BadBound);
+ throw new IllegalArgumentException(BAD_BOUND);
// Specialize internalNextLong for origin 0
long r = mix64(nextSeed());
long m = bound - 1;
@@ -496,7 +496,7 @@
*/
public long nextLong(long origin, long bound) {
if (origin >= bound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return internalNextLong(origin, bound);
}
@@ -522,7 +522,7 @@
*/
public double nextDouble(double bound) {
if (!(bound > 0.0))
- throw new IllegalArgumentException(BadBound);
+ throw new IllegalArgumentException(BAD_BOUND);
double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
return (result < bound) ? result : // correct for rounding
Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
@@ -541,7 +541,7 @@
*/
public double nextDouble(double origin, double bound) {
if (!(origin < bound))
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return internalNextDouble(origin, bound);
}
@@ -569,7 +569,7 @@
*/
public IntStream ints(long streamSize) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, Integer.MAX_VALUE, 0),
@@ -610,9 +610,9 @@
public IntStream ints(long streamSize, int randomNumberOrigin,
int randomNumberBound) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -636,7 +636,7 @@
*/
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.intStream
(new RandomIntsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -655,7 +655,7 @@
*/
public LongStream longs(long streamSize) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, Long.MAX_VALUE, 0L),
@@ -696,9 +696,9 @@
public LongStream longs(long streamSize, long randomNumberOrigin,
long randomNumberBound) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -722,7 +722,7 @@
*/
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.longStream
(new RandomLongsSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -741,7 +741,7 @@
*/
public DoubleStream doubles(long streamSize) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, Double.MAX_VALUE, 0.0),
@@ -784,9 +784,9 @@
public DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
if (!(randomNumberOrigin < randomNumberBound))
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -810,7 +810,7 @@
*/
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
if (!(randomNumberOrigin < randomNumberBound))
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(this, 0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -825,7 +825,8 @@
* approach. The long and double versions of this class are
* identical except for types.
*/
- static final class RandomIntsSpliterator implements Spliterator.OfInt {
+ private static final class RandomIntsSpliterator
+ implements Spliterator.OfInt {
final SplittableRandom rng;
long index;
final long fence;
@@ -880,7 +881,8 @@
/**
* Spliterator for long streams.
*/
- static final class RandomLongsSpliterator implements Spliterator.OfLong {
+ private static final class RandomLongsSpliterator
+ implements Spliterator.OfLong {
final SplittableRandom rng;
long index;
final long fence;
@@ -936,7 +938,8 @@
/**
* Spliterator for double streams.
*/
- static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
+ private static final class RandomDoublesSpliterator
+ implements Spliterator.OfDouble {
final SplittableRandom rng;
long index;
final long fence;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,7 +34,13 @@
*/
package java.util.concurrent;
-import java.util.*;
+
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
/**
* Provides default implementations of {@link ExecutorService}
@@ -51,7 +57,7 @@
* <p><b>Extension example</b>. Here is a sketch of a class
* that customizes {@link ThreadPoolExecutor} to use
* a {@code CustomTask} class instead of the default {@code FutureTask}:
- * <pre> {@code
+ * <pre> {@code
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
*
* static class CustomTask<V> implements RunnableFuture<V> {...}
@@ -146,7 +152,7 @@
int ntasks = tasks.size();
if (ntasks == 0)
throw new IllegalArgumentException();
- ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
+ ArrayList<Future<T>> futures = new ArrayList<>(ntasks);
ExecutorCompletionService<T> ecs =
new ExecutorCompletionService<T>(this);
@@ -179,7 +185,7 @@
else if (active == 0)
break;
else if (timed) {
- f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
+ f = ecs.poll(nanos, NANOSECONDS);
if (f == null)
throw new TimeoutException();
nanos = deadline - System.nanoTime();
@@ -204,8 +210,7 @@
throw ee;
} finally {
- for (int i = 0, size = futures.size(); i < size; i++)
- futures.get(i).cancel(true);
+ cancelAll(futures);
}
}
@@ -229,8 +234,7 @@
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
- ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
- boolean done = false;
+ ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
try {
for (Callable<T> t : tasks) {
RunnableFuture<T> f = newTaskFor(t);
@@ -240,19 +244,15 @@
for (int i = 0, size = futures.size(); i < size; i++) {
Future<T> f = futures.get(i);
if (!f.isDone()) {
- try {
- f.get();
- } catch (CancellationException ignore) {
- } catch (ExecutionException ignore) {
- }
+ try { f.get(); }
+ catch (CancellationException ignore) {}
+ catch (ExecutionException ignore) {}
}
}
- done = true;
return futures;
- } finally {
- if (!done)
- for (int i = 0, size = futures.size(); i < size; i++)
- futures.get(i).cancel(true);
+ } catch (Throwable t) {
+ cancelAll(futures);
+ throw t;
}
}
@@ -261,47 +261,52 @@
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
- long nanos = unit.toNanos(timeout);
- ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
- boolean done = false;
- try {
+ final long nanos = unit.toNanos(timeout);
+ final long deadline = System.nanoTime() + nanos;
+ ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
+ int j = 0;
+ timedOut: try {
for (Callable<T> t : tasks)
futures.add(newTaskFor(t));
- final long deadline = System.nanoTime() + nanos;
final int size = futures.size();
// Interleave time checks and calls to execute in case
// executor doesn't have any/much parallelism.
for (int i = 0; i < size; i++) {
+ if (((i == 0) ? nanos : deadline - System.nanoTime()) <= 0L)
+ break timedOut;
execute((Runnable)futures.get(i));
- nanos = deadline - System.nanoTime();
- if (nanos <= 0L)
- return futures;
}
- for (int i = 0; i < size; i++) {
- Future<T> f = futures.get(i);
+ for (; j < size; j++) {
+ Future<T> f = futures.get(j);
if (!f.isDone()) {
- if (nanos <= 0L)
- return futures;
- try {
- f.get(nanos, TimeUnit.NANOSECONDS);
- } catch (CancellationException ignore) {
- } catch (ExecutionException ignore) {
- } catch (TimeoutException toe) {
- return futures;
+ try { f.get(deadline - System.nanoTime(), NANOSECONDS); }
+ catch (CancellationException ignore) {}
+ catch (ExecutionException ignore) {}
+ catch (TimeoutException timedOut) {
+ break timedOut;
}
- nanos = deadline - System.nanoTime();
}
}
- done = true;
return futures;
- } finally {
- if (!done)
- for (int i = 0, size = futures.size(); i < size; i++)
- futures.get(i).cancel(true);
+ } catch (Throwable t) {
+ cancelAll(futures);
+ throw t;
}
+ // Timed out before all the tasks could be completed; cancel remaining
+ cancelAll(futures, j);
+ return futures;
}
+ private static <T> void cancelAll(ArrayList<Future<T>> futures) {
+ cancelAll(futures, 0);
+ }
+
+ /** Cancels all futures with index at least j. */
+ private static <T> void cancelAll(ArrayList<Future<T>> futures, int j) {
+ for (int size = futures.size(); j < size; j++)
+ futures.get(j).cancel(true);
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ArrayBlockingQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,15 +34,18 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
+
+import java.lang.ref.WeakReference;
import java.util.AbstractQueue;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.Spliterator;
import java.util.Spliterators;
-import java.util.Spliterator;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
/**
* A bounded {@linkplain BlockingQueue blocking queue} backed by an
@@ -77,7 +80,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
@@ -121,12 +124,12 @@
* are known not to be any. Allows queue operations to update
* iterator state.
*/
- transient Itrs itrs = null;
+ transient Itrs itrs;
// Internal helper methods
/**
- * Circularly decrement i.
+ * Circularly decrements array index i.
*/
final int dec(int i) {
return ((i == 0) ? items.length : i) - 1;
@@ -141,16 +144,6 @@
}
/**
- * Throws NullPointerException if argument is null.
- *
- * @param v the element
- */
- private static void checkNotNull(Object v) {
- if (v == null)
- throw new NullPointerException();
- }
-
- /**
* Inserts element at current put position, advances, and signals.
* Call only when holding lock.
*/
@@ -159,8 +152,7 @@
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;
- if (++putIndex == items.length)
- putIndex = 0;
+ if (++putIndex == items.length) putIndex = 0;
count++;
notEmpty.signal();
}
@@ -176,8 +168,7 @@
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
- if (++takeIndex == items.length)
- takeIndex = 0;
+ if (++takeIndex == items.length) takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
@@ -198,8 +189,7 @@
if (removeIndex == takeIndex) {
// removing front item; just advance
items[takeIndex] = null;
- if (++takeIndex == items.length)
- takeIndex = 0;
+ if (++takeIndex == items.length) takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
@@ -207,19 +197,15 @@
// an "interior" remove
// slide over all others up through putIndex.
- final int putIndex = this.putIndex;
- for (int i = removeIndex;;) {
- int next = i + 1;
- if (next == items.length)
- next = 0;
- if (next != putIndex) {
- items[i] = items[next];
- i = next;
- } else {
- items[i] = null;
- this.putIndex = i;
+ for (int i = removeIndex, putIndex = this.putIndex;;) {
+ int pred = i;
+ if (++i == items.length) i = 0;
+ if (i == putIndex) {
+ items[pred] = null;
+ this.putIndex = pred;
break;
}
+ items[pred] = items[i];
}
count--;
if (itrs != null)
@@ -283,10 +269,8 @@
try {
int i = 0;
try {
- for (E e : c) {
- checkNotNull(e);
- items[i++] = e;
- }
+ for (E e : c)
+ items[i++] = Objects.requireNonNull(e);
} catch (ArrayIndexOutOfBoundsException ex) {
throw new IllegalArgumentException();
}
@@ -322,7 +306,7 @@
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- checkNotNull(e);
+ Objects.requireNonNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -345,7 +329,7 @@
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
- checkNotNull(e);
+ Objects.requireNonNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
@@ -368,13 +352,13 @@
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
- checkNotNull(e);
+ Objects.requireNonNull(e);
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return false;
nanos = notFull.awaitNanos(nanos);
}
@@ -413,7 +397,7 @@
lock.lockInterruptibly();
try {
while (count == 0) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
@@ -492,11 +476,11 @@
*/
public boolean remove(Object o) {
if (o == null) return false;
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
@@ -504,8 +488,7 @@
removeAt(i);
return true;
}
- if (++i == items.length)
- i = 0;
+ if (++i == items.length) i = 0;
} while (i != putIndex);
}
return false;
@@ -524,18 +507,17 @@
*/
public boolean contains(Object o) {
if (o == null) return false;
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
if (o.equals(items[i]))
return true;
- if (++i == items.length)
- i = 0;
+ if (++i == items.length) i = 0;
} while (i != putIndex);
}
return false;
@@ -558,23 +540,18 @@
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
- Object[] a;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- final int count = this.count;
- a = new Object[count];
- int n = items.length - takeIndex;
- if (count <= n)
- System.arraycopy(items, takeIndex, a, 0, count);
- else {
- System.arraycopy(items, takeIndex, a, 0, n);
- System.arraycopy(items, 0, a, n, count - n);
- }
+ final Object[] items = this.items;
+ final int end = takeIndex + count;
+ final Object[] a = Arrays.copyOfRange(items, takeIndex, end);
+ if (end != putIndex)
+ System.arraycopy(items, 0, a, items.length - takeIndex, putIndex);
+ return a;
} finally {
lock.unlock();
}
- return a;
}
/**
@@ -598,7 +575,7 @@
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -614,53 +591,30 @@
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
+ final Object[] items = this.items;
final int count = this.count;
- final int len = a.length;
- if (len < count)
- a = (T[])java.lang.reflect.Array.newInstance(
- a.getClass().getComponentType(), count);
- int n = items.length - takeIndex;
- if (count <= n)
- System.arraycopy(items, takeIndex, a, 0, count);
- else {
- System.arraycopy(items, takeIndex, a, 0, n);
- System.arraycopy(items, 0, a, n, count - n);
+ final int firstLeg = Math.min(items.length - takeIndex, count);
+ if (a.length < count) {
+ a = (T[]) Arrays.copyOfRange(items, takeIndex, takeIndex + count,
+ a.getClass());
+ } else {
+ System.arraycopy(items, takeIndex, a, 0, firstLeg);
+ if (a.length > count)
+ a[count] = null;
}
- if (len > count)
- a[count] = null;
+ if (firstLeg < count)
+ System.arraycopy(items, 0, a, firstLeg, putIndex);
+ return a;
} finally {
lock.unlock();
}
- return a;
}
public String toString() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- int k = count;
- if (k == 0)
- return "[]";
-
- final Object[] items = this.items;
- StringBuilder sb = new StringBuilder();
- sb.append('[');
- for (int i = takeIndex; ; ) {
- Object e = items[i];
- sb.append(e == this ? "(this Collection)" : e);
- if (--k == 0)
- return sb.append(']').toString();
- sb.append(',').append(' ');
- if (++i == items.length)
- i = 0;
- }
- } finally {
- lock.unlock();
- }
+ return Helpers.collectionToString(this);
}
/**
@@ -668,18 +622,17 @@
* The queue will be empty after this call returns.
*/
public void clear() {
- final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int k = count;
if (k > 0) {
+ final Object[] items = this.items;
final int putIndex = this.putIndex;
int i = takeIndex;
do {
items[i] = null;
- if (++i == items.length)
- i = 0;
+ if (++i == items.length) i = 0;
} while (i != putIndex);
takeIndex = putIndex;
count = 0;
@@ -710,7 +663,7 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- checkNotNull(c);
+ Objects.requireNonNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
@@ -728,8 +681,7 @@
E x = (E) items[take];
c.add(x);
items[take] = null;
- if (++take == items.length)
- take = 0;
+ if (++take == items.length) take = 0;
i++;
}
return n;
@@ -832,13 +784,13 @@
}
/** Incremented whenever takeIndex wraps around to 0 */
- int cycles = 0;
+ int cycles;
/** Linked list of weak iterator references */
private Node head;
/** Used to expunge stale iterators */
- private Node sweeper = null;
+ private Node sweeper;
private static final int SHORT_SWEEP_PROBES = 4;
private static final int LONG_SWEEP_PROBES = 16;
@@ -1095,10 +1047,8 @@
private int incCursor(int index) {
// assert lock.getHoldCount() == 1;
- if (++index == items.length)
- index = 0;
- if (index == putIndex)
- index = NONE;
+ if (++index == items.length) index = 0;
+ if (index == putIndex) index = NONE;
return index;
}
@@ -1314,17 +1264,18 @@
if (isDetached())
return true;
- final int cycles = itrs.cycles;
final int takeIndex = ArrayBlockingQueue.this.takeIndex;
- final int prevCycles = this.prevCycles;
final int prevTakeIndex = this.prevTakeIndex;
final int len = items.length;
- int cycleDiff = cycles - prevCycles;
- if (removedIndex < takeIndex)
- cycleDiff++;
+ // distance from prevTakeIndex to removedIndex
final int removedDistance =
- (cycleDiff * len) + (removedIndex - prevTakeIndex);
- // assert removedDistance >= 0;
+ len * (itrs.cycles - this.prevCycles
+ + ((removedIndex < takeIndex) ? 1 : 0))
+ + (removedIndex - prevTakeIndex);
+ // assert itrs.cycles - this.prevCycles >= 0;
+ // assert itrs.cycles - this.prevCycles <= 1;
+ // assert removedDistance > 0;
+ // assert removedIndex != takeIndex;
int cursor = this.cursor;
if (cursor >= 0) {
int x = distance(cursor, prevTakeIndex, len);
@@ -1353,7 +1304,7 @@
else if (x > removedDistance)
this.nextIndex = nextIndex = dec(nextIndex);
}
- else if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
+ if (cursor < 0 && nextIndex < 0 && lastRet < 0) {
this.prevTakeIndex = DETACHED;
return true;
}
@@ -1410,8 +1361,9 @@
*/
public Spliterator<E> spliterator() {
return Spliterators.spliterator
- (this, Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT);
+ (this, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/BlockingDeque.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,7 +34,10 @@
*/
package java.util.concurrent;
-import java.util.*;
+
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
/**
* A {@link Deque} that additionally supports blocking operations that wait
@@ -195,7 +198,7 @@
*
* @since 1.6
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
*/
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {
/*
@@ -401,9 +404,9 @@
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean removeFirstOccurrence(Object o);
@@ -419,9 +422,9 @@
* @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean removeLastOccurrence(Object o);
@@ -596,9 +599,9 @@
* @return {@code true} if this deque changed as a result of the call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean remove(Object o);
@@ -611,18 +614,18 @@
* @return {@code true} if this deque contains the specified element
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
- public boolean contains(Object o);
+ boolean contains(Object o);
/**
* Returns the number of elements in this deque.
*
* @return the number of elements in this deque
*/
- public int size();
+ int size();
/**
* Returns an iterator over the elements in this deque in proper sequence.
--- a/jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/BlockingQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -127,7 +127,7 @@
* Usage example, based on a typical producer-consumer scenario.
* Note that a {@code BlockingQueue} can safely be used with multiple
* producers and multiple consumers.
- * <pre> {@code
+ * <pre> {@code
* class Producer implements Runnable {
* private final BlockingQueue queue;
* Producer(BlockingQueue q) { queue = q; }
@@ -175,7 +175,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public interface BlockingQueue<E> extends Queue<E> {
/**
@@ -303,9 +303,9 @@
* @return {@code true} if this queue changed as a result of the call
* @throws ClassCastException if the class of the specified element
* is incompatible with this queue
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean remove(Object o);
@@ -318,11 +318,11 @@
* @return {@code true} if this queue contains the specified element
* @throws ClassCastException if the class of the specified element
* is incompatible with this queue
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified element is null
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
- public boolean contains(Object o);
+ boolean contains(Object o);
/**
* Removes all available elements from this queue and adds them
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,23 +34,13 @@
*/
package java.util.concurrent;
-import java.util.function.Supplier;
-import java.util.function.Consumer;
+
+import java.util.concurrent.locks.LockSupport;
import java.util.function.BiConsumer;
-import java.util.function.Function;
import java.util.function.BiFunction;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.ForkJoinPool;
-import java.util.concurrent.ForkJoinTask;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CompletionException;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.locks.LockSupport;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
/**
* A {@link Future} that may be explicitly completed (setting its
@@ -71,19 +61,32 @@
* <li>Actions supplied for dependent completions of
* <em>non-async</em> methods may be performed by the thread that
* completes the current CompletableFuture, or by any other caller of
- * a completion method.</li>
+ * a completion method.
*
* <li>All <em>async</em> methods without an explicit Executor
* argument are performed using the {@link ForkJoinPool#commonPool()}
* (unless it does not support a parallelism level of at least two, in
- * which case, a new Thread is created to run each task). To simplify
- * monitoring, debugging, and tracking, all generated asynchronous
- * tasks are instances of the marker interface {@link
- * AsynchronousCompletionTask}. </li>
+ * which case, a new Thread is created to run each task). This may be
+ * overridden for non-static methods in subclasses by defining method
+ * {@link #defaultExecutor()}. To simplify monitoring, debugging,
+ * and tracking, all generated asynchronous tasks are instances of the
+ * marker interface {@link AsynchronousCompletionTask}. Operations
+ * with time-delays can use adapter methods defined in this class, for
+ * example: {@code supplyAsync(supplier, delayedExecutor(timeout,
+ * timeUnit))}. To support methods with delays and timeouts, this
+ * class maintains at most one daemon thread for triggering and
+ * cancelling actions, not for running them.
*
* <li>All CompletionStage methods are implemented independently of
* other public methods, so the behavior of one method is not impacted
- * by overrides of others in subclasses. </li> </ul>
+ * by overrides of others in subclasses.
+ *
+ * <li>All CompletionStage methods return CompletableFutures. To
+ * restrict usages to only those methods defined in interface
+ * CompletionStage, use method {@link #minimalCompletionStage}. Or to
+ * ensure only that clients do not themselves modify a future, use
+ * method {@link #copy}.
+ * </ul>
*
* <p>CompletableFuture also implements {@link Future} with the following
* policies: <ul>
@@ -94,7 +97,7 @@
* completion. Method {@link #cancel cancel} has the same effect as
* {@code completeExceptionally(new CancellationException())}. Method
* {@link #isCompletedExceptionally} can be used to determine if a
- * CompletableFuture completed in any exceptional fashion.</li>
+ * CompletableFuture completed in any exceptional fashion.
*
* <li>In case of exceptional completion with a CompletionException,
* methods {@link #get()} and {@link #get(long, TimeUnit)} throw an
@@ -102,10 +105,38 @@
* corresponding CompletionException. To simplify usage in most
* contexts, this class also defines methods {@link #join()} and
* {@link #getNow} that instead throw the CompletionException directly
- * in these cases.</li> </ul>
+ * in these cases.
+ * </ul>
+ *
+ * <p>Arguments used to pass a completion result (that is, for
+ * parameters of type {@code T}) for methods accepting them may be
+ * null, but passing a null value for any other parameter will result
+ * in a {@link NullPointerException} being thrown.
+ *
+ * <p>Subclasses of this class should normally override the "virtual
+ * constructor" method {@link #newIncompleteFuture}, which establishes
+ * the concrete type returned by CompletionStage methods. For example,
+ * here is a class that substitutes a different default Executor and
+ * disables the {@code obtrude} methods:
+ *
+ * <pre> {@code
+ * class MyCompletableFuture<T> extends CompletableFuture<T> {
+ * static final Executor myExecutor = ...;
+ * public MyCompletableFuture() { }
+ * public <U> CompletableFuture<U> newIncompleteFuture() {
+ * return new MyCompletableFuture<U>(); }
+ * public Executor defaultExecutor() {
+ * return myExecutor; }
+ * public void obtrudeValue(T value) {
+ * throw new UnsupportedOperationException(); }
+ * public void obtrudeException(Throwable ex) {
+ * throw new UnsupportedOperationException(); }
+ * }}</pre>
*
* @author Doug Lea
* @since 1.8
+ * @param <T> The result type returned by this future's {@code join}
+ * and {@code get} methods
*/
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
@@ -150,9 +181,7 @@
* fields for source(s), actions, and dependent. They are
* boringly similar, differing from others only with respect to
* underlying functional forms. We do this so that users don't
- * encounter layers of adaptors in common usages. We also
- * include "Relay" classes/methods that don't correspond to user
- * methods; they copy results from one stage to another.
+ * encounter layers of adapters in common usages.
*
* * Boolean CompletableFuture method x(...) (for example
* uniApply) takes all of the arguments needed to check that an
@@ -219,18 +248,18 @@
volatile Completion stack; // Top of Treiber stack of dependent actions
final boolean internalComplete(Object r) { // CAS from null to r
- return UNSAFE.compareAndSwapObject(this, RESULT, null, r);
+ return U.compareAndSwapObject(this, RESULT, null, r);
}
final boolean casStack(Completion cmp, Completion val) {
- return UNSAFE.compareAndSwapObject(this, STACK, cmp, val);
+ return U.compareAndSwapObject(this, STACK, cmp, val);
}
/** Returns true if successfully pushed c onto stack. */
final boolean tryPushStack(Completion c) {
Completion h = stack;
lazySetNext(c, h);
- return UNSAFE.compareAndSwapObject(this, STACK, h, c);
+ return U.compareAndSwapObject(this, STACK, h, c);
}
/** Unconditionally pushes c onto stack, retrying if necessary. */
@@ -250,8 +279,8 @@
/** Completes with the null value, unless already completed. */
final boolean completeNull() {
- return UNSAFE.compareAndSwapObject(this, RESULT, null,
- NIL);
+ return U.compareAndSwapObject(this, RESULT, null,
+ NIL);
}
/** Returns the encoding of the given non-exceptional value. */
@@ -261,8 +290,8 @@
/** Completes with a non-exceptional result, unless already completed. */
final boolean completeValue(T t) {
- return UNSAFE.compareAndSwapObject(this, RESULT, null,
- (t == null) ? NIL : t);
+ return U.compareAndSwapObject(this, RESULT, null,
+ (t == null) ? NIL : t);
}
/**
@@ -276,8 +305,8 @@
/** Completes with an exceptional result, unless already completed. */
final boolean completeThrowable(Throwable x) {
- return UNSAFE.compareAndSwapObject(this, RESULT, null,
- encodeThrowable(x));
+ return U.compareAndSwapObject(this, RESULT, null,
+ encodeThrowable(x));
}
/**
@@ -304,8 +333,8 @@
* existing CompletionException.
*/
final boolean completeThrowable(Throwable x, Object r) {
- return UNSAFE.compareAndSwapObject(this, RESULT, null,
- encodeThrowable(x, r));
+ return U.compareAndSwapObject(this, RESULT, null,
+ encodeThrowable(x, r));
}
/**
@@ -334,8 +363,8 @@
* If exceptional, r is first coerced to a CompletionException.
*/
final boolean completeRelay(Object r) {
- return UNSAFE.compareAndSwapObject(this, RESULT, null,
- encodeRelay(r));
+ return U.compareAndSwapObject(this, RESULT, null,
+ encodeRelay(r));
}
/**
@@ -390,14 +419,14 @@
public static interface AsynchronousCompletionTask {
}
- private static final boolean useCommonPool =
+ private static final boolean USE_COMMON_POOL =
(ForkJoinPool.getCommonPoolParallelism() > 1);
/**
* Default executor -- ForkJoinPool.commonPool() unless it cannot
* support parallelism.
*/
- private static final Executor asyncPool = useCommonPool ?
+ private static final Executor ASYNC_POOL = USE_COMMON_POOL ?
ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
/** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
@@ -407,11 +436,11 @@
/**
* Null-checks user executor argument, and translates uses of
- * commonPool to asyncPool in case parallelism disabled.
+ * commonPool to ASYNC_POOL in case parallelism disabled.
*/
static Executor screenExecutor(Executor e) {
- if (!useCommonPool && e == ForkJoinPool.commonPool())
- return asyncPool;
+ if (!USE_COMMON_POOL && e == ForkJoinPool.commonPool())
+ return ASYNC_POOL;
if (e == null) throw new NullPointerException();
return e;
}
@@ -421,6 +450,12 @@
static final int ASYNC = 1;
static final int NESTED = -1;
+ /**
+ * Spins before blocking in waitingGet
+ */
+ static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ?
+ 1 << 8 : 0);
+
/* ------------- Base Completion classes and operations -------------- */
@SuppressWarnings("serial")
@@ -440,13 +475,13 @@
abstract boolean isLive();
public final void run() { tryFire(ASYNC); }
- public final boolean exec() { tryFire(ASYNC); return true; }
+ public final boolean exec() { tryFire(ASYNC); return false; }
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) {}
}
static void lazySetNext(Completion c, Completion next) {
- UNSAFE.putOrderedObject(c, NEXT, next);
+ U.putOrderedObject(c, NEXT, next);
}
/**
@@ -610,7 +645,7 @@
private <V> CompletableFuture<V> uniApplyStage(
Executor e, Function<? super T,? extends V> f) {
if (f == null) throw new NullPointerException();
- CompletableFuture<V> d = new CompletableFuture<V>();
+ CompletableFuture<V> d = newIncompleteFuture();
if (e != null || !d.uniApply(this, f, null)) {
UniApply<T,V> c = new UniApply<T,V>(e, d, this, f);
push(c);
@@ -665,7 +700,7 @@
private CompletableFuture<Void> uniAcceptStage(Executor e,
Consumer<? super T> f) {
if (f == null) throw new NullPointerException();
- CompletableFuture<Void> d = new CompletableFuture<Void>();
+ CompletableFuture<Void> d = newIncompleteFuture();
if (e != null || !d.uniAccept(this, f, null)) {
UniAccept<T> c = new UniAccept<T>(e, d, this, f);
push(c);
@@ -713,7 +748,7 @@
private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
if (f == null) throw new NullPointerException();
- CompletableFuture<Void> d = new CompletableFuture<Void>();
+ CompletableFuture<Void> d = newIncompleteFuture();
if (e != null || !d.uniRun(this, f, null)) {
UniRun<T> c = new UniRun<T>(e, d, this, f);
push(c);
@@ -774,7 +809,7 @@
private CompletableFuture<T> uniWhenCompleteStage(
Executor e, BiConsumer<? super T, ? super Throwable> f) {
if (f == null) throw new NullPointerException();
- CompletableFuture<T> d = new CompletableFuture<T>();
+ CompletableFuture<T> d = newIncompleteFuture();
if (e != null || !d.uniWhenComplete(this, f, null)) {
UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f);
push(c);
@@ -830,7 +865,7 @@
private <V> CompletableFuture<V> uniHandleStage(
Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
if (f == null) throw new NullPointerException();
- CompletableFuture<V> d = new CompletableFuture<V>();
+ CompletableFuture<V> d = newIncompleteFuture();
if (e != null || !d.uniHandle(this, f, null)) {
UniHandle<T,V> c = new UniHandle<T,V>(e, d, this, f);
push(c);
@@ -880,7 +915,7 @@
private CompletableFuture<T> uniExceptionallyStage(
Function<Throwable, ? extends T> f) {
if (f == null) throw new NullPointerException();
- CompletableFuture<T> d = new CompletableFuture<T>();
+ CompletableFuture<T> d = newIncompleteFuture();
if (!d.uniExceptionally(this, f, null)) {
UniExceptionally<T> c = new UniExceptionally<T>(d, this, f);
push(c);
@@ -912,6 +947,30 @@
return true;
}
+ private CompletableFuture<T> uniCopyStage() {
+ Object r;
+ CompletableFuture<T> d = newIncompleteFuture();
+ if ((r = result) != null)
+ d.completeRelay(r);
+ else {
+ UniRelay<T> c = new UniRelay<T>(d, this);
+ push(c);
+ c.tryFire(SYNC);
+ }
+ return d;
+ }
+
+ private MinimalStage<T> uniAsMinimalStage() {
+ Object r;
+ if ((r = result) != null)
+ return new MinimalStage<T>(encodeRelay(r));
+ MinimalStage<T> d = new MinimalStage<T>();
+ UniRelay<T> c = new UniRelay<T>(d, this);
+ push(c);
+ c.tryFire(SYNC);
+ return d;
+ }
+
@SuppressWarnings("serial")
static final class UniCompose<T,V> extends UniCompletion<T,V> {
Function<? super T, ? extends CompletionStage<V>> fn;
@@ -967,31 +1026,32 @@
private <V> CompletableFuture<V> uniComposeStage(
Executor e, Function<? super T, ? extends CompletionStage<V>> f) {
if (f == null) throw new NullPointerException();
- Object r; Throwable x;
+ Object r, s; Throwable x;
+ CompletableFuture<V> d = newIncompleteFuture();
if (e == null && (r = result) != null) {
- // try to return function result directly
if (r instanceof AltResult) {
if ((x = ((AltResult)r).ex) != null) {
- return new CompletableFuture<V>(encodeThrowable(x, r));
+ d.result = encodeThrowable(x, r);
+ return d;
}
r = null;
}
try {
@SuppressWarnings("unchecked") T t = (T) r;
CompletableFuture<V> g = f.apply(t).toCompletableFuture();
- Object s = g.result;
- if (s != null)
- return new CompletableFuture<V>(encodeRelay(s));
- CompletableFuture<V> d = new CompletableFuture<V>();
- UniRelay<V> copy = new UniRelay<V>(d, g);
- g.push(copy);
- copy.tryFire(SYNC);
+ if ((s = g.result) != null)
+ d.completeRelay(s);
+ else {
+ UniRelay<V> c = new UniRelay<V>(d, g);
+ g.push(c);
+ c.tryFire(SYNC);
+ }
return d;
} catch (Throwable ex) {
- return new CompletableFuture<V>(encodeThrowable(ex));
+ d.result = encodeThrowable(ex);
+ return d;
}
}
- CompletableFuture<V> d = new CompletableFuture<V>();
UniCompose<T,V> c = new UniCompose<T,V>(e, d, this, f);
push(c);
c.tryFire(SYNC);
@@ -1116,7 +1176,7 @@
CompletableFuture<U> b;
if (f == null || (b = o.toCompletableFuture()) == null)
throw new NullPointerException();
- CompletableFuture<V> d = new CompletableFuture<V>();
+ CompletableFuture<V> d = newIncompleteFuture();
if (e != null || !d.biApply(this, b, f, null)) {
BiApply<T,U,V> c = new BiApply<T,U,V>(e, d, this, b, f);
bipush(b, c);
@@ -1188,7 +1248,7 @@
CompletableFuture<U> b;
if (f == null || (b = o.toCompletableFuture()) == null)
throw new NullPointerException();
- CompletableFuture<Void> d = new CompletableFuture<Void>();
+ CompletableFuture<Void> d = newIncompleteFuture();
if (e != null || !d.biAccept(this, b, f, null)) {
BiAccept<T,U> c = new BiAccept<T,U>(e, d, this, b, f);
bipush(b, c);
@@ -1247,7 +1307,7 @@
CompletableFuture<?> b;
if (f == null || (b = o.toCompletableFuture()) == null)
throw new NullPointerException();
- CompletableFuture<Void> d = new CompletableFuture<Void>();
+ CompletableFuture<Void> d = newIncompleteFuture();
if (e != null || !d.biRun(this, b, f, null)) {
BiRun<T,?> c = new BiRun<>(e, d, this, b, f);
bipush(b, c);
@@ -1302,7 +1362,7 @@
if ((a = (lo == mid ? cfs[lo] :
andTree(cfs, lo, mid))) == null ||
(b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
- andTree(cfs, mid+1, hi))) == null)
+ andTree(cfs, mid+1, hi))) == null)
throw new NullPointerException();
if (!d.biRelay(a, b)) {
BiRelay<?,?> c = new BiRelay<>(d, a, b);
@@ -1388,7 +1448,7 @@
CompletableFuture<U> b;
if (f == null || (b = o.toCompletableFuture()) == null)
throw new NullPointerException();
- CompletableFuture<V> d = new CompletableFuture<V>();
+ CompletableFuture<V> d = newIncompleteFuture();
if (e != null || !d.orApply(this, b, f, null)) {
OrApply<T,U,V> c = new OrApply<T,U,V>(e, d, this, b, f);
orpush(b, c);
@@ -1452,7 +1512,7 @@
CompletableFuture<U> b;
if (f == null || (b = o.toCompletableFuture()) == null)
throw new NullPointerException();
- CompletableFuture<Void> d = new CompletableFuture<Void>();
+ CompletableFuture<Void> d = newIncompleteFuture();
if (e != null || !d.orAccept(this, b, f, null)) {
OrAccept<T,U> c = new OrAccept<T,U>(e, d, this, b, f);
orpush(b, c);
@@ -1510,7 +1570,7 @@
CompletableFuture<?> b;
if (f == null || (b = o.toCompletableFuture()) == null)
throw new NullPointerException();
- CompletableFuture<Void> d = new CompletableFuture<Void>();
+ CompletableFuture<Void> d = newIncompleteFuture();
if (e != null || !d.orRun(this, b, f, null)) {
OrRun<T,?> c = new OrRun<>(e, d, this, b, f);
orpush(b, c);
@@ -1556,7 +1616,7 @@
if ((a = (lo == mid ? cfs[lo] :
orTree(cfs, lo, mid))) == null ||
(b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
- orTree(cfs, mid+1, hi))) == null)
+ orTree(cfs, mid+1, hi))) == null)
throw new NullPointerException();
if (!d.orRelay(a, b)) {
OrRelay<?,?> c = new OrRelay<>(d, a, b);
@@ -1571,9 +1631,9 @@
@SuppressWarnings("serial")
static final class AsyncSupply<T> extends ForkJoinTask<Void>
- implements Runnable, AsynchronousCompletionTask {
- CompletableFuture<T> dep; Supplier<T> fn;
- AsyncSupply(CompletableFuture<T> dep, Supplier<T> fn) {
+ implements Runnable, AsynchronousCompletionTask {
+ CompletableFuture<T> dep; Supplier<? extends T> fn;
+ AsyncSupply(CompletableFuture<T> dep, Supplier<? extends T> fn) {
this.dep = dep; this.fn = fn;
}
@@ -1582,7 +1642,7 @@
public final boolean exec() { run(); return true; }
public void run() {
- CompletableFuture<T> d; Supplier<T> f;
+ CompletableFuture<T> d; Supplier<? extends T> f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;
if (d.result == null) {
@@ -1607,7 +1667,7 @@
@SuppressWarnings("serial")
static final class AsyncRun extends ForkJoinTask<Void>
- implements Runnable, AsynchronousCompletionTask {
+ implements Runnable, AsynchronousCompletionTask {
CompletableFuture<Void> dep; Runnable fn;
AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
this.dep = dep; this.fn = fn;
@@ -1651,14 +1711,15 @@
@SuppressWarnings("serial")
static final class Signaller extends Completion
implements ForkJoinPool.ManagedBlocker {
- long nanos; // wait time if timed
+ long nanos; // remaining wait time if timed
final long deadline; // non-zero if timed
- volatile int interruptControl; // > 0: interruptible, < 0: interrupted
+ final boolean interruptible;
+ boolean interrupted;
volatile Thread thread;
Signaller(boolean interruptible, long nanos, long deadline) {
this.thread = Thread.currentThread();
- this.interruptControl = interruptible ? 1 : 0;
+ this.interruptible = interruptible;
this.nanos = nanos;
this.deadline = deadline;
}
@@ -1671,29 +1732,22 @@
return null;
}
public boolean isReleasable() {
- if (thread == null)
- return true;
- if (Thread.interrupted()) {
- int i = interruptControl;
- interruptControl = -1;
- if (i > 0)
- return true;
- }
- if (deadline != 0L &&
- (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
- thread = null;
- return true;
- }
- return false;
+ if (Thread.interrupted())
+ interrupted = true;
+ return ((interrupted && interruptible) ||
+ (deadline != 0L &&
+ (nanos <= 0L ||
+ (nanos = deadline - System.nanoTime()) <= 0L)) ||
+ thread == null);
}
public boolean block() {
- if (isReleasable())
- return true;
- else if (deadline == 0L)
- LockSupport.park(this);
- else if (nanos > 0L)
- LockSupport.parkNanos(this, nanos);
- return isReleasable();
+ while (!isReleasable()) {
+ if (deadline == 0L)
+ LockSupport.park(this);
+ else
+ LockSupport.parkNanos(this, nanos);
+ }
+ return true;
}
final boolean isLive() { return thread != null; }
}
@@ -1705,13 +1759,10 @@
private Object waitingGet(boolean interruptible) {
Signaller q = null;
boolean queued = false;
- int spins = -1;
+ int spins = SPINS;
Object r;
while ((r = result) == null) {
- if (spins < 0)
- spins = (Runtime.getRuntime().availableProcessors() > 1) ?
- 1 << 8 : 0; // Use brief spin-wait on multiprocessors
- else if (spins > 0) {
+ if (spins > 0) {
if (ThreadLocalRandom.nextSecondarySeed() >= 0)
--spins;
}
@@ -1719,29 +1770,27 @@
q = new Signaller(interruptible, 0L, 0L);
else if (!queued)
queued = tryPushStack(q);
- else if (interruptible && q.interruptControl < 0) {
- q.thread = null;
- cleanStack();
- return null;
- }
- else if (q.thread != null && result == null) {
+ else {
try {
ForkJoinPool.managedBlock(q);
- } catch (InterruptedException ie) {
- q.interruptControl = -1;
+ } catch (InterruptedException ie) { // currently cannot happen
+ q.interrupted = true;
}
+ if (q.interrupted && interruptible)
+ break;
}
}
if (q != null) {
q.thread = null;
- if (q.interruptControl < 0) {
+ if (q.interrupted) {
if (interruptible)
- r = null; // report interruption
+ cleanStack();
else
Thread.currentThread().interrupt();
}
}
- postComplete();
+ if (r != null)
+ postComplete();
return r;
}
@@ -1752,37 +1801,39 @@
private Object timedGet(long nanos) throws TimeoutException {
if (Thread.interrupted())
return null;
- if (nanos <= 0L)
- throw new TimeoutException();
- long d = System.nanoTime() + nanos;
- Signaller q = new Signaller(true, nanos, d == 0L ? 1L : d); // avoid 0
- boolean queued = false;
- Object r;
- // We intentionally don't spin here (as waitingGet does) because
- // the call to nanoTime() above acts much like a spin.
- while ((r = result) == null) {
- if (!queued)
- queued = tryPushStack(q);
- else if (q.interruptControl < 0 || q.nanos <= 0L) {
- q.thread = null;
- cleanStack();
- if (q.interruptControl < 0)
- return null;
- throw new TimeoutException();
- }
- else if (q.thread != null && result == null) {
- try {
- ForkJoinPool.managedBlock(q);
- } catch (InterruptedException ie) {
- q.interruptControl = -1;
+ if (nanos > 0L) {
+ long d = System.nanoTime() + nanos;
+ long deadline = (d == 0L) ? 1L : d; // avoid 0
+ Signaller q = null;
+ boolean queued = false;
+ Object r;
+ while ((r = result) == null) { // similar to untimed, without spins
+ if (q == null)
+ q = new Signaller(true, nanos, deadline);
+ else if (!queued)
+ queued = tryPushStack(q);
+ else if (q.nanos <= 0L)
+ break;
+ else {
+ try {
+ ForkJoinPool.managedBlock(q);
+ } catch (InterruptedException ie) {
+ q.interrupted = true;
+ }
+ if (q.interrupted)
+ break;
}
}
+ if (q != null)
+ q.thread = null;
+ if (r != null)
+ postComplete();
+ else
+ cleanStack();
+ if (r != null || (q != null && q.interrupted))
+ return r;
}
- if (q.interruptControl < 0)
- r = null;
- q.thread = null;
- postComplete();
- return r;
+ throw new TimeoutException();
}
/* ------------- public methods -------------- */
@@ -1796,7 +1847,7 @@
/**
* Creates a new complete CompletableFuture with given encoded result.
*/
- private CompletableFuture(Object r) {
+ CompletableFuture(Object r) {
this.result = r;
}
@@ -1811,7 +1862,7 @@
* @return the new CompletableFuture
*/
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
- return asyncSupplyStage(asyncPool, supplier);
+ return asyncSupplyStage(ASYNC_POOL, supplier);
}
/**
@@ -1840,7 +1891,7 @@
* @return the new CompletableFuture
*/
public static CompletableFuture<Void> runAsync(Runnable runnable) {
- return asyncRunStage(asyncPool, runnable);
+ return asyncRunStage(ASYNC_POOL, runnable);
}
/**
@@ -1985,7 +2036,7 @@
public <U> CompletableFuture<U> thenApplyAsync(
Function<? super T,? extends U> fn) {
- return uniApplyStage(asyncPool, fn);
+ return uniApplyStage(defaultExecutor(), fn);
}
public <U> CompletableFuture<U> thenApplyAsync(
@@ -1998,7 +2049,7 @@
}
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {
- return uniAcceptStage(asyncPool, action);
+ return uniAcceptStage(defaultExecutor(), action);
}
public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,
@@ -2011,7 +2062,7 @@
}
public CompletableFuture<Void> thenRunAsync(Runnable action) {
- return uniRunStage(asyncPool, action);
+ return uniRunStage(defaultExecutor(), action);
}
public CompletableFuture<Void> thenRunAsync(Runnable action,
@@ -2028,7 +2079,7 @@
public <U,V> CompletableFuture<V> thenCombineAsync(
CompletionStage<? extends U> other,
BiFunction<? super T,? super U,? extends V> fn) {
- return biApplyStage(asyncPool, other, fn);
+ return biApplyStage(defaultExecutor(), other, fn);
}
public <U,V> CompletableFuture<V> thenCombineAsync(
@@ -2046,7 +2097,7 @@
public <U> CompletableFuture<Void> thenAcceptBothAsync(
CompletionStage<? extends U> other,
BiConsumer<? super T, ? super U> action) {
- return biAcceptStage(asyncPool, other, action);
+ return biAcceptStage(defaultExecutor(), other, action);
}
public <U> CompletableFuture<Void> thenAcceptBothAsync(
@@ -2062,7 +2113,7 @@
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
Runnable action) {
- return biRunStage(asyncPool, other, action);
+ return biRunStage(defaultExecutor(), other, action);
}
public CompletableFuture<Void> runAfterBothAsync(CompletionStage<?> other,
@@ -2078,7 +2129,7 @@
public <U> CompletableFuture<U> applyToEitherAsync(
CompletionStage<? extends T> other, Function<? super T, U> fn) {
- return orApplyStage(asyncPool, other, fn);
+ return orApplyStage(defaultExecutor(), other, fn);
}
public <U> CompletableFuture<U> applyToEitherAsync(
@@ -2094,7 +2145,7 @@
public CompletableFuture<Void> acceptEitherAsync(
CompletionStage<? extends T> other, Consumer<? super T> action) {
- return orAcceptStage(asyncPool, other, action);
+ return orAcceptStage(defaultExecutor(), other, action);
}
public CompletableFuture<Void> acceptEitherAsync(
@@ -2110,7 +2161,7 @@
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
Runnable action) {
- return orRunStage(asyncPool, other, action);
+ return orRunStage(defaultExecutor(), other, action);
}
public CompletableFuture<Void> runAfterEitherAsync(CompletionStage<?> other,
@@ -2126,7 +2177,7 @@
public <U> CompletableFuture<U> thenComposeAsync(
Function<? super T, ? extends CompletionStage<U>> fn) {
- return uniComposeStage(asyncPool, fn);
+ return uniComposeStage(defaultExecutor(), fn);
}
public <U> CompletableFuture<U> thenComposeAsync(
@@ -2142,7 +2193,7 @@
public CompletableFuture<T> whenCompleteAsync(
BiConsumer<? super T, ? super Throwable> action) {
- return uniWhenCompleteStage(asyncPool, action);
+ return uniWhenCompleteStage(defaultExecutor(), action);
}
public CompletableFuture<T> whenCompleteAsync(
@@ -2157,7 +2208,7 @@
public <U> CompletableFuture<U> handleAsync(
BiFunction<? super T, Throwable, ? extends U> fn) {
- return uniHandleStage(asyncPool, fn);
+ return uniHandleStage(defaultExecutor(), fn);
}
public <U> CompletableFuture<U> handleAsync(
@@ -2196,6 +2247,7 @@
return uniExceptionallyStage(fn);
}
+
/* ------------- Arbitrary-arity constructions -------------- */
/**
@@ -2353,10 +2405,12 @@
*/
public String toString() {
Object r = result;
- int count;
+ int count = 0; // avoid call to getNumberOfDependents in case disabled
+ for (Completion p = stack; p != null; p = p.next)
+ ++count;
return super.toString() +
((r == null) ?
- (((count = getNumberOfDependents()) == 0) ?
+ ((count == 0) ?
"[Not completed]" :
"[Not completed, " + count + " dependents]") :
(((r instanceof AltResult) && ((AltResult)r).ex != null) ?
@@ -2364,22 +2418,381 @@
"[Completed normally]"));
}
+ // jdk9 additions
+
+ /**
+ * Returns a new incomplete CompletableFuture of the type to be
+ * returned by a CompletionStage method. Subclasses should
+ * normally override this method to return an instance of the same
+ * class as this CompletableFuture. The default implementation
+ * returns an instance of class CompletableFuture.
+ *
+ * @param <U> the type of the value
+ * @return a new CompletableFuture
+ * @since 1.9
+ */
+ public <U> CompletableFuture<U> newIncompleteFuture() {
+ return new CompletableFuture<U>();
+ }
+
+ /**
+ * Returns the default Executor used for async methods that do not
+ * specify an Executor. This class uses the {@link
+ * ForkJoinPool#commonPool()} if it supports more than one
+ * parallel thread, or else an Executor using one thread per async
+ * task. This method may be overridden in subclasses to return
+ * an Executor that provides at least one independent thread.
+ *
+ * @return the executor
+ * @since 1.9
+ */
+ public Executor defaultExecutor() {
+ return ASYNC_POOL;
+ }
+
+ /**
+ * Returns a new CompletableFuture that is completed normally with
+ * the same value as this CompletableFuture when it completes
+ * normally. If this CompletableFuture completes exceptionally,
+ * then the returned CompletableFuture completes exceptionally
+ * with a CompletionException with this exception as cause. The
+ * behavior is equivalent to {@code thenApply(x -> x)}. This
+ * method may be useful as a form of "defensive copying", to
+ * prevent clients from completing, while still being able to
+ * arrange dependent actions.
+ *
+ * @return the new CompletableFuture
+ * @since 1.9
+ */
+ public CompletableFuture<T> copy() {
+ return uniCopyStage();
+ }
+
+ /**
+ * Returns a new CompletionStage that is completed normally with
+ * the same value as this CompletableFuture when it completes
+ * normally, and cannot be independently completed or otherwise
+ * used in ways not defined by the methods of interface {@link
+ * CompletionStage}. If this CompletableFuture completes
+ * exceptionally, then the returned CompletionStage completes
+ * exceptionally with a CompletionException with this exception as
+ * cause.
+ *
+ * @return the new CompletionStage
+ * @since 1.9
+ */
+ public CompletionStage<T> minimalCompletionStage() {
+ return uniAsMinimalStage();
+ }
+
+ /**
+ * Completes this CompletableFuture with the result of
+ * the given Supplier function invoked from an asynchronous
+ * task using the given executor.
+ *
+ * @param supplier a function returning the value to be used
+ * to complete this CompletableFuture
+ * @param executor the executor to use for asynchronous execution
+ * @return this CompletableFuture
+ * @since 1.9
+ */
+ public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier,
+ Executor executor) {
+ if (supplier == null || executor == null)
+ throw new NullPointerException();
+ executor.execute(new AsyncSupply<T>(this, supplier));
+ return this;
+ }
+
+ /**
+ * Completes this CompletableFuture with the result of the given
+ * Supplier function invoked from an asynchronous task using the
+ * default executor.
+ *
+ * @param supplier a function returning the value to be used
+ * to complete this CompletableFuture
+ * @return this CompletableFuture
+ * @since 1.9
+ */
+ public CompletableFuture<T> completeAsync(Supplier<? extends T> supplier) {
+ return completeAsync(supplier, defaultExecutor());
+ }
+
+ /**
+ * Exceptionally completes this CompletableFuture with
+ * a {@link TimeoutException} if not otherwise completed
+ * before the given timeout.
+ *
+ * @param timeout how long to wait before completing exceptionally
+ * with a TimeoutException, in units of {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return this CompletableFuture
+ * @since 1.9
+ */
+ public CompletableFuture<T> orTimeout(long timeout, TimeUnit unit) {
+ if (unit == null)
+ throw new NullPointerException();
+ if (result == null)
+ whenComplete(new Canceller(Delayer.delay(new Timeout(this),
+ timeout, unit)));
+ return this;
+ }
+
+ /**
+ * Completes this CompletableFuture with the given value if not
+ * otherwise completed before the given timeout.
+ *
+ * @param value the value to use upon timeout
+ * @param timeout how long to wait before completing normally
+ * with the given value, in units of {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return this CompletableFuture
+ * @since 1.9
+ */
+ public CompletableFuture<T> completeOnTimeout(T value, long timeout,
+ TimeUnit unit) {
+ if (unit == null)
+ throw new NullPointerException();
+ if (result == null)
+ whenComplete(new Canceller(Delayer.delay(
+ new DelayedCompleter<T>(this, value),
+ timeout, unit)));
+ return this;
+ }
+
+ /**
+ * Returns a new Executor that submits a task to the given base
+ * executor after the given delay (or no delay if non-positive).
+ * Each delay commences upon invocation of the returned executor's
+ * {@code execute} method.
+ *
+ * @param delay how long to delay, in units of {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code delay} parameter
+ * @param executor the base executor
+ * @return the new delayed executor
+ * @since 1.9
+ */
+ public static Executor delayedExecutor(long delay, TimeUnit unit,
+ Executor executor) {
+ if (unit == null || executor == null)
+ throw new NullPointerException();
+ return new DelayedExecutor(delay, unit, executor);
+ }
+
+ /**
+ * Returns a new Executor that submits a task to the default
+ * executor after the given delay (or no delay if non-positive).
+ * Each delay commences upon invocation of the returned executor's
+ * {@code execute} method.
+ *
+ * @param delay how long to delay, in units of {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code delay} parameter
+ * @return the new delayed executor
+ * @since 1.9
+ */
+ public static Executor delayedExecutor(long delay, TimeUnit unit) {
+ if (unit == null)
+ throw new NullPointerException();
+ return new DelayedExecutor(delay, unit, ASYNC_POOL);
+ }
+
+ /**
+ * Returns a new CompletionStage that is already completed with
+ * the given value and supports only those methods in
+ * interface {@link CompletionStage}.
+ *
+ * @param value the value
+ * @param <U> the type of the value
+ * @return the completed CompletionStage
+ * @since 1.9
+ */
+ public static <U> CompletionStage<U> completedStage(U value) {
+ return new MinimalStage<U>((value == null) ? NIL : value);
+ }
+
+ /**
+ * Returns a new CompletableFuture that is already completed
+ * exceptionally with the given exception.
+ *
+ * @param ex the exception
+ * @param <U> the type of the value
+ * @return the exceptionally completed CompletableFuture
+ * @since 1.9
+ */
+ public static <U> CompletableFuture<U> failedFuture(Throwable ex) {
+ if (ex == null) throw new NullPointerException();
+ return new CompletableFuture<U>(new AltResult(ex));
+ }
+
+ /**
+ * Returns a new CompletionStage that is already completed
+ * exceptionally with the given exception and supports only those
+ * methods in interface {@link CompletionStage}.
+ *
+ * @param ex the exception
+ * @param <U> the type of the value
+ * @return the exceptionally completed CompletionStage
+ * @since 1.9
+ */
+ public static <U> CompletionStage<U> failedStage(Throwable ex) {
+ if (ex == null) throw new NullPointerException();
+ return new MinimalStage<U>(new AltResult(ex));
+ }
+
+ /**
+ * Singleton delay scheduler, used only for starting and
+ * cancelling tasks.
+ */
+ static final class Delayer {
+ static ScheduledFuture<?> delay(Runnable command, long delay,
+ TimeUnit unit) {
+ return delayer.schedule(command, delay, unit);
+ }
+
+ static final class DaemonThreadFactory implements ThreadFactory {
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ t.setDaemon(true);
+ t.setName("CompletableFutureDelayScheduler");
+ return t;
+ }
+ }
+
+ static final ScheduledThreadPoolExecutor delayer;
+ static {
+ (delayer = new ScheduledThreadPoolExecutor(
+ 1, new DaemonThreadFactory())).
+ setRemoveOnCancelPolicy(true);
+ }
+ }
+
+ // Little class-ified lambdas to better support monitoring
+
+ static final class DelayedExecutor implements Executor {
+ final long delay;
+ final TimeUnit unit;
+ final Executor executor;
+ DelayedExecutor(long delay, TimeUnit unit, Executor executor) {
+ this.delay = delay; this.unit = unit; this.executor = executor;
+ }
+ public void execute(Runnable r) {
+ Delayer.delay(new TaskSubmitter(executor, r), delay, unit);
+ }
+ }
+
+ /** Action to submit user task */
+ static final class TaskSubmitter implements Runnable {
+ final Executor executor;
+ final Runnable action;
+ TaskSubmitter(Executor executor, Runnable action) {
+ this.executor = executor;
+ this.action = action;
+ }
+ public void run() { executor.execute(action); }
+ }
+
+ /** Action to completeExceptionally on timeout */
+ static final class Timeout implements Runnable {
+ final CompletableFuture<?> f;
+ Timeout(CompletableFuture<?> f) { this.f = f; }
+ public void run() {
+ if (f != null && !f.isDone())
+ f.completeExceptionally(new TimeoutException());
+ }
+ }
+
+ /** Action to complete on timeout */
+ static final class DelayedCompleter<U> implements Runnable {
+ final CompletableFuture<U> f;
+ final U u;
+ DelayedCompleter(CompletableFuture<U> f, U u) { this.f = f; this.u = u; }
+ public void run() {
+ if (f != null)
+ f.complete(u);
+ }
+ }
+
+ /** Action to cancel unneeded timeouts */
+ static final class Canceller implements BiConsumer<Object, Throwable> {
+ final Future<?> f;
+ Canceller(Future<?> f) { this.f = f; }
+ public void accept(Object ignore, Throwable ex) {
+ if (ex == null && f != null && !f.isDone())
+ f.cancel(false);
+ }
+ }
+
+ /**
+ * A subclass that just throws UOE for most non-CompletionStage methods.
+ */
+ static final class MinimalStage<T> extends CompletableFuture<T> {
+ MinimalStage() { }
+ MinimalStage(Object r) { super(r); }
+ @Override public <U> CompletableFuture<U> newIncompleteFuture() {
+ return new MinimalStage<U>(); }
+ @Override public T get() {
+ throw new UnsupportedOperationException(); }
+ @Override public T get(long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException(); }
+ @Override public T getNow(T valueIfAbsent) {
+ throw new UnsupportedOperationException(); }
+ @Override public T join() {
+ throw new UnsupportedOperationException(); }
+ @Override public boolean complete(T value) {
+ throw new UnsupportedOperationException(); }
+ @Override public boolean completeExceptionally(Throwable ex) {
+ throw new UnsupportedOperationException(); }
+ @Override public boolean cancel(boolean mayInterruptIfRunning) {
+ throw new UnsupportedOperationException(); }
+ @Override public void obtrudeValue(T value) {
+ throw new UnsupportedOperationException(); }
+ @Override public void obtrudeException(Throwable ex) {
+ throw new UnsupportedOperationException(); }
+ @Override public boolean isDone() {
+ throw new UnsupportedOperationException(); }
+ @Override public boolean isCancelled() {
+ throw new UnsupportedOperationException(); }
+ @Override public boolean isCompletedExceptionally() {
+ throw new UnsupportedOperationException(); }
+ @Override public int getNumberOfDependents() {
+ throw new UnsupportedOperationException(); }
+ @Override public CompletableFuture<T> completeAsync
+ (Supplier<? extends T> supplier, Executor executor) {
+ throw new UnsupportedOperationException(); }
+ @Override public CompletableFuture<T> completeAsync
+ (Supplier<? extends T> supplier) {
+ throw new UnsupportedOperationException(); }
+ @Override public CompletableFuture<T> orTimeout
+ (long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException(); }
+ @Override public CompletableFuture<T> completeOnTimeout
+ (T value, long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException(); }
+ }
+
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long RESULT;
private static final long STACK;
private static final long NEXT;
static {
try {
- final sun.misc.Unsafe u;
- UNSAFE = u = sun.misc.Unsafe.getUnsafe();
- Class<?> k = CompletableFuture.class;
- RESULT = u.objectFieldOffset(k.getDeclaredField("result"));
- STACK = u.objectFieldOffset(k.getDeclaredField("stack"));
- NEXT = u.objectFieldOffset
+ RESULT = U.objectFieldOffset
+ (CompletableFuture.class.getDeclaredField("result"));
+ STACK = U.objectFieldOffset
+ (CompletableFuture.class.getDeclaredField("stack"));
+ NEXT = U.objectFieldOffset
(Completion.class.getDeclaredField("next"));
- } catch (Exception x) {
- throw new Error(x);
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,12 +34,11 @@
*/
package java.util.concurrent;
-import java.util.function.Supplier;
-import java.util.function.Consumer;
+
import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.function.BiFunction;
-import java.util.concurrent.Executor;
/**
* A stage of a possibly asynchronous computation, that performs an
@@ -56,9 +55,9 @@
* For example, {@code stage.thenApply(x -> square(x)).thenAccept(x ->
* System.out.print(x)).thenRun(() -> System.out.println())}. An
* additional form (<em>compose</em>) applies functions of stages
- * themselves, rather than their results. </li>
+ * themselves, rather than their results.
*
- * <li> One stage's execution may be triggered by completion of a
+ * <li>One stage's execution may be triggered by completion of a
* single stage, or both of two stages, or either of two stages.
* Dependencies on a single stage are arranged using methods with
* prefix <em>then</em>. Those triggered by completion of
@@ -66,9 +65,9 @@
* effects, using correspondingly named methods. Those triggered by
* <em>either</em> of two stages make no guarantees about which of the
* results or effects are used for the dependent stage's
- * computation.</li>
+ * computation.
*
- * <li> Dependencies among stages control the triggering of
+ * <li>Dependencies among stages control the triggering of
* computations, but do not otherwise guarantee any particular
* ordering. Additionally, execution of a new stage's computations may
* be arranged in any of three ways: default execution, default
@@ -81,7 +80,7 @@
* properties, and might not even support concurrent execution, but
* are arranged for processing in a way that accommodates asynchrony.
*
- * <li> Two method forms support processing whether the triggering
+ * <li>Two method forms support processing whether the triggering
* stage completed normally or exceptionally: Method {@link
* #whenComplete whenComplete} allows injection of an action
* regardless of outcome, otherwise preserving the outcome in its
@@ -100,7 +99,7 @@
* stage completes normally or exceptionally. In the case of method
* {@code whenComplete}, when the supplied action itself encounters an
* exception, then the stage exceptionally completes with this
- * exception if not already completed exceptionally.</li>
+ * exception if not already completed exceptionally.
*
* </ul>
*
@@ -587,7 +586,7 @@
/**
* Returns a new CompletionStage that, when this stage completes
- * normally, is executed with this stage as the argument
+ * normally, is executed with this stage's result as the argument
* to the supplied function.
*
* See the {@link CompletionStage} documentation for rules
@@ -603,7 +602,7 @@
/**
* Returns a new CompletionStage that, when this stage completes
* normally, is executed using this stage's default asynchronous
- * execution facility, with this stage as the argument to the
+ * execution facility, with this stage's result as the argument to the
* supplied function.
*
* See the {@link CompletionStage} documentation for rules
@@ -652,12 +651,14 @@
* Returns a new CompletionStage with the same result or exception as
* this stage, that executes the given action when this stage completes.
*
- * <p>When this stage is complete, the given action is invoked with the
- * result (or {@code null} if none) and the exception (or {@code null}
- * if none) of this stage as arguments. The returned stage is completed
- * when the action returns. If the supplied action itself encounters an
- * exception, then the returned stage exceptionally completes with this
- * exception unless this stage also completed exceptionally.
+ * <p>When this stage is complete, the given action is invoked
+ * with the result (or {@code null} if none) and the exception (or
+ * {@code null} if none) of this stage as arguments. The returned
+ * stage is completed when the action returns. If the supplied
+ * action itself encounters an exception, then the returned stage
+ * exceptionally completes with this exception unless this stage
+ * also completed exceptionally (in which case, the returned stage
+ * exceptionally completes with the original exception).
*
* @param action the action to perform
* @return the new CompletionStage
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -42,7 +42,6 @@
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
@@ -51,14 +50,11 @@
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Spliterator;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
-import java.util.function.BinaryOperator;
import java.util.function.Consumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.Function;
@@ -154,43 +150,43 @@
* being concurrently updated by other threads; for example, when
* computing a snapshot summary of the values in a shared registry.
* There are three kinds of operation, each with four forms, accepting
- * functions with Keys, Values, Entries, and (Key, Value) arguments
- * and/or return values. Because the elements of a ConcurrentHashMap
- * are not ordered in any particular way, and may be processed in
- * different orders in different parallel executions, the correctness
- * of supplied functions should not depend on any ordering, or on any
- * other objects or values that may transiently change while
- * computation is in progress; and except for forEach actions, should
- * ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry}
- * objects do not support method {@code setValue}.
+ * functions with keys, values, entries, and (key, value) pairs as
+ * arguments and/or return values. Because the elements of a
+ * ConcurrentHashMap are not ordered in any particular way, and may be
+ * processed in different orders in different parallel executions, the
+ * correctness of supplied functions should not depend on any
+ * ordering, or on any other objects or values that may transiently
+ * change while computation is in progress; and except for forEach
+ * actions, should ideally be side-effect-free. Bulk operations on
+ * {@link java.util.Map.Entry} objects do not support method {@code
+ * setValue}.
*
* <ul>
- * <li> forEach: Perform a given action on each element.
+ * <li>forEach: Performs a given action on each element.
* A variant form applies a given transformation on each element
- * before performing the action.</li>
+ * before performing the action.
*
- * <li> search: Return the first available non-null result of
+ * <li>search: Returns the first available non-null result of
* applying a given function on each element; skipping further
- * search when a result is found.</li>
+ * search when a result is found.
*
- * <li> reduce: Accumulate each element. The supplied reduction
+ * <li>reduce: Accumulates each element. The supplied reduction
* function cannot rely on ordering (more formally, it should be
* both associative and commutative). There are five variants:
*
* <ul>
*
- * <li> Plain reductions. (There is not a form of this method for
+ * <li>Plain reductions. (There is not a form of this method for
* (key, value) function arguments since there is no corresponding
- * return type.)</li>
+ * return type.)
*
- * <li> Mapped reductions that accumulate the results of a given
- * function applied to each element.</li>
+ * <li>Mapped reductions that accumulate the results of a given
+ * function applied to each element.
*
- * <li> Reductions to scalar doubles, longs, and ints, using a
- * given basis value.</li>
+ * <li>Reductions to scalar doubles, longs, and ints, using a
+ * given basis value.
*
* </ul>
- * </li>
* </ul>
*
* <p>These bulk operations accept a {@code parallelismThreshold}
@@ -576,7 +572,7 @@
* The number of bits used for generation stamp in sizeCtl.
* Must be at least 6 for 32bit arrays.
*/
- private static int RESIZE_STAMP_BITS = 16;
+ private static final int RESIZE_STAMP_BITS = 16;
/**
* The maximum number of threads that can help resize.
@@ -604,7 +600,7 @@
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("segments", Segment[].class),
new ObjectStreamField("segmentMask", Integer.TYPE),
- new ObjectStreamField("segmentShift", Integer.TYPE)
+ new ObjectStreamField("segmentShift", Integer.TYPE),
};
/* ---------------- Nodes -------------- */
@@ -630,10 +626,12 @@
this.next = next;
}
- public final K getKey() { return key; }
- public final V getValue() { return val; }
- public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
- public final String toString(){ return key + "=" + val; }
+ public final K getKey() { return key; }
+ public final V getValue() { return val; }
+ public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
+ public final String toString() {
+ return Helpers.mapEntryToString(key, val);
+ }
public final V setValue(V value) {
throw new UnsupportedOperationException();
}
@@ -1057,6 +1055,8 @@
p.val = value;
}
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
if (binCount != 0) {
@@ -1159,6 +1159,8 @@
}
}
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
if (validated) {
@@ -1366,7 +1368,7 @@
/**
* Stripped-down version of helper class used in previous version,
- * declared for the sake of serialization compatibility
+ * declared for the sake of serialization compatibility.
*/
static class Segment<K,V> extends ReentrantLock implements Serializable {
private static final long serialVersionUID = 2249069246763182397L;
@@ -1401,9 +1403,10 @@
new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
for (int i = 0; i < segments.length; ++i)
segments[i] = new Segment<K,V>(LOAD_FACTOR);
- s.putFields().put("segments", segments);
- s.putFields().put("segmentShift", segmentShift);
- s.putFields().put("segmentMask", segmentMask);
+ java.io.ObjectOutputStream.PutField streamFields = s.putFields();
+ streamFields.put("segments", segments);
+ streamFields.put("segmentShift", segmentShift);
+ streamFields.put("segmentMask", segmentMask);
s.writeFields();
Node<K,V>[] t;
@@ -1620,9 +1623,9 @@
}
/**
- * Helper method for EntrySet.removeIf
+ * Helper method for EntrySetView.removeIf.
*/
- boolean removeEntryIf(Predicate<? super Entry<K, V>> function) {
+ boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
if (function == null) throw new NullPointerException();
Node<K,V>[] t;
boolean removed = false;
@@ -1640,9 +1643,9 @@
}
/**
- * Helper method for Values.removeIf
+ * Helper method for ValuesView.removeIf.
*/
- boolean removeValueIf(Predicate<? super V> function) {
+ boolean removeValueIf(Predicate<? super V> function) {
if (function == null) throw new NullPointerException();
Node<K,V>[] t;
boolean removed = false;
@@ -1716,7 +1719,7 @@
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
- K ek; V ev;
+ K ek;
if (e.hash == h &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
@@ -1726,6 +1729,8 @@
Node<K,V> pred = e;
if ((e = e.next) == null) {
if ((val = mappingFunction.apply(key)) != null) {
+ if (pred.next != null)
+ throw new IllegalStateException("Recursive update");
added = true;
pred.next = new Node<K,V>(h, key, val, null);
}
@@ -1745,6 +1750,8 @@
t.putTreeVal(h, key, val);
}
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
if (binCount != 0) {
@@ -1840,6 +1847,8 @@
}
}
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
if (binCount != 0)
@@ -1931,6 +1940,8 @@
if ((e = e.next) == null) {
val = remappingFunction.apply(key, null);
if (val != null) {
+ if (pred.next != null)
+ throw new IllegalStateException("Recursive update");
delta = 1;
pred.next =
new Node<K,V>(h, key, val, null);
@@ -1963,6 +1974,8 @@
setTabAt(tab, i, untreeify(t.first));
}
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
if (binCount != 0) {
@@ -2072,6 +2085,8 @@
setTabAt(tab, i, untreeify(t.first));
}
}
+ else if (f instanceof ReservationNode)
+ throw new IllegalStateException("Recursive update");
}
}
if (binCount != 0) {
@@ -2089,12 +2104,13 @@
// Hashtable legacy methods
/**
- * Legacy method testing if some key maps into the specified value
- * in this table. This method is identical in functionality to
+ * Tests if some key maps into the specified value in this table.
+ *
+ * <p>Note that this method is identical in functionality to
* {@link #containsValue(Object)}, and exists solely to ensure
* full compatibility with class {@link java.util.Hashtable},
* which supported this method prior to introduction of the
- * Java Collections framework.
+ * Java Collections Framework.
*
* @param value a value to search for
* @return {@code true} if and only if some key maps to the
@@ -2235,7 +2251,7 @@
}
/**
- * A place-holder node used in computeIfAbsent and compute
+ * A place-holder node used in computeIfAbsent and compute.
*/
static final class ReservationNode<K,V> extends Node<K,V> {
ReservationNode() {
@@ -2384,17 +2400,8 @@
break;
else if (tab == table) {
int rs = resizeStamp(n);
- if (sc < 0) {
- Node<K,V>[] nt;
- if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
- sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
- transferIndex <= 0)
- break;
- if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
- transfer(tab, nt);
- }
- else if (U.compareAndSwapInt(this, SIZECTL, sc,
- (rs << RESIZE_STAMP_SHIFT) + 2))
+ if (U.compareAndSwapInt(this, SIZECTL, sc,
+ (rs << RESIZE_STAMP_SHIFT) + 2))
transfer(tab, null);
}
}
@@ -2649,7 +2656,7 @@
* too small, in which case resizes instead.
*/
private final void treeifyBin(Node<K,V>[] tab, int index) {
- Node<K,V> b; int n, sc;
+ Node<K,V> b; int n;
if (tab != null) {
if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
tryPresize(n << 1);
@@ -2693,7 +2700,7 @@
/* ---------------- TreeNodes -------------- */
/**
- * Nodes for use in TreeBins
+ * Nodes for use in TreeBins.
*/
static final class TreeNode<K,V> extends Node<K,V> {
TreeNode<K,V> parent; // red-black tree links
@@ -2719,7 +2726,7 @@
final TreeNode<K,V> findTreeNode(int h, Object k, Class<?> kc) {
if (k != null) {
TreeNode<K,V> p = this;
- do {
+ do {
int ph, dir; K pk; TreeNode<K,V> q;
TreeNode<K,V> pl = p.left, pr = p.right;
if ((ph = p.hash) > h)
@@ -2812,7 +2819,7 @@
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0)
dir = tieBreakOrder(k, pk);
- TreeNode<K,V> xp = p;
+ TreeNode<K,V> xp = p;
if ((p = (dir <= 0) ? p.left : p.right) == null) {
x.parent = xp;
if (dir <= 0)
@@ -3165,7 +3172,7 @@
static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
TreeNode<K,V> x) {
- for (TreeNode<K,V> xp, xpl, xpr;;) {
+ for (TreeNode<K,V> xp, xpl, xpr;;) {
if (x == null || x == root)
return root;
else if ((xp = x.parent) == null) {
@@ -3256,7 +3263,7 @@
}
/**
- * Recursive invariant check
+ * Checks invariants recursively for the tree of Nodes rooted at t.
*/
static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
@@ -3280,15 +3287,13 @@
return true;
}
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long LOCKSTATE;
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> k = TreeBin.class;
LOCKSTATE = U.objectFieldOffset
- (k.getDeclaredField("lockState"));
- } catch (Exception e) {
+ (TreeBin.class.getDeclaredField("lockState"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -3503,7 +3508,7 @@
}
/**
- * Exported Entry for EntryIterator
+ * Exported Entry for EntryIterator.
*/
static final class MapEntry<K,V> implements Map.Entry<K,V> {
final K key; // non-null
@@ -3517,7 +3522,9 @@
public K getKey() { return key; }
public V getValue() { return val; }
public int hashCode() { return key.hashCode() ^ val.hashCode(); }
- public String toString() { return key + "=" + val; }
+ public String toString() {
+ return Helpers.mapEntryToString(key, val);
+ }
public boolean equals(Object o) {
Object k, v; Map.Entry<?,?> e;
@@ -3554,7 +3561,7 @@
this.est = est;
}
- public Spliterator<K> trySplit() {
+ public KeySpliterator<K,V> trySplit() {
int i, f, h;
return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
new KeySpliterator<K,V>(tab, baseSize, baseLimit = h,
@@ -3593,7 +3600,7 @@
this.est = est;
}
- public Spliterator<V> trySplit() {
+ public ValueSpliterator<K,V> trySplit() {
int i, f, h;
return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
new ValueSpliterator<K,V>(tab, baseSize, baseLimit = h,
@@ -3633,7 +3640,7 @@
this.est = est;
}
- public Spliterator<Map.Entry<K,V>> trySplit() {
+ public EntrySpliterator<K,V> trySplit() {
int i, f, h;
return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
new EntrySpliterator<K,V>(tab, baseSize, baseLimit = h,
@@ -4445,19 +4452,19 @@
public abstract boolean contains(Object o);
public abstract boolean remove(Object o);
- private static final String oomeMsg = "Required array size too large";
+ private static final String OOME_MSG = "Required array size too large";
public final Object[] toArray() {
long sz = map.mappingCount();
if (sz > MAX_ARRAY_SIZE)
- throw new OutOfMemoryError(oomeMsg);
+ throw new OutOfMemoryError(OOME_MSG);
int n = (int)sz;
Object[] r = new Object[n];
int i = 0;
for (E e : this) {
if (i == n) {
if (n >= MAX_ARRAY_SIZE)
- throw new OutOfMemoryError(oomeMsg);
+ throw new OutOfMemoryError(OOME_MSG);
if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
n = MAX_ARRAY_SIZE;
else
@@ -4473,7 +4480,7 @@
public final <T> T[] toArray(T[] a) {
long sz = map.mappingCount();
if (sz > MAX_ARRAY_SIZE)
- throw new OutOfMemoryError(oomeMsg);
+ throw new OutOfMemoryError(OOME_MSG);
int m = (int)sz;
T[] r = (a.length >= m) ? a :
(T[])java.lang.reflect.Array
@@ -4483,7 +4490,7 @@
for (E e : this) {
if (i == n) {
if (n >= MAX_ARRAY_SIZE)
- throw new OutOfMemoryError(oomeMsg);
+ throw new OutOfMemoryError(OOME_MSG);
if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
n = MAX_ARRAY_SIZE;
else
@@ -4803,7 +4810,7 @@
return added;
}
- public boolean removeIf(Predicate<? super Entry<K, V>> filter) {
+ public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
return map.removeEntryIf(filter);
}
@@ -4878,7 +4885,7 @@
}
/**
- * Same as Traverser version
+ * Same as Traverser version.
*/
final Node<K,V> advance() {
Node<K,V> e;
@@ -6323,38 +6330,40 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long SIZECTL;
private static final long TRANSFERINDEX;
private static final long BASECOUNT;
private static final long CELLSBUSY;
private static final long CELLVALUE;
- private static final long ABASE;
+ private static final int ABASE;
private static final int ASHIFT;
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ConcurrentHashMap.class;
SIZECTL = U.objectFieldOffset
- (k.getDeclaredField("sizeCtl"));
+ (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
TRANSFERINDEX = U.objectFieldOffset
- (k.getDeclaredField("transferIndex"));
+ (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
BASECOUNT = U.objectFieldOffset
- (k.getDeclaredField("baseCount"));
+ (ConcurrentHashMap.class.getDeclaredField("baseCount"));
CELLSBUSY = U.objectFieldOffset
- (k.getDeclaredField("cellsBusy"));
- Class<?> ck = CounterCell.class;
+ (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
+
CELLVALUE = U.objectFieldOffset
- (ck.getDeclaredField("value"));
- Class<?> ak = Node[].class;
- ABASE = U.arrayBaseOffset(ak);
- int scale = U.arrayIndexScale(ak);
+ (CounterCell.class.getDeclaredField("value"));
+
+ ABASE = U.arrayBaseOffset(Node[].class);
+ int scale = U.arrayIndexScale(Node[].class);
if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
+ throw new Error("array index scale not a power of two");
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
- } catch (Exception e) {
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,11 +36,12 @@
package java.util.concurrent;
import java.util.AbstractCollection;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Queue;
import java.util.Spliterator;
import java.util.Spliterators;
@@ -87,7 +88,7 @@
* @since 1.7
* @author Doug Lea
* @author Martin Buchholz
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
*/
public class ConcurrentLinkedDeque<E>
extends AbstractCollection<E>
@@ -300,47 +301,45 @@
* only be seen after publication via casNext or casPrev.
*/
Node(E item) {
- UNSAFE.putObject(this, itemOffset, item);
+ U.putObject(this, ITEM, item);
}
boolean casItem(E cmp, E val) {
- return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+ return U.compareAndSwapObject(this, ITEM, cmp, val);
}
void lazySetNext(Node<E> val) {
- UNSAFE.putOrderedObject(this, nextOffset, val);
+ U.putOrderedObject(this, NEXT, val);
}
boolean casNext(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+ return U.compareAndSwapObject(this, NEXT, cmp, val);
}
void lazySetPrev(Node<E> val) {
- UNSAFE.putOrderedObject(this, prevOffset, val);
+ U.putOrderedObject(this, PREV, val);
}
boolean casPrev(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, prevOffset, cmp, val);
+ return U.compareAndSwapObject(this, PREV, cmp, val);
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long prevOffset;
- private static final long itemOffset;
- private static final long nextOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long PREV;
+ private static final long ITEM;
+ private static final long NEXT;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = Node.class;
- prevOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("prev"));
- itemOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("item"));
- nextOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("next"));
- } catch (Exception e) {
+ PREV = U.objectFieldOffset
+ (Node.class.getDeclaredField("prev"));
+ ITEM = U.objectFieldOffset
+ (Node.class.getDeclaredField("item"));
+ NEXT = U.objectFieldOffset
+ (Node.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -350,8 +349,7 @@
* Links e as first element.
*/
private void linkFirst(E e) {
- checkNotNull(e);
- final Node<E> newNode = new Node<E>(e);
+ final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
restartFromHead:
for (;;)
@@ -383,8 +381,7 @@
* Links e as last element.
*/
private void linkLast(E e) {
- checkNotNull(e);
- final Node<E> newNode = new Node<E>(e);
+ final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
restartFromTail:
for (;;)
@@ -789,16 +786,6 @@
// Minor convenience utilities
/**
- * Throws NullPointerException if argument is null.
- *
- * @param v the element
- */
- private static void checkNotNull(Object v) {
- if (v == null)
- throw new NullPointerException();
- }
-
- /**
* Returns element unless it is null, in which case throws
* NoSuchElementException.
*
@@ -812,22 +799,6 @@
}
/**
- * Creates an array list and fills it with elements of this list.
- * Used by toArray.
- *
- * @return the array list
- */
- private ArrayList<E> toArrayList() {
- ArrayList<E> list = new ArrayList<E>();
- for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null)
- list.add(item);
- }
- return list;
- }
-
- /**
* Constructs an empty deque.
*/
public ConcurrentLinkedDeque() {
@@ -847,8 +818,7 @@
// Copy c into a private chain of Nodes
Node<E> h = null, t = null;
for (E e : c) {
- checkNotNull(e);
- Node<E> newNode = new Node<E>(e);
+ Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
if (h == null)
h = t = newNode;
else {
@@ -1046,16 +1016,19 @@
public void push(E e) { addFirst(e); }
/**
- * Removes the first element {@code e} such that
- * {@code o.equals(e)}, if such an element exists in this deque.
+ * Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return {@code true} if the deque contained the specified element
* @throws NullPointerException if the specified element is null
*/
public boolean removeFirstOccurrence(Object o) {
- checkNotNull(o);
+ Objects.requireNonNull(o);
for (Node<E> p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null && o.equals(item) && p.casItem(item, null)) {
@@ -1067,16 +1040,19 @@
}
/**
- * Removes the last element {@code e} such that
- * {@code o.equals(e)}, if such an element exists in this deque.
+ * Removes the last occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
+ * More formally, removes the last element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
* @return {@code true} if the deque contained the specified element
* @throws NullPointerException if the specified element is null
*/
public boolean removeLastOccurrence(Object o) {
- checkNotNull(o);
+ Objects.requireNonNull(o);
for (Node<E> p = last(); p != null; p = pred(p)) {
E item = p.item;
if (item != null && o.equals(item) && p.casItem(item, null)) {
@@ -1088,18 +1064,20 @@
}
/**
- * Returns {@code true} if this deque contains at least one
- * element {@code e} such that {@code o.equals(e)}.
+ * Returns {@code true} if this deque contains the specified element.
+ * More formally, returns {@code true} if and only if this deque contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o element whose presence in this deque is to be tested
* @return {@code true} if this deque contains the specified element
*/
public boolean contains(Object o) {
- if (o == null) return false;
- for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null && o.equals(item))
- return true;
+ if (o != null) {
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null && o.equals(item))
+ return true;
+ }
}
return false;
}
@@ -1130,19 +1108,28 @@
* @return the number of elements in this deque
*/
public int size() {
- int count = 0;
- for (Node<E> p = first(); p != null; p = succ(p))
- if (p.item != null)
- // Collection.size() spec says to max out
- if (++count == Integer.MAX_VALUE)
- break;
- return count;
+ restartFromHead: for (;;) {
+ int count = 0;
+ for (Node<E> p = first(); p != null;) {
+ if (p.item != null)
+ if (++count == Integer.MAX_VALUE)
+ break; // @see Collection.size()
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ return count;
+ }
}
/**
- * Removes the first element {@code e} such that
- * {@code o.equals(e)}, if such an element exists in this deque.
+ * Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
+ * More formally, removes the first element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
+ * (or equivalently, if this deque changed as a result of the call).
+ *
+ * <p>This method is equivalent to {@link #removeFirstOccurrence(Object)}.
*
* @param o element to be removed from this deque, if present
* @return {@code true} if the deque contained the specified element
@@ -1172,8 +1159,7 @@
// Copy c into a private chain of Nodes
Node<E> beginningOfTheEnd = null, last = null;
for (E e : c) {
- checkNotNull(e);
- Node<E> newNode = new Node<E>(e);
+ Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
if (beginningOfTheEnd == null)
beginningOfTheEnd = last = newNode;
else {
@@ -1224,6 +1210,62 @@
;
}
+ public String toString() {
+ String[] a = null;
+ restartFromHead: for (;;) {
+ int charLength = 0;
+ int size = 0;
+ for (Node<E> p = first(); p != null;) {
+ E item = p.item;
+ if (item != null) {
+ if (a == null)
+ a = new String[4];
+ else if (size == a.length)
+ a = Arrays.copyOf(a, 2 * size);
+ String s = item.toString();
+ a[size++] = s;
+ charLength += s.length();
+ }
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+
+ if (size == 0)
+ return "[]";
+
+ return Helpers.toString(a, size, charLength);
+ }
+ }
+
+ private Object[] toArrayInternal(Object[] a) {
+ Object[] x = a;
+ restartFromHead: for (;;) {
+ int size = 0;
+ for (Node<E> p = first(); p != null;) {
+ E item = p.item;
+ if (item != null) {
+ if (x == null)
+ x = new Object[4];
+ else if (size == x.length)
+ x = Arrays.copyOf(x, 2 * (size + 4));
+ x[size++] = item;
+ }
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ if (x == null)
+ return new Object[0];
+ else if (a != null && size <= a.length) {
+ if (a != x)
+ System.arraycopy(x, 0, a, 0, size);
+ if (size < a.length)
+ a[size] = null;
+ return a;
+ }
+ return (size == x.length) ? x : Arrays.copyOf(x, size);
+ }
+ }
+
/**
* Returns an array containing all of the elements in this deque, in
* proper sequence (from first to last element).
@@ -1238,7 +1280,7 @@
* @return an array containing all of the elements in this deque
*/
public Object[] toArray() {
- return toArrayList().toArray();
+ return toArrayInternal(null);
}
/**
@@ -1264,7 +1306,7 @@
* The following code can be used to dump the deque into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -1278,8 +1320,10 @@
* this deque
* @throws NullPointerException if the specified array is null
*/
+ @SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- return toArrayList().toArray(a);
+ if (a == null) throw new NullPointerException();
+ return (T[]) toArrayInternal(a);
}
/**
@@ -1346,7 +1390,7 @@
Node<E> p = (nextNode == null) ? startNode() : nextNode(nextNode);
for (;; p = nextNode(p)) {
if (p == null) {
- // p might be active end or TERMINATOR node; both are OK
+ // might be at active end or TERMINATOR node; both are OK
nextNode = null;
nextItem = null;
break;
@@ -1426,8 +1470,9 @@
if (i > 0) {
batch = i;
return Spliterators.spliterator
- (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT);
+ (a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
}
}
@@ -1539,8 +1584,7 @@
// Read in elements until trailing null sentinel found
Node<E> h = null, t = null;
- Object item;
- while ((item = s.readObject()) != null) {
+ for (Object item; (item = s.readObject()) != null; ) {
@SuppressWarnings("unchecked")
Node<E> newNode = new Node<E>((E) item);
if (h == null)
@@ -1555,31 +1599,29 @@
}
private boolean casHead(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+ return U.compareAndSwapObject(this, HEAD, cmp, val);
}
private boolean casTail(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+ return U.compareAndSwapObject(this, TAIL, cmp, val);
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long headOffset;
- private static final long tailOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long HEAD;
+ private static final long TAIL;
static {
PREV_TERMINATOR = new Node<Object>();
PREV_TERMINATOR.next = PREV_TERMINATOR;
NEXT_TERMINATOR = new Node<Object>();
NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ConcurrentLinkedDeque.class;
- headOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("head"));
- tailOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("tail"));
- } catch (Exception e) {
+ HEAD = U.objectFieldOffset
+ (ConcurrentLinkedDeque.class.getDeclaredField("head"));
+ TAIL = U.objectFieldOffset
+ (ConcurrentLinkedDeque.class.getDeclaredField("tail"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,10 +36,11 @@
package java.util.concurrent;
import java.util.AbstractQueue;
-import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Queue;
import java.util.Spliterator;
import java.util.Spliterators;
@@ -60,9 +61,9 @@
* does not permit the use of {@code null} elements.
*
* <p>This implementation employs an efficient <em>non-blocking</em>
- * algorithm based on one described in <a
- * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
- * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
+ * algorithm based on one described in
+ * <a href="http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf">
+ * Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue
* Algorithms</a> by Maged M. Michael and Michael L. Scott.
*
* <p>Iterators are <i>weakly consistent</i>, returning elements
@@ -100,7 +101,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
implements Queue<E>, java.io.Serializable {
@@ -180,45 +181,28 @@
private static class Node<E> {
volatile E item;
volatile Node<E> next;
-
- /**
- * Constructs a new node. Uses relaxed write because item can
- * only be seen after publication via casNext.
- */
- Node(E item) {
- UNSAFE.putObject(this, itemOffset, item);
- }
-
- boolean casItem(E cmp, E val) {
- return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
- }
-
- void lazySetNext(Node<E> val) {
- UNSAFE.putOrderedObject(this, nextOffset, val);
- }
+ }
- boolean casNext(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
- }
-
- // Unsafe mechanics
-
- private static final sun.misc.Unsafe UNSAFE;
- private static final long itemOffset;
- private static final long nextOffset;
+ /**
+ * Returns a new node holding item. Uses relaxed write because item
+ * can only be seen after piggy-backing publication via casNext.
+ */
+ static <E> Node<E> newNode(E item) {
+ Node<E> node = new Node<E>();
+ U.putObject(node, ITEM, item);
+ return node;
+ }
- static {
- try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = Node.class;
- itemOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("item"));
- nextOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("next"));
- } catch (Exception e) {
- throw new Error(e);
- }
- }
+ static <E> boolean casItem(Node<E> node, E cmp, E val) {
+ return U.compareAndSwapObject(node, ITEM, cmp, val);
+ }
+
+ static <E> void lazySetNext(Node<E> node, Node<E> val) {
+ U.putOrderedObject(node, NEXT, val);
+ }
+
+ static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
+ return U.compareAndSwapObject(node, NEXT, cmp, val);
}
/**
@@ -233,7 +217,7 @@
* - it is permitted for tail to lag behind head, that is, for tail
* to not be reachable from head!
*/
- private transient volatile Node<E> head;
+ transient volatile Node<E> head;
/**
* A node from which the last node on list (that is, the unique
@@ -253,7 +237,7 @@
* Creates a {@code ConcurrentLinkedQueue} that is initially empty.
*/
public ConcurrentLinkedQueue() {
- head = tail = new Node<E>(null);
+ head = tail = newNode(null);
}
/**
@@ -268,17 +252,16 @@
public ConcurrentLinkedQueue(Collection<? extends E> c) {
Node<E> h = null, t = null;
for (E e : c) {
- checkNotNull(e);
- Node<E> newNode = new Node<E>(e);
+ Node<E> newNode = newNode(Objects.requireNonNull(e));
if (h == null)
h = t = newNode;
else {
- t.lazySetNext(newNode);
+ lazySetNext(t, newNode);
t = newNode;
}
}
if (h == null)
- h = t = new Node<E>(null);
+ h = t = newNode(null);
head = h;
tail = t;
}
@@ -302,8 +285,9 @@
* as sentinel for succ(), below.
*/
final void updateHead(Node<E> h, Node<E> p) {
+ // assert h != null && p != null && (h == p || h.item == null);
if (h != p && casHead(h, p))
- h.lazySetNext(h);
+ lazySetNext(h, h);
}
/**
@@ -324,14 +308,13 @@
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- checkNotNull(e);
- final Node<E> newNode = new Node<E>(e);
+ final Node<E> newNode = newNode(Objects.requireNonNull(e));
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {
// p is last node
- if (p.casNext(null, newNode)) {
+ if (casNext(p, null, newNode)) {
// Successful CAS is the linearization point
// for e to become an element of this queue,
// and for newNode to become "live".
@@ -359,7 +342,7 @@
for (Node<E> h = head, p = h, q;;) {
E item = p.item;
- if (item != null && p.casItem(item, null)) {
+ if (item != null && casItem(p, item, null)) {
// Successful CAS is the linearization point
// for item to be removed from this queue.
if (p != h) // hop two nodes at a time
@@ -446,13 +429,17 @@
* @return the number of elements in this queue
*/
public int size() {
- int count = 0;
- for (Node<E> p = first(); p != null; p = succ(p))
- if (p.item != null)
- // Collection.size() spec says to max out
- if (++count == Integer.MAX_VALUE)
- break;
- return count;
+ restartFromHead: for (;;) {
+ int count = 0;
+ for (Node<E> p = first(); p != null;) {
+ if (p.item != null)
+ if (++count == Integer.MAX_VALUE)
+ break; // @see Collection.size()
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ return count;
+ }
}
/**
@@ -464,11 +451,12 @@
* @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
- if (o == null) return false;
- for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null && o.equals(item))
- return true;
+ if (o != null) {
+ for (Node<E> p = first(); p != null; p = succ(p)) {
+ E item = p.item;
+ if (item != null && o.equals(item))
+ return true;
+ }
}
return false;
}
@@ -485,19 +473,25 @@
* @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
- if (o == null) return false;
- Node<E> pred = null;
- for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null &&
- o.equals(item) &&
- p.casItem(item, null)) {
- Node<E> next = succ(p);
- if (pred != null && next != null)
- pred.casNext(p, next);
- return true;
+ if (o != null) {
+ Node<E> next, pred = null;
+ for (Node<E> p = first(); p != null; pred = p, p = next) {
+ boolean removed = false;
+ E item = p.item;
+ if (item != null) {
+ if (!o.equals(item)) {
+ next = succ(p);
+ continue;
+ }
+ removed = casItem(p, item, null);
+ }
+
+ next = succ(p);
+ if (pred != null && next != null) // unlink
+ casNext(pred, p, next);
+ if (removed)
+ return true;
}
- pred = p;
}
return false;
}
@@ -522,12 +516,11 @@
// Copy c into a private chain of Nodes
Node<E> beginningOfTheEnd = null, last = null;
for (E e : c) {
- checkNotNull(e);
- Node<E> newNode = new Node<E>(e);
+ Node<E> newNode = newNode(Objects.requireNonNull(e));
if (beginningOfTheEnd == null)
beginningOfTheEnd = last = newNode;
else {
- last.lazySetNext(newNode);
+ lazySetNext(last, newNode);
last = newNode;
}
}
@@ -539,7 +532,7 @@
Node<E> q = p.next;
if (q == null) {
// p is last node
- if (p.casNext(null, beginningOfTheEnd)) {
+ if (casNext(p, null, beginningOfTheEnd)) {
// Successful CAS is the linearization point
// for all elements to be added to this queue.
if (!casTail(t, last)) {
@@ -565,6 +558,62 @@
}
}
+ public String toString() {
+ String[] a = null;
+ restartFromHead: for (;;) {
+ int charLength = 0;
+ int size = 0;
+ for (Node<E> p = first(); p != null;) {
+ E item = p.item;
+ if (item != null) {
+ if (a == null)
+ a = new String[4];
+ else if (size == a.length)
+ a = Arrays.copyOf(a, 2 * size);
+ String s = item.toString();
+ a[size++] = s;
+ charLength += s.length();
+ }
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+
+ if (size == 0)
+ return "[]";
+
+ return Helpers.toString(a, size, charLength);
+ }
+ }
+
+ private Object[] toArrayInternal(Object[] a) {
+ Object[] x = a;
+ restartFromHead: for (;;) {
+ int size = 0;
+ for (Node<E> p = first(); p != null;) {
+ E item = p.item;
+ if (item != null) {
+ if (x == null)
+ x = new Object[4];
+ else if (size == x.length)
+ x = Arrays.copyOf(x, 2 * (size + 4));
+ x[size++] = item;
+ }
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ if (x == null)
+ return new Object[0];
+ else if (a != null && size <= a.length) {
+ if (a != x)
+ System.arraycopy(x, 0, a, 0, size);
+ if (size < a.length)
+ a[size] = null;
+ return a;
+ }
+ return (size == x.length) ? x : Arrays.copyOf(x, size);
+ }
+ }
+
/**
* Returns an array containing all of the elements in this queue, in
* proper sequence.
@@ -579,14 +628,7 @@
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
- // Use ArrayList to deal with resizing.
- ArrayList<E> al = new ArrayList<E>();
- for (Node<E> p = first(); p != null; p = succ(p)) {
- E item = p.item;
- if (item != null)
- al.add(item);
- }
- return al.toArray();
+ return toArrayInternal(null);
}
/**
@@ -610,7 +652,7 @@
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -626,28 +668,8 @@
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- // try to use sent-in array
- int k = 0;
- Node<E> p;
- for (p = first(); p != null && k < a.length; p = succ(p)) {
- E item = p.item;
- if (item != null)
- a[k++] = (T)item;
- }
- if (p == null) {
- if (k < a.length)
- a[k] = null;
- return a;
- }
-
- // If won't fit, use ArrayList version
- ArrayList<E> al = new ArrayList<E>();
- for (Node<E> q = first(); q != null; q = succ(q)) {
- E item = q.item;
- if (item != null)
- al.add(item);
- }
- return al.toArray(a);
+ if (a == null) throw new NullPointerException();
+ return (T[]) toArrayInternal(a);
}
/**
@@ -683,54 +705,47 @@
private Node<E> lastRet;
Itr() {
- advance();
- }
-
- /**
- * Moves to next valid node and returns item to return for
- * next(), or null if no such.
- */
- private E advance() {
- lastRet = nextNode;
- E x = nextItem;
-
- Node<E> pred, p;
- if (nextNode == null) {
- p = first();
- pred = null;
- } else {
- pred = nextNode;
- p = succ(nextNode);
- }
-
- for (;;) {
- if (p == null) {
- nextNode = null;
- nextItem = null;
- return x;
+ restartFromHead: for (;;) {
+ Node<E> h, p, q;
+ for (p = h = head;; p = q) {
+ E item;
+ if ((item = p.item) != null) {
+ nextNode = p;
+ nextItem = item;
+ break;
+ }
+ else if ((q = p.next) == null)
+ break;
+ else if (p == q)
+ continue restartFromHead;
}
- E item = p.item;
- if (item != null) {
- nextNode = p;
- nextItem = item;
- return x;
- } else {
- // skip over nulls
- Node<E> next = succ(p);
- if (pred != null && next != null)
- pred.casNext(p, next);
- p = next;
- }
+ updateHead(h, p);
+ return;
}
}
public boolean hasNext() {
- return nextNode != null;
+ return nextItem != null;
}
public E next() {
- if (nextNode == null) throw new NoSuchElementException();
- return advance();
+ final Node<E> pred = nextNode;
+ if (pred == null) throw new NoSuchElementException();
+ // assert nextItem != null;
+ lastRet = pred;
+ E item = null;
+
+ for (Node<E> p = succ(pred), q;; p = q) {
+ if (p == null || (item = p.item) != null) {
+ nextNode = p;
+ E x = nextItem;
+ nextItem = item;
+ return x;
+ }
+ // unlink deleted nodes
+ if ((q = succ(p)) != null)
+ casNext(pred, p, q);
+ }
}
public void remove() {
@@ -780,19 +795,18 @@
// Read in elements until trailing null sentinel found
Node<E> h = null, t = null;
- Object item;
- while ((item = s.readObject()) != null) {
+ for (Object item; (item = s.readObject()) != null; ) {
@SuppressWarnings("unchecked")
- Node<E> newNode = new Node<E>((E) item);
+ Node<E> newNode = newNode((E) item);
if (h == null)
h = t = newNode;
else {
- t.lazySetNext(newNode);
+ lazySetNext(t, newNode);
t = newNode;
}
}
if (h == null)
- h = t = new Node<E>(null);
+ h = t = newNode(null);
head = h;
tail = t;
}
@@ -829,8 +843,9 @@
if (i > 0) {
batch = i;
return Spliterators.spliterator
- (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT);
+ (a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
}
return null;
@@ -904,38 +919,32 @@
return new CLQSpliterator<E>(this);
}
- /**
- * Throws NullPointerException if argument is null.
- *
- * @param v the element
- */
- private static void checkNotNull(Object v) {
- if (v == null)
- throw new NullPointerException();
- }
-
private boolean casTail(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+ return U.compareAndSwapObject(this, TAIL, cmp, val);
}
private boolean casHead(Node<E> cmp, Node<E> val) {
- return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+ return U.compareAndSwapObject(this, HEAD, cmp, val);
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long headOffset;
- private static final long tailOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long HEAD;
+ private static final long TAIL;
+ private static final long ITEM;
+ private static final long NEXT;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ConcurrentLinkedQueue.class;
- headOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("head"));
- tailOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("tail"));
- } catch (Exception e) {
+ HEAD = U.objectFieldOffset
+ (ConcurrentLinkedQueue.class.getDeclaredField("head"));
+ TAIL = U.objectFieldOffset
+ (ConcurrentLinkedQueue.class.getDeclaredField("tail"));
+ ITEM = U.objectFieldOffset
+ (Node.class.getDeclaredField("item"));
+ NEXT = U.objectFieldOffset
+ (Node.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -89,7 +89,7 @@
return ((v = get(key)) != null) ? v : defaultValue;
}
- /**
+ /**
* {@inheritDoc}
*
* @implSpec The default implementation is equivalent to, for this
@@ -181,10 +181,10 @@
* is not supported by this map
* @throws ClassCastException if the key or value is of an inappropriate
* type for this map
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified key or value is null,
* and this map does not permit null keys or values
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
*/
boolean remove(Object key, Object value);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentNavigableMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentNavigableMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,7 +34,9 @@
*/
package java.util.concurrent;
-import java.util.*;
+
+import java.util.NavigableMap;
+import java.util.NavigableSet;
/**
* A {@link ConcurrentMap} supporting {@link NavigableMap} operations,
@@ -101,7 +103,7 @@
* reflected in the descending map, and vice-versa.
*
* <p>The returned map has an ordering equivalent to
- * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
+ * {@link java.util.Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code m.descendingMap().descendingMap()} returns a
* view of {@code m} essentially equivalent to {@code m}.
*
@@ -125,7 +127,7 @@
*
* @return a navigable set view of the keys in this map
*/
- public NavigableSet<K> navigableKeySet();
+ NavigableSet<K> navigableKeySet();
/**
* Returns a {@link NavigableSet} view of the keys contained in this map.
@@ -163,5 +165,5 @@
*
* @return a reverse order navigable set view of the keys in this map
*/
- public NavigableSet<K> descendingKeySet();
+ NavigableSet<K> descendingKeySet();
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractMap;
@@ -50,13 +51,10 @@
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
-import java.util.SortedSet;
import java.util.Spliterator;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
-import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -359,9 +357,9 @@
private static final long serialVersionUID = -8627078645895051609L;
/**
- * Special value used to identify base-level header
+ * Special value used to identify base-level header.
*/
- private static final Object BASE_HEADER = new Object();
+ static final Object BASE_HEADER = new Object();
/**
* The topmost head index of the skiplist.
@@ -377,11 +375,11 @@
final Comparator<? super K> comparator;
/** Lazily initialized key set */
- private transient KeySet<K> keySet;
+ private transient KeySet<K,V> keySet;
/** Lazily initialized entry set */
private transient EntrySet<K,V> entrySet;
/** Lazily initialized values collection */
- private transient Values<V> values;
+ private transient Values<K,V> values;
/** Lazily initialized descending key set */
private transient ConcurrentNavigableMap<K,V> descendingMap;
@@ -400,10 +398,10 @@
}
/**
- * compareAndSet head node
+ * compareAndSet head node.
*/
private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
- return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+ return U.compareAndSwapObject(this, HEAD, cmp, val);
}
/* ---------------- Nodes -------------- */
@@ -443,17 +441,17 @@
}
/**
- * compareAndSet value field
+ * compareAndSet value field.
*/
boolean casValue(Object cmp, Object val) {
- return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val);
+ return U.compareAndSwapObject(this, VALUE, cmp, val);
}
/**
- * compareAndSet next field
+ * compareAndSet next field.
*/
boolean casNext(Node<K,V> cmp, Node<K,V> val) {
- return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+ return U.compareAndSwapObject(this, NEXT, cmp, val);
}
/**
@@ -534,21 +532,19 @@
return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
}
- // UNSAFE mechanics
+ // Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long valueOffset;
- private static final long nextOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long VALUE;
+ private static final long NEXT;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = Node.class;
- valueOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("value"));
- nextOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("next"));
- } catch (Exception e) {
+ VALUE = U.objectFieldOffset
+ (Node.class.getDeclaredField("value"));
+ NEXT = U.objectFieldOffset
+ (Node.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -578,10 +574,10 @@
}
/**
- * compareAndSet right field
+ * compareAndSet right field.
*/
final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
- return UNSAFE.compareAndSwapObject(this, rightOffset, cmp, val);
+ return U.compareAndSwapObject(this, RIGHT, cmp, val);
}
/**
@@ -618,15 +614,13 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long rightOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long RIGHT;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = Index.class;
- rightOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("right"));
- } catch (Exception e) {
+ RIGHT = U.objectFieldOffset
+ (Index.class.getDeclaredField("right"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -730,10 +724,10 @@
*
* The traversal loops in doPut, doRemove, and findNear all
* include the same three kinds of checks. And specialized
- * versions appear in findFirst, and findLast and their
- * variants. They can't easily share code because each uses the
- * reads of fields held in locals occurring in the orders they
- * were performed.
+ * versions appear in findFirst, and findLast and their variants.
+ * They can't easily share code because each uses the reads of
+ * fields held in locals occurring in the orders they were
+ * performed.
*
* @param key the key
* @return node holding key, or null if no such
@@ -1364,7 +1358,7 @@
// Track the current rightmost node at each level. Uses an
// ArrayList to avoid committing to initial or maximum level.
- ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+ ArrayList<Index<K,V>> preds = new ArrayList<>();
// initialize
for (int i = 0; i <= h.level; ++i)
@@ -1461,12 +1455,12 @@
* distinct because readObject calls can't be nicely adapted
* as the kind of iterator needed by buildFromSorted. (They
* can be, but doing so requires type cheats and/or creation
- * of adaptor classes.) It is simpler to just adapt the code.
+ * of adapter classes.) It is simpler to just adapt the code.
*/
HeadIndex<K,V> h = head;
Node<K,V> basepred = h.node;
- ArrayList<Index<K,V>> preds = new ArrayList<Index<K,V>>();
+ ArrayList<Index<K,V>> preds = new ArrayList<>();
for (int i = 0; i <= h.level; ++i)
preds.add(null);
Index<K,V> q = h;
@@ -1833,13 +1827,13 @@
* @return a navigable set view of the keys in this map
*/
public NavigableSet<K> keySet() {
- KeySet<K> ks = keySet;
- return (ks != null) ? ks : (keySet = new KeySet<K>(this));
+ KeySet<K,V> ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet<>(this));
}
public NavigableSet<K> navigableKeySet() {
- KeySet<K> ks = keySet;
- return (ks != null) ? ks : (keySet = new KeySet<K>(this));
+ KeySet<K,V> ks = keySet;
+ return (ks != null) ? ks : (keySet = new KeySet<>(this));
}
/**
@@ -1862,8 +1856,8 @@
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
*/
public Collection<V> values() {
- Values<V> vs = values;
- return (vs != null) ? vs : (values = new Values<V>(this));
+ Values<K,V> vs = values;
+ return (vs != null) ? vs : (values = new Values<>(this));
}
/**
@@ -2346,20 +2340,6 @@
}
}
- // Factory methods for iterators needed by ConcurrentSkipListSet etc
-
- Iterator<K> keyIterator() {
- return new KeyIterator();
- }
-
- Iterator<V> valueIterator() {
- return new ValueIterator();
- }
-
- Iterator<Map.Entry<K,V>> entryIterator() {
- return new EntryIterator();
- }
-
/* ---------------- View Classes -------------- */
/*
@@ -2376,36 +2356,34 @@
return list;
}
- static final class KeySet<E>
- extends AbstractSet<E> implements NavigableSet<E> {
- final ConcurrentNavigableMap<E,?> m;
- KeySet(ConcurrentNavigableMap<E,?> map) { m = map; }
+ static final class KeySet<K,V>
+ extends AbstractSet<K> implements NavigableSet<K> {
+ final ConcurrentNavigableMap<K,V> m;
+ KeySet(ConcurrentNavigableMap<K,V> map) { m = map; }
public int size() { return m.size(); }
public boolean isEmpty() { return m.isEmpty(); }
public boolean contains(Object o) { return m.containsKey(o); }
public boolean remove(Object o) { return m.remove(o) != null; }
public void clear() { m.clear(); }
- public E lower(E e) { return m.lowerKey(e); }
- public E floor(E e) { return m.floorKey(e); }
- public E ceiling(E e) { return m.ceilingKey(e); }
- public E higher(E e) { return m.higherKey(e); }
- public Comparator<? super E> comparator() { return m.comparator(); }
- public E first() { return m.firstKey(); }
- public E last() { return m.lastKey(); }
- public E pollFirst() {
- Map.Entry<E,?> e = m.pollFirstEntry();
+ public K lower(K e) { return m.lowerKey(e); }
+ public K floor(K e) { return m.floorKey(e); }
+ public K ceiling(K e) { return m.ceilingKey(e); }
+ public K higher(K e) { return m.higherKey(e); }
+ public Comparator<? super K> comparator() { return m.comparator(); }
+ public K first() { return m.firstKey(); }
+ public K last() { return m.lastKey(); }
+ public K pollFirst() {
+ Map.Entry<K,V> e = m.pollFirstEntry();
return (e == null) ? null : e.getKey();
}
- public E pollLast() {
- Map.Entry<E,?> e = m.pollLastEntry();
+ public K pollLast() {
+ Map.Entry<K,V> e = m.pollLastEntry();
return (e == null) ? null : e.getKey();
}
- @SuppressWarnings("unchecked")
- public Iterator<E> iterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<E,Object>)m).keyIterator();
- else
- return ((ConcurrentSkipListMap.SubMap<E,Object>)m).keyIterator();
+ public Iterator<K> iterator() {
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<K,V>)m).new KeyIterator()
+ : ((SubMap<K,V>)m).new SubMapKeyIterator();
}
public boolean equals(Object o) {
if (o == this)
@@ -2423,87 +2401,76 @@
}
public Object[] toArray() { return toList(this).toArray(); }
public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
- public Iterator<E> descendingIterator() {
+ public Iterator<K> descendingIterator() {
return descendingSet().iterator();
}
- public NavigableSet<E> subSet(E fromElement,
+ public NavigableSet<K> subSet(K fromElement,
boolean fromInclusive,
- E toElement,
+ K toElement,
boolean toInclusive) {
- return new KeySet<E>(m.subMap(fromElement, fromInclusive,
- toElement, toInclusive));
+ return new KeySet<>(m.subMap(fromElement, fromInclusive,
+ toElement, toInclusive));
}
- public NavigableSet<E> headSet(E toElement, boolean inclusive) {
- return new KeySet<E>(m.headMap(toElement, inclusive));
+ public NavigableSet<K> headSet(K toElement, boolean inclusive) {
+ return new KeySet<>(m.headMap(toElement, inclusive));
}
- public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
- return new KeySet<E>(m.tailMap(fromElement, inclusive));
+ public NavigableSet<K> tailSet(K fromElement, boolean inclusive) {
+ return new KeySet<>(m.tailMap(fromElement, inclusive));
}
- public NavigableSet<E> subSet(E fromElement, E toElement) {
+ public NavigableSet<K> subSet(K fromElement, K toElement) {
return subSet(fromElement, true, toElement, false);
}
- public NavigableSet<E> headSet(E toElement) {
+ public NavigableSet<K> headSet(K toElement) {
return headSet(toElement, false);
}
- public NavigableSet<E> tailSet(E fromElement) {
+ public NavigableSet<K> tailSet(K fromElement) {
return tailSet(fromElement, true);
}
- public NavigableSet<E> descendingSet() {
- return new KeySet<E>(m.descendingMap());
+ public NavigableSet<K> descendingSet() {
+ return new KeySet<>(m.descendingMap());
}
- @SuppressWarnings("unchecked")
- public Spliterator<E> spliterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
- else
- return (Spliterator<E>)((SubMap<E,?>)m).keyIterator();
+
+ public Spliterator<K> spliterator() {
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<K,V>)m).keySpliterator()
+ : ((SubMap<K,V>)m).new SubMapKeyIterator();
}
}
- static final class Values<E> extends AbstractCollection<E> {
- final ConcurrentNavigableMap<?, E> m;
- Values(ConcurrentNavigableMap<?, E> map) {
+ static final class Values<K,V> extends AbstractCollection<V> {
+ final ConcurrentNavigableMap<K,V> m;
+ Values(ConcurrentNavigableMap<K,V> map) {
m = map;
}
- @SuppressWarnings("unchecked")
- public Iterator<E> iterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<?,E>)m).valueIterator();
- else
- return ((SubMap<?,E>)m).valueIterator();
- }
- public boolean isEmpty() {
- return m.isEmpty();
+ public Iterator<V> iterator() {
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<K,V>)m).new ValueIterator()
+ : ((SubMap<K,V>)m).new SubMapValueIterator();
}
- public int size() {
- return m.size();
- }
- public boolean contains(Object o) {
- return m.containsValue(o);
- }
- public void clear() {
- m.clear();
- }
+ public int size() { return m.size(); }
+ public boolean isEmpty() { return m.isEmpty(); }
+ public boolean contains(Object o) { return m.containsValue(o); }
+ public void clear() { m.clear(); }
public Object[] toArray() { return toList(this).toArray(); }
public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
- @SuppressWarnings("unchecked")
- public Spliterator<E> spliterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<?,E>)m).valueSpliterator();
- else
- return (Spliterator<E>)((SubMap<?,E>)m).valueIterator();
+
+ public Spliterator<V> spliterator() {
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<K,V>)m).valueSpliterator()
+ : ((SubMap<K,V>)m).new SubMapValueIterator();
}
- public boolean removeIf(Predicate<? super E> filter) {
+
+ public boolean removeIf(Predicate<? super V> filter) {
if (filter == null) throw new NullPointerException();
if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<?,E>)m).removeValueIf(filter);
+ return ((ConcurrentSkipListMap<K,V>)m).removeValueIf(filter);
// else use iterator
- @SuppressWarnings("unchecked") Iterator<Map.Entry<Object,E>> it =
- ((SubMap<Object,E>)m).entryIterator();
+ Iterator<Map.Entry<K,V>> it =
+ ((SubMap<K,V>)m).new SubMapEntryIterator();
boolean removed = false;
while (it.hasNext()) {
- Map.Entry<Object,E> e = it.next();
- E v = e.getValue();
+ Map.Entry<K,V> e = it.next();
+ V v = e.getValue();
if (filter.test(v) && m.remove(e.getKey(), v))
removed = true;
}
@@ -2511,24 +2478,22 @@
}
}
- static final class EntrySet<K1,V1> extends AbstractSet<Map.Entry<K1,V1>> {
- final ConcurrentNavigableMap<K1, V1> m;
- EntrySet(ConcurrentNavigableMap<K1, V1> map) {
+ static final class EntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> {
+ final ConcurrentNavigableMap<K,V> m;
+ EntrySet(ConcurrentNavigableMap<K,V> map) {
m = map;
}
- @SuppressWarnings("unchecked")
- public Iterator<Map.Entry<K1,V1>> iterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<K1,V1>)m).entryIterator();
- else
- return ((SubMap<K1,V1>)m).entryIterator();
+ public Iterator<Map.Entry<K,V>> iterator() {
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<K,V>)m).new EntryIterator()
+ : ((SubMap<K,V>)m).new SubMapEntryIterator();
}
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
- V1 v = m.get(e.getKey());
+ V v = m.get(e.getKey());
return v != null && v.equals(e.getValue());
}
public boolean remove(Object o) {
@@ -2563,23 +2528,22 @@
}
public Object[] toArray() { return toList(this).toArray(); }
public <T> T[] toArray(T[] a) { return toList(this).toArray(a); }
- @SuppressWarnings("unchecked")
- public Spliterator<Map.Entry<K1,V1>> spliterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<K1,V1>)m).entrySpliterator();
- else
- return (Spliterator<Map.Entry<K1,V1>>)
- ((SubMap<K1,V1>)m).entryIterator();
+
+ public Spliterator<Map.Entry<K,V>> spliterator() {
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<K,V>)m).entrySpliterator()
+ : ((SubMap<K,V>)m).new SubMapEntryIterator();
}
- public boolean removeIf(Predicate<? super Entry<K1, V1>> filter) {
+ public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
if (filter == null) throw new NullPointerException();
if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<K1,V1>)m).removeEntryIf(filter);
+ return ((ConcurrentSkipListMap<K,V>)m).removeEntryIf(filter);
// else use iterator
- Iterator<Map.Entry<K1,V1>> it = ((SubMap<K1,V1>)m).entryIterator();
+ Iterator<Map.Entry<K,V>> it =
+ ((SubMap<K,V>)m).new SubMapEntryIterator();
boolean removed = false;
while (it.hasNext()) {
- Map.Entry<K1,V1> e = it.next();
+ Map.Entry<K,V> e = it.next();
if (filter.test(e) && m.remove(e.getKey(), e.getValue()))
removed = true;
}
@@ -2589,13 +2553,13 @@
/**
* Submaps returned by {@link ConcurrentSkipListMap} submap operations
- * represent a subrange of mappings of their underlying
- * maps. Instances of this class support all methods of their
- * underlying maps, differing in that mappings outside their range are
- * ignored, and attempts to add mappings outside their ranges result
- * in {@link IllegalArgumentException}. Instances of this class are
- * constructed only using the {@code subMap}, {@code headMap}, and
- * {@code tailMap} methods of their underlying maps.
+ * represent a subrange of mappings of their underlying maps.
+ * Instances of this class support all methods of their underlying
+ * maps, differing in that mappings outside their range are ignored,
+ * and attempts to add mappings outside their ranges result in {@link
+ * IllegalArgumentException}. Instances of this class are constructed
+ * only using the {@code subMap}, {@code headMap}, and {@code tailMap}
+ * methods of their underlying maps.
*
* @serial include
*/
@@ -2604,7 +2568,7 @@
private static final long serialVersionUID = -7647078645895051609L;
/** Underlying map */
- private final ConcurrentSkipListMap<K,V> m;
+ final ConcurrentSkipListMap<K,V> m;
/** lower bound key, or null if from start */
private final K lo;
/** upper bound key, or null if to end */
@@ -2614,10 +2578,10 @@
/** inclusion flag for hi */
private final boolean hiInclusive;
/** direction */
- private final boolean isDescending;
+ final boolean isDescending;
// Lazily initialized view holders
- private transient KeySet<K> keySetView;
+ private transient KeySet<K,V> keySetView;
private transient Set<Map.Entry<K,V>> entrySetView;
private transient Collection<V> valuesView;
@@ -2790,7 +2754,7 @@
}
/**
- * Submap version of ConcurrentSkipListMap.getNearEntry
+ * Submap version of ConcurrentSkipListMap.getNearEntry.
*/
Map.Entry<K,V> getNearEntry(K key, int rel) {
Comparator<? super K> cmp = m.comparator;
@@ -3085,18 +3049,18 @@
/* ---------------- Submap Views -------------- */
public NavigableSet<K> keySet() {
- KeySet<K> ks = keySetView;
- return (ks != null) ? ks : (keySetView = new KeySet<K>(this));
+ KeySet<K,V> ks = keySetView;
+ return (ks != null) ? ks : (keySetView = new KeySet<>(this));
}
public NavigableSet<K> navigableKeySet() {
- KeySet<K> ks = keySetView;
- return (ks != null) ? ks : (keySetView = new KeySet<K>(this));
+ KeySet<K,V> ks = keySetView;
+ return (ks != null) ? ks : (keySetView = new KeySet<>(this));
}
public Collection<V> values() {
Collection<V> vs = valuesView;
- return (vs != null) ? vs : (valuesView = new Values<V>(this));
+ return (vs != null) ? vs : (valuesView = new Values<>(this));
}
public Set<Map.Entry<K,V>> entrySet() {
@@ -3108,21 +3072,9 @@
return descendingMap().navigableKeySet();
}
- Iterator<K> keyIterator() {
- return new SubMapKeyIterator();
- }
-
- Iterator<V> valueIterator() {
- return new SubMapValueIterator();
- }
-
- Iterator<Map.Entry<K,V>> entryIterator() {
- return new SubMapEntryIterator();
- }
-
/**
* Variant of main Iter class to traverse through submaps.
- * Also serves as back-up Spliterator for views
+ * Also serves as back-up Spliterator for views.
*/
abstract class SubMapIter<T> implements Iterator<T>, Spliterator<T> {
/** the last node returned by next() */
@@ -3298,9 +3250,9 @@
}
/**
- * Helper method for EntrySet.removeIf
+ * Helper method for EntrySet.removeIf.
*/
- boolean removeEntryIf(Predicate<? super Entry<K, V>> function) {
+ boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
if (function == null) throw new NullPointerException();
boolean removed = false;
for (Node<K,V> n = findFirst(); n != null; n = n.next) {
@@ -3316,7 +3268,7 @@
}
/**
- * Helper method for Values.removeIf
+ * Helper method for Values.removeIf.
*/
boolean removeValueIf(Predicate<? super V> function) {
if (function == null) throw new NullPointerException();
@@ -3371,7 +3323,7 @@
super(comparator, row, origin, fence, est);
}
- public Spliterator<K> trySplit() {
+ public KeySpliterator<K,V> trySplit() {
Node<K,V> e; K ek;
Comparator<? super K> cmp = comparator;
K f = fence;
@@ -3459,7 +3411,7 @@
super(comparator, row, origin, fence, est);
}
- public Spliterator<V> trySplit() {
+ public ValueSpliterator<K,V> trySplit() {
Node<K,V> e; K ek;
Comparator<? super K> cmp = comparator;
K f = fence;
@@ -3546,7 +3498,7 @@
super(comparator, row, origin, fence, est);
}
- public Spliterator<Map.Entry<K,V>> trySplit() {
+ public EntrySpliterator<K,V> trySplit() {
Node<K,V> e; K ek;
Comparator<? super K> cmp = comparator;
K f = fence;
@@ -3644,20 +3596,13 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long headOffset;
- private static final long SECONDARY;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long HEAD;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ConcurrentSkipListMap.class;
- headOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("head"));
- Class<?> tk = Thread.class;
- SECONDARY = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
-
- } catch (Exception e) {
+ HEAD = U.objectFieldOffset
+ (ConcurrentSkipListMap.class.getDeclaredField("head"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
@@ -323,8 +324,9 @@
*
* @param c collection containing elements to be removed from this set
* @return {@code true} if this set changed as a result of the call
- * @throws ClassCastException if the types of one or more elements in this
- * set are incompatible with the specified collection
+ * @throws ClassCastException if the class of an element of this set
+ * is incompatible with the specified collection
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
@@ -384,7 +386,6 @@
/* ---------------- SortedSet operations -------------- */
-
public Comparator<? super E> comparator() {
return m.comparator();
}
@@ -498,28 +499,24 @@
* @return a {@code Spliterator} over the elements in this set
* @since 1.8
*/
- @SuppressWarnings("unchecked")
public Spliterator<E> spliterator() {
- if (m instanceof ConcurrentSkipListMap)
- return ((ConcurrentSkipListMap<E,?>)m).keySpliterator();
- else
- return (Spliterator<E>)((ConcurrentSkipListMap.SubMap<E,?>)m).keyIterator();
+ return (m instanceof ConcurrentSkipListMap)
+ ? ((ConcurrentSkipListMap<E,?>)m).keySpliterator()
+ : ((ConcurrentSkipListMap.SubMap<E,?>)m).new SubMapKeyIterator();
}
// Support for resetting map in clone
private void setMap(ConcurrentNavigableMap<E,Object> map) {
- UNSAFE.putObjectVolatile(this, mapOffset, map);
+ U.putObjectVolatile(this, MAP, map);
}
- private static final sun.misc.Unsafe UNSAFE;
- private static final long mapOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long MAP;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ConcurrentSkipListSet.class;
- mapOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("m"));
- } catch (Exception e) {
+ MAP = U.objectFieldOffset
+ (ConcurrentSkipListSet.class.getDeclaredField("m"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Tue Oct 20 08:24:37 2015 -0700
@@ -33,6 +33,7 @@
*/
package java.util.concurrent;
+
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collection;
@@ -46,7 +47,6 @@
import java.util.RandomAccess;
import java.util.Spliterator;
import java.util.Spliterators;
-import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
@@ -86,14 +86,17 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this list
*/
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
private static final long serialVersionUID = 8673264195747942595L;
- /** The lock protecting all mutators */
- final transient ReentrantLock lock = new ReentrantLock();
+ /**
+ * The lock protecting all mutators. (We have a mild preference
+ * for builtin monitors over ReentrantLock when either will do.)
+ */
+ final transient Object lock = new Object();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
@@ -172,13 +175,6 @@
}
/**
- * Tests for equality, coping with nulls.
- */
- private static boolean eq(Object o1, Object o2) {
- return (o1 == null) ? o2 == null : o1.equals(o2);
- }
-
- /**
* static version of indexOf, to allow repeated calls without
* needing to re-acquire array each time.
* @param o element to search for
@@ -224,8 +220,7 @@
/**
* Returns {@code true} if this list contains the specified element.
* More formally, returns {@code true} if and only if this list contains
- * at least one element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>.
+ * at least one element {@code e} such that {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this list is to be tested
* @return {@code true} if this list contains the specified element
@@ -248,7 +243,7 @@
* this list, searching forwards from {@code index}, or returns -1 if
* the element is not found.
* More formally, returns the lowest index {@code i} such that
- * <tt>(i >= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>,
+ * {@code i >= index && Objects.equals(get(i), e)},
* or -1 if there is no such index.
*
* @param e element to search for
@@ -276,7 +271,7 @@
* this list, searching backwards from {@code index}, or returns -1 if
* the element is not found.
* More formally, returns the highest index {@code i} such that
- * <tt>(i <= index && (e==null ? get(i)==null : e.equals(get(i))))</tt>,
+ * {@code i <= index && Objects.equals(get(i), e)},
* or -1 if there is no such index.
*
* @param e element to search for
@@ -353,7 +348,7 @@
* The following code can be used to dump the list into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -368,7 +363,7 @@
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
- public <T> T[] toArray(T a[]) {
+ public <T> T[] toArray(T[] a) {
Object[] elements = getArray();
int len = elements.length;
if (a.length < len)
@@ -388,6 +383,10 @@
return (E) a[index];
}
+ static String outOfBounds(int index, int size) {
+ return "Index: " + index + ", Size: " + size;
+ }
+
/**
* {@inheritDoc}
*
@@ -404,9 +403,7 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E set(int index, E element) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
E oldValue = get(elements, index);
@@ -420,8 +417,6 @@
setArray(elements);
}
return oldValue;
- } finally {
- lock.unlock();
}
}
@@ -432,17 +427,13 @@
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
- } finally {
- lock.unlock();
}
}
@@ -454,14 +445,11 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
if (index > len || index < 0)
- throw new IndexOutOfBoundsException("Index: "+index+
- ", Size: "+len);
+ throw new IndexOutOfBoundsException(outOfBounds(index, len));
Object[] newElements;
int numMoved = len - index;
if (numMoved == 0)
@@ -474,8 +462,6 @@
}
newElements[index] = element;
setArray(newElements);
- } finally {
- lock.unlock();
}
}
@@ -487,9 +473,7 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E remove(int index) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
E oldValue = get(elements, index);
@@ -504,8 +488,6 @@
setArray(newElements);
}
return oldValue;
- } finally {
- lock.unlock();
}
}
@@ -513,8 +495,7 @@
* Removes the first occurrence of the specified element from this list,
* if it is present. If this list does not contain the element, it is
* unchanged. More formally, removes the element with the lowest index
- * {@code i} such that
- * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
+ * {@code i} such that {@code Objects.equals(o, get(i))}
* (if such an element exists). Returns {@code true} if this list
* contained the specified element (or equivalently, if this list
* changed as a result of the call).
@@ -533,15 +514,14 @@
* recent snapshot contains o at the given index.
*/
private boolean remove(Object o, Object[] snapshot, int index) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] current = getArray();
int len = current.length;
if (snapshot != current) findIndex: {
int prefix = Math.min(index, len);
for (int i = 0; i < prefix; i++) {
- if (current[i] != snapshot[i] && eq(o, current[i])) {
+ if (current[i] != snapshot[i]
+ && Objects.equals(o, current[i])) {
index = i;
break findIndex;
}
@@ -561,8 +541,6 @@
len - index - 1);
setArray(newElements);
return true;
- } finally {
- lock.unlock();
}
}
@@ -579,9 +557,7 @@
* ({@code fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
*/
void removeRange(int fromIndex, int toIndex) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
@@ -598,8 +574,6 @@
fromIndex, numMoved);
setArray(newElements);
}
- } finally {
- lock.unlock();
}
}
@@ -620,16 +594,15 @@
* recent snapshot does not contain e.
*/
private boolean addIfAbsent(E e, Object[] snapshot) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] current = getArray();
int len = current.length;
if (snapshot != current) {
// Optimize for lost race to another addXXX operation
int common = Math.min(snapshot.length, len);
for (int i = 0; i < common; i++)
- if (current[i] != snapshot[i] && eq(e, current[i]))
+ if (current[i] != snapshot[i]
+ && Objects.equals(e, current[i]))
return false;
if (indexOf(e, current, common, len) >= 0)
return false;
@@ -638,8 +611,6 @@
newElements[len] = e;
setArray(newElements);
return true;
- } finally {
- lock.unlock();
}
}
@@ -672,18 +643,16 @@
* @return {@code true} if this list changed as a result of the call
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list contains a null element and the
* specified collection does not permit null elements
- * (<a href="../Collection.html#optional-restrictions">optional</a>),
+ * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
*/
public boolean removeAll(Collection<?> c) {
if (c == null) throw new NullPointerException();
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
if (len != 0) {
@@ -701,8 +670,6 @@
}
}
return false;
- } finally {
- lock.unlock();
}
}
@@ -715,18 +682,16 @@
* @return {@code true} if this list changed as a result of the call
* @throws ClassCastException if the class of an element of this list
* is incompatible with the specified collection
- * (<a href="../Collection.html#optional-restrictions">optional</a>)
+ * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this list contains a null element and the
* specified collection does not permit null elements
- * (<a href="../Collection.html#optional-restrictions">optional</a>),
+ * (<a href="{@docRoot}/../api/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
*/
public boolean retainAll(Collection<?> c) {
if (c == null) throw new NullPointerException();
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
if (len != 0) {
@@ -744,8 +709,6 @@
}
}
return false;
- } finally {
- lock.unlock();
}
}
@@ -764,9 +727,7 @@
Object[] cs = c.toArray();
if (cs.length == 0)
return 0;
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
int added = 0;
@@ -783,8 +744,6 @@
setArray(newElements);
}
return added;
- } finally {
- lock.unlock();
}
}
@@ -793,12 +752,8 @@
* The list will be empty after this call returns.
*/
public void clear() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
setArray(new Object[0]);
- } finally {
- lock.unlock();
}
}
@@ -817,9 +772,7 @@
((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();
if (cs.length == 0)
return false;
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
if (len == 0 && cs.getClass() == Object[].class)
@@ -830,8 +783,6 @@
setArray(newElements);
}
return true;
- } finally {
- lock.unlock();
}
}
@@ -853,14 +804,11 @@
*/
public boolean addAll(int index, Collection<? extends E> c) {
Object[] cs = c.toArray();
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
if (index > len || index < 0)
- throw new IndexOutOfBoundsException("Index: "+index+
- ", Size: "+len);
+ throw new IndexOutOfBoundsException(outOfBounds(index, len));
if (cs.length == 0)
return false;
int numMoved = len - index;
@@ -877,52 +825,47 @@
System.arraycopy(cs, 0, newElements, index, cs.length);
setArray(newElements);
return true;
- } finally {
- lock.unlock();
}
}
public void forEach(Consumer<? super E> action) {
if (action == null) throw new NullPointerException();
- Object[] elements = getArray();
- int len = elements.length;
- for (int i = 0; i < len; ++i) {
- @SuppressWarnings("unchecked") E e = (E) elements[i];
+ for (Object x : getArray()) {
+ @SuppressWarnings("unchecked") E e = (E) x;
action.accept(e);
}
}
public boolean removeIf(Predicate<? super E> filter) {
if (filter == null) throw new NullPointerException();
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- Object[] elements = getArray();
- int len = elements.length;
- if (len != 0) {
- int newlen = 0;
- Object[] temp = new Object[len];
- for (int i = 0; i < len; ++i) {
- @SuppressWarnings("unchecked") E e = (E) elements[i];
- if (!filter.test(e))
- temp[newlen++] = e;
- }
- if (newlen != len) {
- setArray(Arrays.copyOf(temp, newlen));
+ synchronized (lock) {
+ final Object[] elements = getArray();
+ final int len = elements.length;
+ int i;
+ for (i = 0; i < len; i++) {
+ @SuppressWarnings("unchecked") E e = (E) elements[i];
+ if (filter.test(e)) {
+ int newlen = i;
+ final Object[] newElements = new Object[len - 1];
+ System.arraycopy(elements, 0, newElements, 0, newlen);
+ for (i++; i < len; i++) {
+ @SuppressWarnings("unchecked") E x = (E) elements[i];
+ if (!filter.test(x))
+ newElements[newlen++] = x;
+ }
+ setArray((newlen == len - 1)
+ ? newElements // one match => one copy
+ : Arrays.copyOf(newElements, newlen));
return true;
}
}
- return false;
- } finally {
- lock.unlock();
+ return false; // zero matches => zero copies
}
}
public void replaceAll(UnaryOperator<E> operator) {
if (operator == null) throw new NullPointerException();
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
@@ -931,22 +874,16 @@
newElements[i] = operator.apply(e);
}
setArray(newElements);
- } finally {
- lock.unlock();
}
}
public void sort(Comparator<? super E> c) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
Object[] newElements = Arrays.copyOf(elements, elements.length);
@SuppressWarnings("unchecked") E[] es = (E[])newElements;
Arrays.sort(es, c);
setArray(newElements);
- } finally {
- lock.unlock();
}
}
@@ -1022,7 +959,7 @@
* be the same if they have the same length and corresponding
* elements at the same position in the sequence are <em>equal</em>.
* Two elements {@code e1} and {@code e2} are considered
- * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
+ * <em>equal</em> if {@code Objects.equals(e1, e2)}.
*
* @param o the object to be compared for equality with this list
* @return {@code true} if the specified object is equal to this list
@@ -1033,12 +970,11 @@
if (!(o instanceof List))
return false;
- List<?> list = (List<?>)(o);
+ List<?> list = (List<?>)o;
Iterator<?> it = list.iterator();
Object[] elements = getArray();
- int len = elements.length;
- for (int i = 0; i < len; ++i)
- if (!it.hasNext() || !eq(elements[i], it.next()))
+ for (int i = 0, len = elements.length; i < len; i++)
+ if (!it.hasNext() || !Objects.equals(elements[i], it.next()))
return false;
if (it.hasNext())
return false;
@@ -1054,12 +990,8 @@
*/
public int hashCode() {
int hashCode = 1;
- Object[] elements = getArray();
- int len = elements.length;
- for (int i = 0; i < len; ++i) {
- Object obj = elements[i];
- hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
- }
+ for (Object x : getArray())
+ hashCode = 31 * hashCode + (x == null ? 0 : x.hashCode());
return hashCode;
}
@@ -1103,7 +1035,7 @@
Object[] elements = getArray();
int len = elements.length;
if (index < 0 || index > len)
- throw new IndexOutOfBoundsException("Index: "+index);
+ throw new IndexOutOfBoundsException(outOfBounds(index, len));
return new COWIterator<E>(elements, index);
}
@@ -1133,7 +1065,7 @@
/** Index of element to be returned by subsequent call to next. */
private int cursor;
- private COWIterator(Object[] elements, int initialCursor) {
+ COWIterator(Object[] elements, int initialCursor) {
cursor = initialCursor;
snapshot = elements;
}
@@ -1196,13 +1128,12 @@
}
@Override
+ @SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
- Object[] elements = snapshot;
- final int size = elements.length;
+ final int size = snapshot.length;
for (int i = cursor; i < size; i++) {
- @SuppressWarnings("unchecked") E e = (E) elements[i];
- action.accept(e);
+ action.accept((E) snapshot[i]);
}
cursor = size;
}
@@ -1224,16 +1155,12 @@
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public List<E> subList(int fromIndex, int toIndex) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
+ synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
throw new IndexOutOfBoundsException();
return new COWSubList<E>(this, fromIndex, toIndex);
- } finally {
- lock.unlock();
}
}
@@ -1264,6 +1191,7 @@
// only call this holding l's lock
COWSubList(CopyOnWriteArrayList<E> list,
int fromIndex, int toIndex) {
+ // assert Thread.holdsLock(list.lock);
l = list;
expectedArray = l.getArray();
offset = fromIndex;
@@ -1272,94 +1200,72 @@
// only call this holding l's lock
private void checkForComodification() {
+ // assert Thread.holdsLock(l.lock);
if (l.getArray() != expectedArray)
throw new ConcurrentModificationException();
}
// only call this holding l's lock
private void rangeCheck(int index) {
+ // assert Thread.holdsLock(l.lock);
if (index < 0 || index >= size)
- throw new IndexOutOfBoundsException("Index: "+index+
- ",Size: "+size);
+ throw new IndexOutOfBoundsException(outOfBounds(index, size));
}
public E set(int index, E element) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
rangeCheck(index);
checkForComodification();
E x = l.set(index+offset, element);
expectedArray = l.getArray();
return x;
- } finally {
- lock.unlock();
}
}
public E get(int index) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
rangeCheck(index);
checkForComodification();
return l.get(index+offset);
- } finally {
- lock.unlock();
}
}
public int size() {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
checkForComodification();
return size;
- } finally {
- lock.unlock();
}
}
public void add(int index, E element) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
checkForComodification();
if (index < 0 || index > size)
- throw new IndexOutOfBoundsException();
+ throw new IndexOutOfBoundsException
+ (outOfBounds(index, size));
l.add(index+offset, element);
expectedArray = l.getArray();
size++;
- } finally {
- lock.unlock();
}
}
public void clear() {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
checkForComodification();
l.removeRange(offset, offset+size);
expectedArray = l.getArray();
size = 0;
- } finally {
- lock.unlock();
}
}
public E remove(int index) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
rangeCheck(index);
checkForComodification();
E result = l.remove(index+offset);
expectedArray = l.getArray();
size--;
return result;
- } finally {
- lock.unlock();
}
}
@@ -1372,41 +1278,29 @@
}
public Iterator<E> iterator() {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
checkForComodification();
return new COWSubListIterator<E>(l, 0, offset, size);
- } finally {
- lock.unlock();
}
}
public ListIterator<E> listIterator(int index) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
checkForComodification();
if (index < 0 || index > size)
- throw new IndexOutOfBoundsException("Index: "+index+
- ", Size: "+size);
+ throw new IndexOutOfBoundsException
+ (outOfBounds(index, size));
return new COWSubListIterator<E>(l, index, offset, size);
- } finally {
- lock.unlock();
}
}
public List<E> subList(int fromIndex, int toIndex) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
checkForComodification();
if (fromIndex < 0 || toIndex > size || fromIndex > toIndex)
throw new IndexOutOfBoundsException();
return new COWSubList<E>(l, fromIndex + offset,
toIndex + offset);
- } finally {
- lock.unlock();
}
}
@@ -1427,9 +1321,7 @@
public void replaceAll(UnaryOperator<E> operator) {
if (operator == null) throw new NullPointerException();
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
int lo = offset;
int hi = offset + size;
Object[] elements = expectedArray;
@@ -1444,15 +1336,11 @@
newElements[i] = operator.apply(e);
}
l.setArray(expectedArray = newElements);
- } finally {
- lock.unlock();
}
}
public void sort(Comparator<? super E> c) {
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
int lo = offset;
int hi = offset + size;
Object[] elements = expectedArray;
@@ -1465,17 +1353,13 @@
@SuppressWarnings("unchecked") E[] es = (E[])newElements;
Arrays.sort(es, lo, hi, c);
l.setArray(expectedArray = newElements);
- } finally {
- lock.unlock();
}
}
public boolean removeAll(Collection<?> c) {
if (c == null) throw new NullPointerException();
boolean removed = false;
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
int n = size;
if (n > 0) {
int lo = offset;
@@ -1504,8 +1388,6 @@
l.setArray(expectedArray = newElements);
}
}
- } finally {
- lock.unlock();
}
return removed;
}
@@ -1513,9 +1395,7 @@
public boolean retainAll(Collection<?> c) {
if (c == null) throw new NullPointerException();
boolean removed = false;
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
int n = size;
if (n > 0) {
int lo = offset;
@@ -1544,8 +1424,6 @@
l.setArray(expectedArray = newElements);
}
}
- } finally {
- lock.unlock();
}
return removed;
}
@@ -1553,9 +1431,7 @@
public boolean removeIf(Predicate<? super E> filter) {
if (filter == null) throw new NullPointerException();
boolean removed = false;
- final ReentrantLock lock = l.lock;
- lock.lock();
- try {
+ synchronized (l.lock) {
int n = size;
if (n > 0) {
int lo = offset;
@@ -1584,8 +1460,6 @@
l.setArray(expectedArray = newElements);
}
}
- } finally {
- lock.unlock();
}
return removed;
}
@@ -1658,29 +1532,26 @@
}
@Override
+ @SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
- int s = size;
- ListIterator<E> i = it;
- while (nextIndex() < s) {
- action.accept(i.next());
+ while (nextIndex() < size) {
+ action.accept(it.next());
}
}
}
// Support for resetting lock while deserializing
private void resetLock() {
- UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
+ U.putObjectVolatile(this, LOCK, new Object());
}
- private static final sun.misc.Unsafe UNSAFE;
- private static final long lockOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long LOCK;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = CopyOnWriteArrayList.class;
- lockOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("lock"));
- } catch (Exception e) {
+ LOCK = U.objectFieldOffset
+ (CopyOnWriteArrayList.class.getDeclaredField("lock"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,14 +34,16 @@
*/
package java.util.concurrent;
+
+import java.util.AbstractSet;
import java.util.Collection;
+import java.util.Iterator;
+import java.util.Objects;
import java.util.Set;
-import java.util.AbstractSet;
-import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.function.Consumer;
import java.util.function.Predicate;
-import java.util.function.Consumer;
/**
* A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
@@ -66,12 +68,12 @@
* copy-on-write set to maintain a set of Handler objects that
* perform some action upon state updates.
*
- * <pre> {@code
+ * <pre> {@code
* class Handler { void handle(); ... }
*
* class X {
* private final CopyOnWriteArraySet<Handler> handlers
- * = new CopyOnWriteArraySet<Handler>();
+ * = new CopyOnWriteArraySet<>();
* public void addHandler(Handler h) { handlers.add(h); }
*
* private long internalState;
@@ -91,7 +93,7 @@
* @see CopyOnWriteArrayList
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this set
*/
public class CopyOnWriteArraySet<E> extends AbstractSet<E>
implements java.io.Serializable {
@@ -146,8 +148,7 @@
/**
* Returns {@code true} if this set contains the specified element.
* More formally, returns {@code true} if and only if this set
- * contains an element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>.
+ * contains an element {@code e} such that {@code Objects.equals(o, e)}.
*
* @param o element whose presence in this set is to be tested
* @return {@code true} if this set contains the specified element
@@ -203,7 +204,7 @@
* The following code can be used to dump the set into a newly allocated
* array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -232,11 +233,10 @@
/**
* Removes the specified element from this set if it is present.
* More formally, removes an element {@code e} such that
- * <tt>(o==null ? e==null : o.equals(e))</tt>,
- * if this set contains such an element. Returns {@code true} if
- * this set contained the element (or equivalently, if this set
- * changed as a result of the call). (This set will not contain the
- * element once the call returns.)
+ * {@code Objects.equals(o, e)}, if this set contains such an element.
+ * Returns {@code true} if this set contained the element (or
+ * equivalently, if this set changed as a result of the call).
+ * (This set will not contain the element once the call returns.)
*
* @param o object to be removed from this set, if present
* @return {@code true} if this set contained the specified element
@@ -249,7 +249,7 @@
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element {@code e} to this set if
* the set contains no element {@code e2} such that
- * <tt>(e==null ? e2==null : e.equals(e2))</tt>.
+ * {@code Objects.equals(e, e2)}.
* If this set already contains the element, the call leaves the set
* unchanged and returns {@code false}.
*
@@ -273,7 +273,44 @@
* @see #contains(Object)
*/
public boolean containsAll(Collection<?> c) {
- return al.containsAll(c);
+ return (c instanceof Set)
+ ? compareSets(al.getArray(), (Set<?>) c) >= 0
+ : al.containsAll(c);
+ }
+
+ /**
+ * Tells whether the objects in snapshot (regarded as a set) are a
+ * superset of the given set.
+ *
+ * @return -1 if snapshot is not a superset, 0 if the two sets
+ * contain precisely the same elements, and 1 if snapshot is a
+ * proper superset of the given set
+ */
+ private static int compareSets(Object[] snapshot, Set<?> set) {
+ // Uses O(n^2) algorithm, that is only appropriate for small
+ // sets, which CopyOnWriteArraySets should be.
+ //
+ // Optimize up to O(n) if the two sets share a long common prefix,
+ // as might happen if one set was created as a copy of the other set.
+
+ final int len = snapshot.length;
+ // Mark matched elements to avoid re-checking
+ final boolean[] matched = new boolean[len];
+
+ // j is the largest int with matched[i] true for { i | 0 <= i < j }
+ int j = 0;
+ outer: for (Object x : set) {
+ for (int i = j; i < len; i++) {
+ if (!matched[i] && Objects.equals(x, snapshot[i])) {
+ matched[i] = true;
+ if (i == j)
+ do { j++; } while (j < len && matched[j]);
+ continue outer;
+ }
+ }
+ return -1;
+ }
+ return (j == len) ? 0 : 1;
}
/**
@@ -302,9 +339,11 @@
* @param c collection containing elements to be removed from this set
* @return {@code true} if this set changed as a result of the call
* @throws ClassCastException if the class of an element of this set
- * is incompatible with the specified collection (optional)
+ * is incompatible with the specified collection
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this set contains a null element and the
- * specified collection does not permit null elements (optional),
+ * specified collection does not permit null elements
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
*/
@@ -323,9 +362,11 @@
* @param c collection containing elements to be retained in this set
* @return {@code true} if this set changed as a result of the call
* @throws ClassCastException if the class of an element of this set
- * is incompatible with the specified collection (optional)
+ * is incompatible with the specified collection
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>)
* @throws NullPointerException if this set contains a null element and the
- * specified collection does not permit null elements (optional),
+ * specified collection does not permit null elements
+ * (<a href="{@docRoot}/java/util/Collection.html#optional-restrictions">optional</a>),
* or if the specified collection is null
* @see #remove(Object)
*/
@@ -359,41 +400,15 @@
* number of elements and for every element {@code e1} returned by
* the iterator over the specified set, there is an element
* {@code e2} returned by the iterator over this set such that
- * {@code (e1==null ? e2==null : e1.equals(e2))}.
+ * {@code Objects.equals(e1, e2)}.
*
* @param o object to be compared for equality with this set
* @return {@code true} if the specified object is equal to this set
*/
public boolean equals(Object o) {
- if (o == this)
- return true;
- if (!(o instanceof Set))
- return false;
- Set<?> set = (Set<?>)(o);
- Iterator<?> it = set.iterator();
-
- // Uses O(n^2) algorithm that is only appropriate
- // for small sets, which CopyOnWriteArraySets should be.
-
- // Use a single snapshot of underlying array
- Object[] elements = al.getArray();
- int len = elements.length;
- // Mark matched elements to avoid re-checking
- boolean[] matched = new boolean[len];
- int k = 0;
- outer: while (it.hasNext()) {
- if (++k > len)
- return false;
- Object x = it.next();
- for (int i = 0; i < len; ++i) {
- if (!matched[i] && eq(x, elements[i])) {
- matched[i] = true;
- continue outer;
- }
- }
- return false;
- }
- return k == len;
+ return (o == this)
+ || ((o instanceof Set)
+ && compareSets(al.getArray(), (Set<?>) o) == 0);
}
public boolean removeIf(Predicate<? super E> filter) {
@@ -423,11 +438,4 @@
return Spliterators.spliterator
(al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
}
-
- /**
- * Tests for equality, coping with nulls.
- */
- private static boolean eq(Object o1, Object o2) {
- return (o1 == null) ? o2 == null : o1.equals(o2);
- }
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountDownLatch.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountDownLatch.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
@@ -72,7 +73,7 @@
* until all workers have completed.
* </ul>
*
- * <pre> {@code
+ * <pre> {@code
* class Driver { // ...
* void main() throws InterruptedException {
* CountDownLatch startSignal = new CountDownLatch(1);
@@ -113,7 +114,7 @@
* will be able to pass through await. (When threads must repeatedly
* count down in this way, instead use a {@link CyclicBarrier}.)
*
- * <pre> {@code
+ * <pre> {@code
* class Driver2 { // ...
* void main() throws InterruptedException {
* CountDownLatch doneSignal = new CountDownLatch(N);
@@ -179,7 +180,7 @@
int c = getState();
if (c == 0)
return false;
- int nextc = c-1;
+ int nextc = c - 1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java Tue Oct 20 08:24:37 2015 -0700
@@ -168,7 +168,8 @@
* {@code tryComplete}) the pending count is set to one:
*
* <pre> {@code
- * class ForEach<E> ...
+ * class ForEach<E> ... {
+ * ...
* public void compute() { // version 2
* if (hi - lo >= 2) {
* int mid = (lo + hi) >>> 1;
@@ -182,7 +183,7 @@
* tryComplete();
* }
* }
- * }</pre>
+ * }}</pre>
*
* As a further improvement, notice that the left task need not even exist.
* Instead of creating a new one, we can iterate using the original task,
@@ -191,9 +192,10 @@
* {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
*
* <pre> {@code
- * class ForEach<E> ...
+ * class ForEach<E> ... {
+ * ...
* public void compute() { // version 3
- * int l = lo, h = hi;
+ * int l = lo, h = hi;
* while (h - l >= 2) {
* int mid = (l + h) >>> 1;
* addToPendingCount(1);
@@ -204,7 +206,7 @@
* op.apply(array[l]);
* propagateCompletion();
* }
- * }</pre>
+ * }}</pre>
*
* Additional improvements of such classes might entail precomputing
* pending counts so that they can be established in constructors,
@@ -233,7 +235,7 @@
* }
* public E getRawResult() { return result.get(); }
* public void compute() { // similar to ForEach version 3
- * int l = lo, h = hi;
+ * int l = lo, h = hi;
* while (result.get() == null && h >= l) {
* if (h - l >= 2) {
* int mid = (l + h) >>> 1;
@@ -363,7 +365,7 @@
* this.next = next;
* }
* public void compute() {
- * int l = lo, h = hi;
+ * int l = lo, h = hi;
* while (h - l >= 2) {
* int mid = (l + h) >>> 1;
* addToPendingCount(1);
@@ -374,7 +376,7 @@
* result = mapper.apply(array[l]);
* // process completions by reducing along and advancing subtask links
* for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
- * for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
+ * for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
* t.result = reducer.apply(t.result, s.result);
* }
* }
@@ -402,8 +404,7 @@
* // sample use:
* PacketSender p = new PacketSender();
* new HeaderBuilder(p, ...).fork();
- * new BodyBuilder(p, ...).fork();
- * }</pre>
+ * new BodyBuilder(p, ...).fork();}</pre>
*
* @since 1.8
* @author Doug Lea
@@ -733,7 +734,7 @@
}
/**
- * Returns the result of the computation. By default
+ * Returns the result of the computation. By default,
* returns {@code null}, which is appropriate for {@code Void}
* actions, but in other cases should be overridden, almost
* always to return a field or function of a field that
@@ -753,14 +754,13 @@
protected void setRawResult(T t) { }
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long PENDING;
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
PENDING = U.objectFieldOffset
(CountedCompleter.class.getDeclaredField("pending"));
- } catch (Exception e) {
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -54,7 +55,7 @@
* <p><b>Sample usage:</b> Here is an example of using a barrier in a
* parallel decomposition design:
*
- * <pre> {@code
+ * <pre> {@code
* class Solver {
* final int N;
* final float[][] data;
@@ -85,7 +86,7 @@
* new Runnable() { public void run() { mergeRows(...); }};
* barrier = new CyclicBarrier(N, barrierAction);
*
- * List<Thread> threads = new ArrayList<Thread>(N);
+ * List<Thread> threads = new ArrayList<>(N);
* for (int i = 0; i < N; i++) {
* Thread thread = new Thread(new Worker(i));
* threads.add(thread);
@@ -111,7 +112,7 @@
* {@link #await} returns the arrival index of that thread at the barrier.
* You can then choose which thread should execute the barrier action, for
* example:
- * <pre> {@code
+ * <pre> {@code
* if (barrier.await() == 0) {
* // log the completion of this iteration
* }}</pre>
@@ -149,7 +150,7 @@
* but no subsequent reset.
*/
private static class Generation {
- boolean broken = false;
+ boolean broken; // initially false
}
/** The lock for guarding barrier entry */
@@ -158,7 +159,7 @@
private final Condition trip = lock.newCondition();
/** The number of parties */
private final int parties;
- /* The command to run when tripped */
+ /** The command to run when tripped */
private final Runnable barrierCommand;
/** The current generation */
private Generation generation = new Generation();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/DelayQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,10 +34,16 @@
*/
package java.util.concurrent;
+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.PriorityQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
/**
* An unbounded {@linkplain BlockingQueue blocking queue} of
@@ -65,7 +71,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {
@@ -89,7 +95,7 @@
* signalled. So waiting threads must be prepared to acquire
* and lose leadership while waiting.
*/
- private Thread leader = null;
+ private Thread leader;
/**
* Condition signalled when a newer element becomes available
@@ -185,10 +191,9 @@
lock.lock();
try {
E first = q.peek();
- if (first == null || first.getDelay(NANOSECONDS) > 0)
- return null;
- else
- return q.poll();
+ return (first == null || first.getDelay(NANOSECONDS) > 0)
+ ? null
+ : q.poll();
} finally {
lock.unlock();
}
@@ -211,7 +216,7 @@
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
- if (delay <= 0)
+ if (delay <= 0L)
return q.poll();
first = null; // don't retain ref while waiting
if (leader != null)
@@ -253,15 +258,15 @@
for (;;) {
E first = q.peek();
if (first == null) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(NANOSECONDS);
- if (delay <= 0)
+ if (delay <= 0L)
return q.poll();
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
@@ -490,7 +495,7 @@
}
/**
- * Identity-based version for use in Itr.remove
+ * Identity-based version for use in Itr.remove.
*/
void removeEQ(Object o) {
final ReentrantLock lock = this.lock;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,9 +35,6 @@
*/
package java.util.concurrent;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.locks.LockSupport;
/**
* A synchronization point at which threads can pair and swap elements
@@ -53,9 +50,9 @@
* to swap buffers between threads so that the thread filling the
* buffer gets a freshly emptied one when it needs it, handing off the
* filled one to the thread emptying the buffer.
- * <pre> {@code
+ * <pre> {@code
* class FillAndEmpty {
- * Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
+ * Exchanger<DataBuffer> exchanger = new Exchanger<>();
* DataBuffer initialEmptyBuffer = ... a made-up type
* DataBuffer initialFullBuffer = ...
*
@@ -326,7 +323,7 @@
}
/**
- * Per-thread state
+ * Per-thread state.
*/
private final Participant participant;
@@ -628,37 +625,33 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long BOUND;
private static final long SLOT;
private static final long MATCH;
private static final long BLOCKER;
private static final int ABASE;
static {
- int s;
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> ek = Exchanger.class;
- Class<?> nk = Node.class;
- Class<?> ak = Node[].class;
- Class<?> tk = Thread.class;
BOUND = U.objectFieldOffset
- (ek.getDeclaredField("bound"));
+ (Exchanger.class.getDeclaredField("bound"));
SLOT = U.objectFieldOffset
- (ek.getDeclaredField("slot"));
+ (Exchanger.class.getDeclaredField("slot"));
+
MATCH = U.objectFieldOffset
- (nk.getDeclaredField("match"));
+ (Node.class.getDeclaredField("match"));
+
BLOCKER = U.objectFieldOffset
- (tk.getDeclaredField("parkBlocker"));
- s = U.arrayIndexScale(ak);
+ (Thread.class.getDeclaredField("parkBlocker"));
+
+ int scale = U.arrayIndexScale(Node[].class);
+ if ((scale & (scale - 1)) != 0 || scale > (1 << ASHIFT))
+ throw new Error("Unsupported array scale");
// ABASE absorbs padding in front of element 0
- ABASE = U.arrayBaseOffset(ak) + (1 << ASHIFT);
-
- } catch (Exception e) {
+ ABASE = U.arrayBaseOffset(Node[].class) + (1 << ASHIFT);
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
- if ((s & (s-1)) != 0 || s > (1 << ASHIFT))
- throw new Error("Unsupported array scale");
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Executor.java Tue Oct 20 08:24:37 2015 -0700
@@ -41,33 +41,31 @@
* mechanics of how each task will be run, including details of thread
* use, scheduling, etc. An {@code Executor} is normally used
* instead of explicitly creating threads. For example, rather than
- * invoking {@code new Thread(new(RunnableTask())).start()} for each
+ * invoking {@code new Thread(new RunnableTask()).start()} for each
* of a set of tasks, you might use:
*
- * <pre>
- * Executor executor = <em>anExecutor</em>;
+ * <pre> {@code
+ * Executor executor = anExecutor();
* executor.execute(new RunnableTask1());
* executor.execute(new RunnableTask2());
- * ...
- * </pre>
+ * ...}</pre>
*
- * However, the {@code Executor} interface does not strictly
- * require that execution be asynchronous. In the simplest case, an
- * executor can run the submitted task immediately in the caller's
- * thread:
+ * However, the {@code Executor} interface does not strictly require
+ * that execution be asynchronous. In the simplest case, an executor
+ * can run the submitted task immediately in the caller's thread:
*
- * <pre> {@code
+ * <pre> {@code
* class DirectExecutor implements Executor {
* public void execute(Runnable r) {
* r.run();
* }
* }}</pre>
*
- * More typically, tasks are executed in some thread other
- * than the caller's thread. The executor below spawns a new thread
- * for each task.
+ * More typically, tasks are executed in some thread other than the
+ * caller's thread. The executor below spawns a new thread for each
+ * task.
*
- * <pre> {@code
+ * <pre> {@code
* class ThreadPerTaskExecutor implements Executor {
* public void execute(Runnable r) {
* new Thread(r).start();
@@ -79,9 +77,9 @@
* serializes the submission of tasks to a second executor,
* illustrating a composite executor.
*
- * <pre> {@code
+ * <pre> {@code
* class SerialExecutor implements Executor {
- * final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
+ * final Queue<Runnable> tasks = new ArrayDeque<>();
* final Executor executor;
* Runnable active;
*
@@ -90,7 +88,7 @@
* }
*
* public synchronized void execute(final Runnable r) {
- * tasks.offer(new Runnable() {
+ * tasks.add(new Runnable() {
* public void run() {
* try {
* r.run();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorCompletionService.java Tue Oct 20 08:24:37 2015 -0700
@@ -56,16 +56,16 @@
* void solve(Executor e,
* Collection<Callable<Result>> solvers)
* throws InterruptedException, ExecutionException {
- * CompletionService<Result> ecs
- * = new ExecutorCompletionService<Result>(e);
- * for (Callable<Result> s : solvers)
- * ecs.submit(s);
- * int n = solvers.size();
- * for (int i = 0; i < n; ++i) {
- * Result r = ecs.take().get();
- * if (r != null)
- * use(r);
- * }
+ * CompletionService<Result> ecs
+ * = new ExecutorCompletionService<Result>(e);
+ * for (Callable<Result> s : solvers)
+ * ecs.submit(s);
+ * int n = solvers.size();
+ * for (int i = 0; i < n; ++i) {
+ * Result r = ecs.take().get();
+ * if (r != null)
+ * use(r);
+ * }
* }}</pre>
*
* Suppose instead that you would like to use the first non-null result
@@ -76,32 +76,31 @@
* void solve(Executor e,
* Collection<Callable<Result>> solvers)
* throws InterruptedException {
- * CompletionService<Result> ecs
- * = new ExecutorCompletionService<Result>(e);
- * int n = solvers.size();
- * List<Future<Result>> futures
- * = new ArrayList<Future<Result>>(n);
- * Result result = null;
- * try {
- * for (Callable<Result> s : solvers)
- * futures.add(ecs.submit(s));
- * for (int i = 0; i < n; ++i) {
- * try {
- * Result r = ecs.take().get();
- * if (r != null) {
- * result = r;
- * break;
- * }
- * } catch (ExecutionException ignore) {}
+ * CompletionService<Result> ecs
+ * = new ExecutorCompletionService<Result>(e);
+ * int n = solvers.size();
+ * List<Future<Result>> futures = new ArrayList<>(n);
+ * Result result = null;
+ * try {
+ * for (Callable<Result> s : solvers)
+ * futures.add(ecs.submit(s));
+ * for (int i = 0; i < n; ++i) {
+ * try {
+ * Result r = ecs.take().get();
+ * if (r != null) {
+ * result = r;
+ * break;
* }
+ * } catch (ExecutionException ignore) {}
* }
- * finally {
- * for (Future<Result> f : futures)
- * f.cancel(true);
- * }
+ * }
+ * finally {
+ * for (Future<Result> f : futures)
+ * f.cancel(true);
+ * }
*
- * if (result != null)
- * use(result);
+ * if (result != null)
+ * use(result);
* }}</pre>
*/
public class ExecutorCompletionService<V> implements CompletionService<V> {
@@ -110,15 +109,18 @@
private final BlockingQueue<Future<V>> completionQueue;
/**
- * FutureTask extension to enqueue upon completion
+ * FutureTask extension to enqueue upon completion.
*/
- private class QueueingFuture extends FutureTask<Void> {
- QueueingFuture(RunnableFuture<V> task) {
+ private static class QueueingFuture<V> extends FutureTask<Void> {
+ QueueingFuture(RunnableFuture<V> task,
+ BlockingQueue<Future<V>> completionQueue) {
super(task, null);
this.task = task;
+ this.completionQueue = completionQueue;
}
+ private final Future<V> task;
+ private final BlockingQueue<Future<V>> completionQueue;
protected void done() { completionQueue.add(task); }
- private final Future<V> task;
}
private RunnableFuture<V> newTaskFor(Callable<V> task) {
@@ -178,14 +180,14 @@
public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
- executor.execute(new QueueingFuture(f));
+ executor.execute(new QueueingFuture<V>(f, completionQueue));
return f;
}
public Future<V> submit(Runnable task, V result) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task, result);
- executor.execute(new QueueingFuture(f));
+ executor.execute(new QueueingFuture<V>(f, completionQueue));
return f;
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorService.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ExecutorService.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,8 +34,9 @@
*/
package java.util.concurrent;
+
+import java.util.Collection;
import java.util.List;
-import java.util.Collection;
/**
* An {@link Executor} that provides methods to manage termination and
@@ -71,7 +72,7 @@
* pool service incoming requests. It uses the preconfigured {@link
* Executors#newFixedThreadPool} factory method:
*
- * <pre> {@code
+ * <pre> {@code
* class NetworkService implements Runnable {
* private final ServerSocket serverSocket;
* private final ExecutorService pool;
@@ -105,7 +106,7 @@
* first by calling {@code shutdown} to reject incoming tasks, and then
* calling {@code shutdownNow}, if necessary, to cancel any lingering tasks:
*
- * <pre> {@code
+ * <pre> {@code
* void shutdownAndAwaitTermination(ExecutorService pool) {
* pool.shutdown(); // Disable new tasks from being submitted
* try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Executors.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,14 +34,16 @@
*/
package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
+
import java.security.AccessControlContext;
+import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import sun.security.util.SecurityConstants;
/**
@@ -51,18 +53,18 @@
* package. This class supports the following kinds of methods:
*
* <ul>
- * <li> Methods that create and return an {@link ExecutorService}
- * set up with commonly useful configuration settings.
- * <li> Methods that create and return a {@link ScheduledExecutorService}
- * set up with commonly useful configuration settings.
- * <li> Methods that create and return a "wrapped" ExecutorService, that
- * disables reconfiguration by making implementation-specific methods
- * inaccessible.
- * <li> Methods that create and return a {@link ThreadFactory}
- * that sets newly created threads to a known state.
- * <li> Methods that create and return a {@link Callable}
- * out of other closure-like forms, so they can be used
- * in execution methods requiring {@code Callable}.
+ * <li>Methods that create and return an {@link ExecutorService}
+ * set up with commonly useful configuration settings.
+ * <li>Methods that create and return a {@link ScheduledExecutorService}
+ * set up with commonly useful configuration settings.
+ * <li>Methods that create and return a "wrapped" ExecutorService, that
+ * disables reconfiguration by making implementation-specific methods
+ * inaccessible.
+ * <li>Methods that create and return a {@link ThreadFactory}
+ * that sets newly created threads to a known state.
+ * <li>Methods that create and return a {@link Callable}
+ * out of other closure-like forms, so they can be used
+ * in execution methods requiring {@code Callable}.
* </ul>
*
* @since 1.5
@@ -114,9 +116,10 @@
}
/**
- * Creates a work-stealing thread pool using all
- * {@link Runtime#availableProcessors available processors}
+ * Creates a work-stealing thread pool using the number of
+ * {@linkplain Runtime#availableProcessors available processors}
* as its target parallelism level.
+ *
* @return the newly created thread pool
* @see #newWorkStealingPool(int)
* @since 1.8
@@ -498,11 +501,11 @@
// Non-public classes supporting the public methods
/**
- * A callable that runs given task and returns given result
+ * A callable that runs given task and returns given result.
*/
- static final class RunnableAdapter<T> implements Callable<T> {
- final Runnable task;
- final T result;
+ private static final class RunnableAdapter<T> implements Callable<T> {
+ private final Runnable task;
+ private final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
@@ -514,11 +517,11 @@
}
/**
- * A callable that runs under established access control settings
+ * A callable that runs under established access control settings.
*/
- static final class PrivilegedCallable<T> implements Callable<T> {
- private final Callable<T> task;
- private final AccessControlContext acc;
+ private static final class PrivilegedCallable<T> implements Callable<T> {
+ final Callable<T> task;
+ final AccessControlContext acc;
PrivilegedCallable(Callable<T> task) {
this.task = task;
@@ -541,12 +544,13 @@
/**
* A callable that runs under established access control settings and
- * current ClassLoader
+ * current ClassLoader.
*/
- static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
- private final Callable<T> task;
- private final AccessControlContext acc;
- private final ClassLoader ccl;
+ private static final class PrivilegedCallableUsingCurrentClassLoader<T>
+ implements Callable<T> {
+ final Callable<T> task;
+ final AccessControlContext acc;
+ final ClassLoader ccl;
PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
SecurityManager sm = System.getSecurityManager();
@@ -591,9 +595,9 @@
}
/**
- * The default thread factory
+ * The default thread factory.
*/
- static class DefaultThreadFactory implements ThreadFactory {
+ private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
@@ -621,11 +625,11 @@
}
/**
- * Thread factory capturing access control context and class loader
+ * Thread factory capturing access control context and class loader.
*/
- static class PrivilegedThreadFactory extends DefaultThreadFactory {
- private final AccessControlContext acc;
- private final ClassLoader ccl;
+ private static class PrivilegedThreadFactory extends DefaultThreadFactory {
+ final AccessControlContext acc;
+ final ClassLoader ccl;
PrivilegedThreadFactory() {
super();
@@ -662,7 +666,8 @@
* A wrapper class that exposes only the ExecutorService methods
* of an ExecutorService implementation.
*/
- static class DelegatedExecutorService extends AbstractExecutorService {
+ private static class DelegatedExecutorService
+ extends AbstractExecutorService {
private final ExecutorService e;
DelegatedExecutorService(ExecutorService executor) { e = executor; }
public void execute(Runnable command) { e.execute(command); }
@@ -703,8 +708,8 @@
}
}
- static class FinalizableDelegatedExecutorService
- extends DelegatedExecutorService {
+ private static class FinalizableDelegatedExecutorService
+ extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
@@ -717,7 +722,7 @@
* A wrapper class that exposes only the ScheduledExecutorService
* methods of a ScheduledExecutorService implementation.
*/
- static class DelegatedScheduledExecutorService
+ private static class DelegatedScheduledExecutorService
extends DelegatedExecutorService
implements ScheduledExecutorService {
private final ScheduledExecutorService e;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Flow.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,319 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * Interrelated interfaces and static methods for establishing
+ * flow-controlled components in which {@link Publisher Publishers}
+ * produce items consumed by one or more {@link Subscriber
+ * Subscribers}, each managed by a {@link Subscription
+ * Subscription}.
+ *
+ * <p>These interfaces correspond to the <a
+ * href="http://www.reactive-streams.org/"> reactive-streams</a>
+ * specification. They apply in both concurrent and distributed
+ * asynchronous settings: All (seven) methods are defined in {@code
+ * void} "one-way" message style. Communication relies on a simple form
+ * of flow control (method {@link Subscription#request}) that can be
+ * used to avoid resource management problems that may otherwise occur
+ * in "push" based systems.
+ *
+ * <p><b>Examples.</b> A {@link Publisher} usually defines its own
+ * {@link Subscription} implementation; constructing one in method
+ * {@code subscribe} and issuing it to the calling {@link
+ * Subscriber}. It publishes items to the subscriber asynchronously,
+ * normally using an {@link Executor}. For example, here is a very
+ * simple publisher that only issues (when requested) a single {@code
+ * TRUE} item to a single subscriber. Because the subscriber receives
+ * only a single item, this class does not use buffering and ordering
+ * control required in most implementations (for example {@link
+ * SubmissionPublisher}).
+ *
+ * <pre> {@code
+ * class OneShotPublisher implements Publisher<Boolean> {
+ * private final ExecutorService executor = ForkJoinPool.commonPool(); // daemon-based
+ * private boolean subscribed; // true after first subscribe
+ * public synchronized void subscribe(Subscriber<? super Boolean> subscriber) {
+ * if (subscribed)
+ * subscriber.onError(new IllegalStateException()); // only one allowed
+ * else {
+ * subscribed = true;
+ * subscriber.onSubscribe(new OneShotSubscription(subscriber, executor));
+ * }
+ * }
+ * static class OneShotSubscription implements Subscription {
+ * private final Subscriber<? super Boolean> subscriber;
+ * private final ExecutorService executor;
+ * private Future<?> future; // to allow cancellation
+ * private boolean completed;
+ * OneShotSubscription(Subscriber<? super Boolean> subscriber,
+ * ExecutorService executor) {
+ * this.subscriber = subscriber;
+ * this.executor = executor;
+ * }
+ * public synchronized void request(long n) {
+ * if (n != 0 && !completed) {
+ * completed = true;
+ * if (n < 0) {
+ * IllegalArgumentException ex = new IllegalArgumentException();
+ * executor.execute(() -> subscriber.onError(ex));
+ * } else {
+ * future = executor.submit(() -> {
+ * subscriber.onNext(Boolean.TRUE);
+ * subscriber.onComplete();
+ * });
+ * }
+ * }
+ * }
+ * public synchronized void cancel() {
+ * completed = true;
+ * if (future != null) future.cancel(false);
+ * }
+ * }
+ * }}</pre>
+ *
+ * <p>A {@link Subscriber} arranges that items be requested and
+ * processed. Items (invocations of {@link Subscriber#onNext}) are
+ * not issued unless requested, but multiple items may be requested.
+ * Many Subscriber implementations can arrange this in the style of
+ * the following example, where a buffer size of 1 single-steps, and
+ * larger sizes usually allow for more efficient overlapped processing
+ * with less communication; for example with a value of 64, this keeps
+ * total outstanding requests between 32 and 64.
+ * Because Subscriber method invocations for a given {@link
+ * Subscription} are strictly ordered, there is no need for these
+ * methods to use locks or volatiles unless a Subscriber maintains
+ * multiple Subscriptions (in which case it is better to instead
+ * define multiple Subscribers, each with its own Subscription).
+ *
+ * <pre> {@code
+ * class SampleSubscriber<T> implements Subscriber<T> {
+ * final Consumer<? super T> consumer;
+ * Subscription subscription;
+ * final long bufferSize;
+ * long count;
+ * SampleSubscriber(long bufferSize, Consumer<? super T> consumer) {
+ * this.bufferSize = bufferSize;
+ * this.consumer = consumer;
+ * }
+ * public void onSubscribe(Subscription subscription) {
+ * long initialRequestSize = bufferSize;
+ * count = bufferSize - bufferSize / 2; // re-request when half consumed
+ * (this.subscription = subscription).request(initialRequestSize);
+ * }
+ * public void onNext(T item) {
+ * if (--count <= 0)
+ * subscription.request(count = bufferSize - bufferSize / 2);
+ * consumer.accept(item);
+ * }
+ * public void onError(Throwable ex) { ex.printStackTrace(); }
+ * public void onComplete() {}
+ * }}</pre>
+ *
+ * <p>The default value of {@link #defaultBufferSize} may provide a
+ * useful starting point for choosing request sizes and capacities in
+ * Flow components based on expected rates, resources, and usages.
+ * Or, when flow control is never needed, a subscriber may initially
+ * request an effectively unbounded number of items, as in:
+ *
+ * <pre> {@code
+ * class UnboundedSubscriber<T> implements Subscriber<T> {
+ * public void onSubscribe(Subscription subscription) {
+ * subscription.request(Long.MAX_VALUE); // effectively unbounded
+ * }
+ * public void onNext(T item) { use(item); }
+ * public void onError(Throwable ex) { ex.printStackTrace(); }
+ * public void onComplete() {}
+ * void use(T item) { ... }
+ * }}</pre>
+ *
+ * @author Doug Lea
+ * @since 1.9
+ */
+public final class Flow {
+
+ private Flow() {} // uninstantiable
+
+ /**
+ * A producer of items (and related control messages) received by
+ * Subscribers. Each current {@link Subscriber} receives the same
+ * items (via method {@code onNext}) in the same order, unless
+ * drops or errors are encountered. If a Publisher encounters an
+ * error that does not allow items to be issued to a Subscriber,
+ * that Subscriber receives {@code onError}, and then receives no
+ * further messages. Otherwise, when it is known that no further
+ * messages will be issued to it, a subscriber receives {@code
+ * onComplete}. Publishers ensure that Subscriber method
+ * invocations for each subscription are strictly ordered in <a
+ * href="package-summary.html#MemoryVisibility"><i>happens-before</i></a>
+ * order.
+ *
+ * <p>Publishers may vary in policy about whether drops (failures
+ * to issue an item because of resource limitations) are treated
+ * as unrecoverable errors. Publishers may also vary about
+ * whether Subscribers receive items that were produced or
+ * available before they subscribed.
+ *
+ * @param <T> the published item type
+ */
+ @FunctionalInterface
+ public static interface Publisher<T> {
+ /**
+ * Adds the given Subscriber if possible. If already
+ * subscribed, or the attempt to subscribe fails due to policy
+ * violations or errors, the Subscriber's {@code onError}
+ * method is invoked with an {@link IllegalStateException}.
+ * Otherwise, the Subscriber's {@code onSubscribe} method is
+ * invoked with a new {@link Subscription}. Subscribers may
+ * enable receiving items by invoking the {@code request}
+ * method of this Subscription, and may unsubscribe by
+ * invoking its {@code cancel} method.
+ *
+ * @param subscriber the subscriber
+ * @throws NullPointerException if subscriber is null
+ */
+ public void subscribe(Subscriber<? super T> subscriber);
+ }
+
+ /**
+ * A receiver of messages. The methods in this interface are
+ * invoked in strict sequential order for each {@link
+ * Subscription}.
+ *
+ * @param <T> the subscribed item type
+ */
+ public static interface Subscriber<T> {
+ /**
+ * Method invoked prior to invoking any other Subscriber
+ * methods for the given Subscription. If this method throws
+ * an exception, resulting behavior is not guaranteed, but may
+ * cause the Subscription not to be established or to be cancelled.
+ *
+ * <p>Typically, implementations of this method invoke {@code
+ * subscription.request} to enable receiving items.
+ *
+ * @param subscription a new subscription
+ */
+ public void onSubscribe(Subscription subscription);
+
+ /**
+ * Method invoked with a Subscription's next item. If this
+ * method throws an exception, resulting behavior is not
+ * guaranteed, but may cause the Subscription to be cancelled.
+ *
+ * @param item the item
+ */
+ public void onNext(T item);
+
+ /**
+ * Method invoked upon an unrecoverable error encountered by a
+ * Publisher or Subscription, after which no other Subscriber
+ * methods are invoked by the Subscription. If this method
+ * itself throws an exception, resulting behavior is
+ * undefined.
+ *
+ * @param throwable the exception
+ */
+ public void onError(Throwable throwable);
+
+ /**
+ * Method invoked when it is known that no additional
+ * Subscriber method invocations will occur for a Subscription
+ * that is not already terminated by error, after which no
+ * other Subscriber methods are invoked by the Subscription.
+ * If this method throws an exception, resulting behavior is
+ * undefined.
+ */
+ public void onComplete();
+ }
+
+ /**
+ * Message control linking a {@link Publisher} and {@link
+ * Subscriber}. Subscribers receive items only when requested,
+ * and may cancel at any time. The methods in this interface are
+ * intended to be invoked only by their Subscribers; usages in
+ * other contexts have undefined effects.
+ */
+ public static interface Subscription {
+ /**
+ * Adds the given number {@code n} of items to the current
+ * unfulfilled demand for this subscription. If {@code n} is
+ * negative, the Subscriber will receive an {@code onError}
+ * signal with an {@link IllegalArgumentException} argument.
+ * Otherwise, the Subscriber will receive up to {@code n}
+ * additional {@code onNext} invocations (or fewer if
+ * terminated).
+ *
+ * @param n the increment of demand; a value of {@code
+ * Long.MAX_VALUE} may be considered as effectively unbounded
+ */
+ public void request(long n);
+
+ /**
+ * Causes the Subscriber to (eventually) stop receiving
+ * messages. Implementation is best-effort -- additional
+ * messages may be received after invoking this method.
+ * A cancelled subscription need not ever receive an
+ * {@code onComplete} or {@code onError} signal.
+ */
+ public void cancel();
+ }
+
+ /**
+ * A component that acts as both a Subscriber and Publisher.
+ *
+ * @param <T> the subscribed item type
+ * @param <R> the published item type
+ */
+ public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
+ }
+
+ static final int DEFAULT_BUFFER_SIZE = 256;
+
+ /**
+ * Returns a default value for Publisher or Subscriber buffering,
+ * that may be used in the absence of other constraints.
+ *
+ * @implNote
+ * The current value returned is 256.
+ *
+ * @return the buffer size value
+ */
+ public static int defaultBufferSize() {
+ return DEFAULT_BUFFER_SIZE;
+ }
+
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,23 +36,16 @@
package java.util.concurrent;
import java.lang.Thread.UncaughtExceptionHandler;
+import java.security.AccessControlContext;
+import java.security.Permissions;
+import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.AbstractExecutorService;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.security.AccessControlContext;
-import java.security.ProtectionDomain;
-import java.security.Permissions;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.LockSupport;
/**
* An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -216,42 +209,60 @@
* arbitrating pop vs poll (steal) from being on the indices
* ("base" and "top") to the slots themselves.
*
- * Adding tasks then takes the form of a classic array push(task):
- * q.array[q.top] = task; ++q.top;
+ * Adding tasks then takes the form of a classic array push(task)
+ * in a circular buffer:
+ * q.array[q.top++ % length] = task;
*
* (The actual code needs to null-check and size-check the array,
- * properly fence the accesses, and possibly signal waiting
- * workers to start scanning -- see below.) Both a successful pop
- * and poll mainly entail a CAS of a slot from non-null to null.
+ * uses masking, not mod, for indexing a power-of-two-sized array,
+ * properly fences accesses, and possibly signals waiting workers
+ * to start scanning -- see below.) Both a successful pop and
+ * poll mainly entail a CAS of a slot from non-null to null.
*
* The pop operation (always performed by owner) is:
- * if ((base != top) and
- * (the task at top slot is not null) and
+ * if ((the task at top slot is not null) and
* (CAS slot to null))
* decrement top and return task;
*
* And the poll operation (usually by a stealer) is
- * if ((base != top) and
- * (the task at base slot is not null) and
- * (base has not changed) and
+ * if ((the task at base slot is not null) and
* (CAS slot to null))
* increment base and return task;
*
- * Because we rely on CASes of references, we do not need tag bits
- * on base or top. They are simple ints as used in any circular
- * array-based queue (see for example ArrayDeque). Updates to the
- * indices guarantee that top == base means the queue is empty,
- * but otherwise may err on the side of possibly making the queue
- * appear nonempty when a push, pop, or poll have not fully
- * committed. (Method isEmpty() checks the case of a partially
+ * There are several variants of each of these; for example most
+ * versions of poll pre-screen the CAS by rechecking that the base
+ * has not changed since reading the slot, and most methods only
+ * attempt the CAS if base appears not to be equal to top.
+ *
+ * Memory ordering. See "Correct and Efficient Work-Stealing for
+ * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
+ * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
+ * analysis of memory ordering requirements in work-stealing
+ * algorithms similar to (but different than) the one used here.
+ * Extracting tasks in array slots via (fully fenced) CAS provides
+ * primary synchronization. The base and top indices imprecisely
+ * guide where to extract from. We do not always require strict
+ * orderings of array and index updates, so sometimes let them be
+ * subject to compiler and processor reorderings. However, the
+ * volatile "base" index also serves as a basis for memory
+ * ordering: Slot accesses are preceded by a read of base,
+ * ensuring happens-before ordering with respect to stealers (so
+ * the slots themselves can be read via plain array reads.) The
+ * only other memory orderings relied on are maintained in the
+ * course of signalling and activation (see below). A check that
+ * base == top indicates (momentary) emptiness, but otherwise may
+ * err on the side of possibly making the queue appear nonempty
+ * when a push, pop, or poll have not fully committed, or making
+ * it appear empty when an update of top has not yet been visibly
+ * written. (Method isEmpty() checks the case of a partially
* completed removal of the last element.) Because of this, the
* poll operation, considered individually, is not wait-free. One
* thief cannot successfully continue until another in-progress
- * one (or, if previously empty, a push) completes. However, in
- * the aggregate, we ensure at least probabilistic
- * non-blockingness. If an attempted steal fails, a thief always
- * chooses a different random victim target to try next. So, in
- * order for one thief to progress, it suffices for any
+ * one (or, if previously empty, a push) visibly completes.
+ * However, in the aggregate, we ensure at least probabilistic
+ * non-blockingness. If an attempted steal fails, a scanning
+ * thief chooses a different random victim target to try next. So,
+ * in order for one thief to progress, it suffices for any
* in-progress poll or new push on any empty queue to
* complete. (This is why we normally use method pollAt and its
* variants that try once at the apparent base index, else
@@ -262,19 +273,6 @@
* local task processing is in FIFO, not LIFO order, simply by
* using poll rather than pop. This can be useful in
* message-passing frameworks in which tasks are never joined.
- * However neither mode considers affinities, loads, cache
- * localities, etc, so rarely provide the best possible
- * performance on a given machine, but portably provide good
- * throughput by averaging over these factors. Further, even if
- * we did try to use such information, we do not usually have a
- * basis for exploiting it. For example, some sets of tasks
- * profit from cache affinities, but others are harmed by cache
- * pollution effects. Additionally, even though it requires
- * scanning, long-term throughput is often best using random
- * selection rather than directed selection policies, so cheap
- * randomization of sufficient quality is used whenever
- * applicable. Various Marsaglia XorShifts (some with different
- * shift constants) are inlined at use points.
*
* WorkQueues are also used in a similar way for tasks submitted
* to the pool. We cannot mix these tasks in the same queues used
@@ -286,14 +284,14 @@
* like workers except that they are restricted to executing local
* tasks that they submitted (or in the case of CountedCompleters,
* others with the same root task). Insertion of tasks in shared
- * mode requires a lock (mainly to protect in the case of
- * resizing) but we use only a simple spinlock (using field
- * qlock), because submitters encountering a busy queue move on to
- * try or create other queues -- they block only when creating and
- * registering new queues. Additionally, "qlock" saturates to an
- * unlockable value (-1) at shutdown. Unlocking still can be and
- * is performed by cheaper ordered writes of "qlock" in successful
- * cases, but uses CAS in unsuccessful cases.
+ * mode requires a lock but we use only a simple spinlock (using
+ * field qlock), because submitters encountering a busy queue move
+ * on to try or create other queues -- they block only when
+ * creating and registering new queues. Because it is used only as
+ * a spinlock, unlocking requires only a "releasing" store (using
+ * putOrderedInt). The qlock is also used during termination
+ * detection, in which case it is forced to a negative
+ * non-lockable value.
*
* Management
* ==========
@@ -320,46 +318,36 @@
* and their negations (used for thresholding) to fit into 16bit
* subfields.
*
- * Field "runState" holds lockable state bits (STARTED, STOP, etc)
- * also protecting updates to the workQueues array. When used as
- * a lock, it is normally held only for a few instructions (the
- * only exceptions are one-time array initialization and uncommon
- * resizing), so is nearly always available after at most a brief
- * spin. But to be extra-cautious, after spinning, method
- * awaitRunStateLock (called only if an initial CAS fails), uses a
- * wait/notify mechanics on a builtin monitor to block when
- * (rarely) needed. This would be a terrible idea for a highly
- * contended lock, but most pools run without the lock ever
- * contending after the spin limit, so this works fine as a more
- * conservative alternative. Because we don't otherwise have an
- * internal Object to use as a monitor, the "stealCounter" (an
- * AtomicLong) is used when available (it too must be lazily
- * initialized; see externalSubmit).
+ * Field "runState" holds lifetime status, atomically and
+ * monotonically setting STARTED, SHUTDOWN, STOP, and finally
+ * TERMINATED bits.
+ *
+ * Field "auxState" is a ReentrantLock subclass that also
+ * opportunistically holds some other bookkeeping fields accessed
+ * only when locked. It is mainly used to lock (infrequent)
+ * updates to workQueues. The auxState instance is itself lazily
+ * constructed (see tryInitialize), requiring a double-check-style
+ * bootstrapping use of field runState, and locking a private
+ * static.
*
- * Usages of "runState" vs "ctl" interact in only one case:
- * deciding to add a worker thread (see tryAddWorker), in which
- * case the ctl CAS is performed while the lock is held.
- *
- * Recording WorkQueues. WorkQueues are recorded in the
- * "workQueues" array. The array is created upon first use (see
- * externalSubmit) and expanded if necessary. Updates to the
- * array while recording new workers and unrecording terminated
- * ones are protected from each other by the runState lock, but
- * the array is otherwise concurrently readable, and accessed
+ * Field "workQueues" holds references to WorkQueues. It is
+ * updated (only during worker creation and termination) under the
+ * lock, but is otherwise concurrently readable, and accessed
* directly. We also ensure that reads of the array reference
- * itself never become too stale. To simplify index-based
- * operations, the array size is always a power of two, and all
- * readers must tolerate null slots. Worker queues are at odd
- * indices. Shared (submission) queues are at even indices, up to
- * a maximum of 64 slots, to limit growth even if array needs to
- * expand to add more workers. Grouping them together in this way
- * simplifies and speeds up task scanning.
+ * itself never become too stale (for example, re-reading before
+ * each scan). To simplify index-based operations, the array size
+ * is always a power of two, and all readers must tolerate null
+ * slots. Worker queues are at odd indices. Shared (submission)
+ * queues are at even indices, up to a maximum of 64 slots, to
+ * limit growth even if array needs to expand to add more
+ * workers. Grouping them together in this way simplifies and
+ * speeds up task scanning.
*
* All worker thread creation is on-demand, triggered by task
* submissions, replacement of terminated workers, and/or
* compensation for blocked workers. However, all other support
* code is set up to work with other policies. To ensure that we
- * do not hold on to worker references that would prevent GC, All
+ * do not hold on to worker references that would prevent GC, all
* accesses to workQueues are via indices into the workQueues
* array (which is one source of some of the messy code
* constructions here). In essence, the workQueues array serves as
@@ -386,7 +374,7 @@
* activating threads in most-recently used order. This improves
* performance and locality, outweighing the disadvantages of
* being prone to contention and inability to release a worker
- * unless it is topmost on stack. We park/unpark workers after
+ * unless it is topmost on stack. We block/unblock workers after
* pushing on the idle worker stack (represented by the lower
* 32bit subfield of ctl) when they cannot find work. The top
* stack state holds the value of the "scanState" field of the
@@ -394,48 +382,14 @@
* addition to the count subfields (also serving as version
* stamps) provide protection against Treiber stack ABA effects.
*
- * Field scanState is used by both workers and the pool to manage
- * and track whether a worker is INACTIVE (possibly blocked
- * waiting for a signal), or SCANNING for tasks (when neither hold
- * it is busy running tasks). When a worker is inactivated, its
- * scanState field is set, and is prevented from executing tasks,
- * even though it must scan once for them to avoid queuing
- * races. Note that scanState updates lag queue CAS releases so
- * usage requires care. When queued, the lower 16 bits of
- * scanState must hold its pool index. So we place the index there
- * upon initialization (see registerWorker) and otherwise keep it
- * there or restore it when necessary.
- *
- * Memory ordering. See "Correct and Efficient Work-Stealing for
- * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
- * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
- * analysis of memory ordering requirements in work-stealing
- * algorithms similar to the one used here. We usually need
- * stronger than minimal ordering because we must sometimes signal
- * workers, requiring Dekker-like full-fences to avoid lost
- * signals. Arranging for enough ordering without expensive
- * over-fencing requires tradeoffs among the supported means of
- * expressing access constraints. The most central operations,
- * taking from queues and updating ctl state, require full-fence
- * CAS. Array slots are read using the emulation of volatiles
- * provided by Unsafe. Access from other threads to WorkQueue
- * base, top, and array requires a volatile load of the first of
- * any of these read. We use the convention of declaring the
- * "base" index volatile, and always read it before other fields.
- * The owner thread must ensure ordered updates, so writes use
- * ordered intrinsics unless they can piggyback on those for other
- * writes. Similar conventions and rationales hold for other
- * WorkQueue fields (such as "currentSteal") that are only written
- * by owners but observed by others.
- *
* Creating workers. To create a worker, we pre-increment total
* count (serving as a reservation), and attempt to construct a
* ForkJoinWorkerThread via its factory. Upon construction, the
* new thread invokes registerWorker, where it constructs a
* WorkQueue and is assigned an index in the workQueues array
- * (expanding the array if necessary). The thread is then
- * started. Upon any exception across these steps, or null return
- * from factory, deregisterWorker adjusts counts and records
+ * (expanding the array if necessary). The thread is then started.
+ * Upon any exception across these steps, or null return from
+ * factory, deregisterWorker adjusts counts and records
* accordingly. If a null return, the pool continues running with
* fewer than the target number workers. If exceptional, the
* exception is propagated, generally to some external caller.
@@ -448,80 +402,106 @@
* probability of collision low. We cannot use
* ThreadLocalRandom.getProbe() for similar purposes here because
* the thread has not started yet, but do so for creating
- * submission queues for existing external threads.
+ * submission queues for existing external threads (see
+ * externalPush).
+ *
+ * WorkQueue field scanState is used by both workers and the pool
+ * to manage and track whether a worker is UNSIGNALLED (possibly
+ * blocked waiting for a signal). When a worker is inactivated,
+ * its scanState field is set, and is prevented from executing
+ * tasks, even though it must scan once for them to avoid queuing
+ * races. Note that scanState updates lag queue CAS releases so
+ * usage requires care. When queued, the lower 16 bits of
+ * scanState must hold its pool index. So we place the index there
+ * upon initialization (see registerWorker) and otherwise keep it
+ * there or restore it when necessary.
+ *
+ * The ctl field also serves as the basis for memory
+ * synchronization surrounding activation. This uses a more
+ * efficient version of a Dekker-like rule that task producers and
+ * consumers sync with each other by both writing/CASing ctl (even
+ * if to its current value). This would be extremely costly. So
+ * we relax it in several ways: (1) Producers only signal when
+ * their queue is empty. Other workers propagate this signal (in
+ * method scan) when they find tasks. (2) Workers only enqueue
+ * after scanning (see below) and not finding any tasks. (3)
+ * Rather than CASing ctl to its current value in the common case
+ * where no action is required, we reduce write contention by
+ * equivalently prefacing signalWork when called by an external
+ * task producer using a memory access with full-volatile
+ * semantics or a "fullFence". (4) For internal task producers we
+ * rely on the fact that even if no other workers awaken, the
+ * producer itself will eventually see the task and execute it.
+ *
+ * Almost always, too many signals are issued. A task producer
+ * cannot in general tell if some existing worker is in the midst
+ * of finishing one task (or already scanning) and ready to take
+ * another without being signalled. So the producer might instead
+ * activate a different worker that does not find any work, and
+ * then inactivates. This scarcely matters in steady-state
+ * computations involving all workers, but can create contention
+ * and bookkeeping bottlenecks during ramp-up, ramp-down, and small
+ * computations involving only a few workers.
+ *
+ * Scanning. Method scan() performs top-level scanning for tasks.
+ * Each scan traverses (and tries to poll from) each queue in
+ * pseudorandom permutation order by randomly selecting an origin
+ * index and a step value. (The pseudorandom generator need not
+ * have high-quality statistical properties in the long term, but
+ * just within computations; We use 64bit and 32bit Marsaglia
+ * XorShifts, which are cheap and suffice here.) Scanning also
+ * employs contention reduction: When scanning workers fail a CAS
+ * polling for work, they soon restart with a different
+ * pseudorandom scan order (thus likely retrying at different
+ * intervals). This improves throughput when many threads are
+ * trying to take tasks from few queues. Scans do not otherwise
+ * explicitly take into account core affinities, loads, cache
+ * localities, etc, However, they do exploit temporal locality
+ * (which usually approximates these) by preferring to re-poll (up
+ * to POLL_LIMIT times) from the same queue after a successful
+ * poll before trying others. Restricted forms of scanning occur
+ * in methods helpComplete and findNonEmptyStealQueue, and take
+ * similar but simpler forms.
*
* Deactivation and waiting. Queuing encounters several intrinsic
- * races; most notably that a task-producing thread can miss
- * seeing (and signalling) another thread that gave up looking for
- * work but has not yet entered the wait queue. When a worker
- * cannot find a task to steal, it deactivates and enqueues. Very
- * often, the lack of tasks is transient due to GC or OS
- * scheduling. To reduce false-alarm deactivation, scanners
- * compute checksums of queue states during sweeps. (The
- * stability checks used here and elsewhere are probabilistic
- * variants of snapshot techniques -- see Herlihy & Shavit.)
- * Workers give up and try to deactivate only after the sum is
- * stable across scans. Further, to avoid missed signals, they
- * repeat this scanning process after successful enqueuing until
- * again stable. In this state, the worker cannot take/run a task
- * it sees until it is released from the queue, so the worker
- * itself eventually tries to release itself or any successor (see
- * tryRelease). Otherwise, upon an empty scan, a deactivated
- * worker uses an adaptive local spin construction (see awaitWork)
- * before blocking (via park). Note the unusual conventions about
- * Thread.interrupts surrounding parking and other blocking:
- * Because interrupts are used solely to alert threads to check
- * termination, which is checked anyway upon blocking, we clear
- * status (using Thread.interrupted) before any call to park, so
- * that park does not immediately return due to status being set
- * via some other unrelated call to interrupt in user code.
+ * races; most notably that an inactivating scanning worker can
+ * miss seeing a task produced during a scan. So when a worker
+ * cannot find a task to steal, it inactivates and enqueues, and
+ * then rescans to ensure that it didn't miss one, reactivating
+ * upon seeing one with probability approximately proportional to
+ * probability of a miss. (In most cases, the worker will be
+ * signalled before self-signalling, avoiding cascades of multiple
+ * signals for the same task).
*
- * Signalling and activation. Workers are created or activated
- * only when there appears to be at least one task they might be
- * able to find and execute. Upon push (either by a worker or an
- * external submission) to a previously (possibly) empty queue,
- * workers are signalled if idle, or created if fewer exist than
- * the given parallelism level. These primary signals are
- * buttressed by others whenever other threads remove a task from
- * a queue and notice that there are other tasks there as well.
- * On most platforms, signalling (unpark) overhead time is
- * noticeably long, and the time between signalling a thread and
- * it actually making progress can be very noticeably long, so it
- * is worth offloading these delays from critical paths as much as
- * possible. Also, because inactive workers are often rescanning
- * or spinning rather than blocking, we set and clear the "parker"
- * field of WorkQueues to reduce unnecessary calls to unpark.
- * (This requires a secondary recheck to avoid missed signals.)
+ * Workers block (in method awaitWork) using park/unpark;
+ * advertising the need for signallers to unpark by setting their
+ * "parker" fields.
*
* Trimming workers. To release resources after periods of lack of
* use, a worker starting to wait when the pool is quiescent will
* time out and terminate (see awaitWork) if the pool has remained
- * quiescent for period IDLE_TIMEOUT, increasing the period as the
- * number of threads decreases, eventually removing all workers.
- * Also, when more than two spare threads exist, excess threads
- * are immediately terminated at the next quiescent point.
- * (Padding by two avoids hysteresis.)
+ * quiescent for period given by IDLE_TIMEOUT_MS, increasing the
+ * period as the number of threads decreases, eventually removing
+ * all workers.
*
* Shutdown and Termination. A call to shutdownNow invokes
* tryTerminate to atomically set a runState bit. The calling
* thread, as well as every other worker thereafter terminating,
* helps terminate others by setting their (qlock) status,
* cancelling their unprocessed tasks, and waking them up, doing
- * so repeatedly until stable (but with a loop bounded by the
- * number of workers). Calls to non-abrupt shutdown() preface
- * this by checking whether termination should commence. This
- * relies primarily on the active count bits of "ctl" maintaining
- * consensus -- tryTerminate is called from awaitWork whenever
- * quiescent. However, external submitters do not take part in
- * this consensus. So, tryTerminate sweeps through queues (until
- * stable) to ensure lack of in-flight submissions and workers
- * about to process them before triggering the "STOP" phase of
- * termination. (Note: there is an intrinsic conflict if
+ * so repeatedly until stable. Calls to non-abrupt shutdown()
+ * preface this by checking whether termination should commence.
+ * This relies primarily on the active count bits of "ctl"
+ * maintaining consensus -- tryTerminate is called from awaitWork
+ * whenever quiescent. However, external submitters do not take
+ * part in this consensus. So, tryTerminate sweeps through queues
+ * (until stable) to ensure lack of in-flight submissions and
+ * workers about to process them before triggering the "STOP"
+ * phase of termination. (Note: there is an intrinsic conflict if
* helpQuiescePool is called when shutdown is enabled. Both wait
* for quiescence, but tryTerminate is biased to not trigger until
* helpQuiescePool completes.)
*
- *
* Joining Tasks
* =============
*
@@ -605,8 +585,13 @@
* continuation tasks) blocks on a join and there still remain
* enough threads to ensure liveness.
*
+ * Spare threads are removed as soon as they notice that the
+ * target parallelism level has been exceeded, in method
+ * tryDropSpare. (Method scan arranges returns for rechecks upon
+ * each probe via the "bound" parameter.)
+ *
* The compensation mechanism may be bounded. Bounds for the
- * commonPool (see commonMaxSpares) better enable JVMs to cope
+ * commonPool (see COMMON_MAX_SPARES) better enable JVMs to cope
* with programming errors and abuse before running out of
* resources to do so. In other cases, users may supply factories
* that limit thread construction. The effects of bounding in this
@@ -728,7 +713,7 @@
* Default ForkJoinWorkerThreadFactory implementation; creates a
* new ForkJoinWorkerThread.
*/
- static final class DefaultForkJoinWorkerThreadFactory
+ private static final class DefaultForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new ForkJoinWorkerThread(pool);
@@ -741,7 +726,7 @@
* in WorkQueue.tryRemoveAndExec. We don't need the proxy to
* actually do anything beyond having a unique identity.
*/
- static final class EmptyTask extends ForkJoinTask<Void> {
+ private static final class EmptyTask extends ForkJoinTask<Void> {
private static final long serialVersionUID = -7721805057305804111L;
EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
public final Void getRawResult() { return null; }
@@ -749,6 +734,16 @@
public final boolean exec() { return true; }
}
+ /**
+ * Additional fields and lock created upon initialization.
+ */
+ private static final class AuxState extends ReentrantLock {
+ private static final long serialVersionUID = -6001602636862214147L;
+ volatile long stealCount; // cumulative steal count
+ long indexSeed; // index bits for registerWorker
+ AuxState() {}
+ }
+
// Constants shared across ForkJoinPool and WorkQueue
// Bounds
@@ -758,15 +753,23 @@
static final int SQMASK = 0x007e; // max 64 (even) slots
// Masks and units for WorkQueue.scanState and ctl sp subfield
- static final int SCANNING = 1; // false when running tasks
- static final int INACTIVE = 1 << 31; // must be negative
+ static final int UNSIGNALLED = 1 << 31; // must be negative
static final int SS_SEQ = 1 << 16; // version count
// Mode bits for ForkJoinPool.config and WorkQueue.config
static final int MODE_MASK = 0xffff << 16; // top half of int
- static final int LIFO_QUEUE = 0;
- static final int FIFO_QUEUE = 1 << 16;
- static final int SHARED_QUEUE = 1 << 31; // must be negative
+ static final int SPARE_WORKER = 1 << 17; // set if tc > 0 on creation
+ static final int UNREGISTERED = 1 << 18; // to skip some of deregister
+ static final int FIFO_QUEUE = 1 << 31; // must be negative
+ static final int LIFO_QUEUE = 0; // for clarity
+ static final int IS_OWNED = 1; // low bit 0 if shared
+
+ /**
+ * The maximum number of task executions from the same queue
+ * before checking other queues, bounding unfairness and impact of
+ * infinite user task recursion. Must be a power of two minus 1.
+ */
+ static final int POLL_LIMIT = (1 << 10) - 1;
/**
* Queues supporting work-stealing as well as external task
@@ -801,7 +804,8 @@
static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
// Instance fields
- volatile int scanState; // versioned, <0: inactive; odd:scanning
+
+ volatile int scanState; // versioned, negative if inactive
int stackPred; // pool stack (ctl) predecessor
int nsteals; // number of steals
int hint; // randomization and stealer index hint
@@ -814,7 +818,8 @@
final ForkJoinWorkerThread owner; // owning thread or null if shared
volatile Thread parker; // == owner during call to park; else null
volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
- volatile ForkJoinTask<?> currentSteal; // mainly used by helpStealer
+ @sun.misc.Contended("group2") // separate from other fields
+ volatile ForkJoinTask<?> currentSteal; // nonnull when running some task
WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
this.pool = pool;
@@ -834,7 +839,7 @@
* Returns the approximate number of tasks in the queue.
*/
final int queueSize() {
- int n = base - top; // non-owner callers must read base first
+ int n = base - top; // read base first
return (n >= 0) ? 0 : -n; // ignore transient negative
}
@@ -844,33 +849,31 @@
* near-empty queue has at least one unclaimed task.
*/
final boolean isEmpty() {
- ForkJoinTask<?>[] a; int n, m, s;
- return ((n = base - (s = top)) >= 0 ||
- (n == -1 && // possibly one task
- ((a = array) == null || (m = a.length - 1) < 0 ||
- U.getObject
- (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
+ ForkJoinTask<?>[] a; int n, al, s;
+ return ((n = base - (s = top)) >= 0 || // possibly one task
+ (n == -1 && ((a = array) == null ||
+ (al = a.length) == 0 ||
+ a[(al - 1) & (s - 1)] == null)));
}
/**
- * Pushes a task. Call only by owner in unshared queues. (The
- * shared-queue version is embedded in method externalPush.)
+ * Pushes a task. Call only by owner in unshared queues.
*
* @param task the task. Caller must ensure non-null.
* @throws RejectedExecutionException if array cannot be resized
*/
final void push(ForkJoinTask<?> task) {
- ForkJoinTask<?>[] a; ForkJoinPool p;
- int b = base, s = top, n;
- if ((a = array) != null) { // ignore if queue removed
- int m = a.length - 1; // fenced write for task visibility
- U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
- U.putOrderedInt(this, QTOP, s + 1);
- if ((n = s - b) <= 1) {
- if ((p = pool) != null)
- p.signalWork(p.workQueues, this);
+ U.storeFence(); // ensure safe publication
+ int s = top, al, d; ForkJoinTask<?>[] a;
+ if ((a = array) != null && (al = a.length) > 0) {
+ a[(al - 1) & s] = task; // relaxed writes OK
+ top = s + 1;
+ ForkJoinPool p = pool;
+ if ((d = base - s) == 0 && p != null) {
+ U.fullFence();
+ p.signalWork();
}
- else if (n >= m)
+ else if (al + d == 1)
growArray();
}
}
@@ -883,22 +886,23 @@
final ForkJoinTask<?>[] growArray() {
ForkJoinTask<?>[] oldA = array;
int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
- if (size > MAXIMUM_QUEUE_CAPACITY)
+ if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY)
throw new RejectedExecutionException("Queue capacity exceeded");
int oldMask, t, b;
ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
- if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
+ if (oldA != null && (oldMask = oldA.length - 1) > 0 &&
(t = top) - (b = base) > 0) {
int mask = size - 1;
do { // emulate poll from old array, push to new array
- ForkJoinTask<?> x;
- int oldj = ((b & oldMask) << ASHIFT) + ABASE;
- int j = ((b & mask) << ASHIFT) + ABASE;
- x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
+ int index = b & oldMask;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> x = (ForkJoinTask<?>)
+ U.getObjectVolatile(oldA, offset);
if (x != null &&
- U.compareAndSwapObject(oldA, oldj, x, null))
- U.putObjectVolatile(a, j, x);
+ U.compareAndSwapObject(oldA, offset, x, null))
+ a[b & mask] = x;
} while (++b != t);
+ U.storeFence();
}
return a;
}
@@ -908,16 +912,16 @@
* by owner in unshared queues.
*/
final ForkJoinTask<?> pop() {
- ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
- if ((a = array) != null && (m = a.length - 1) >= 0) {
- for (int s; (s = top - 1) - base >= 0;) {
- long j = ((m & s) << ASHIFT) + ABASE;
- if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
- break;
- if (U.compareAndSwapObject(a, j, t, null)) {
- U.putOrderedInt(this, QTOP, s);
- return t;
- }
+ int b = base, s = top, al, i; ForkJoinTask<?>[] a;
+ if ((a = array) != null && b != s && (al = a.length) > 0) {
+ int index = (al - 1) & --s;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getObject(a, offset);
+ if (t != null &&
+ U.compareAndSwapObject(a, offset, t, null)) {
+ top = s;
+ return t;
}
}
return null;
@@ -929,12 +933,15 @@
* appear in ForkJoinPool methods scan and helpStealer.
*/
final ForkJoinTask<?> pollAt(int b) {
- ForkJoinTask<?> t; ForkJoinTask<?>[] a;
- if ((a = array) != null) {
- int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
- base == b && U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
+ ForkJoinTask<?>[] a; int al;
+ if ((a = array) != null && (al = a.length) > 0) {
+ int index = (al - 1) & b;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (t != null && b++ == base &&
+ U.compareAndSwapObject(a, offset, t, null)) {
+ base = b;
return t;
}
}
@@ -945,20 +952,27 @@
* Takes next task, if one exists, in FIFO order.
*/
final ForkJoinTask<?> poll() {
- ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;
- while ((b = base) - top < 0 && (a = array) != null) {
- int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
- if (base == b) {
- if (t != null) {
- if (U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
- return t;
+ for (;;) {
+ int b = base, s = top, d, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && (d = b - s) < 0 &&
+ (al = a.length) > 0) {
+ int index = (al - 1) & b;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (b++ == base) {
+ if (t != null) {
+ if (U.compareAndSwapObject(a, offset, t, null)) {
+ base = b;
+ return t;
+ }
}
+ else if (d == -1)
+ break; // now empty
}
- else if (b + 1 == top) // now empty
- break;
}
+ else
+ break;
}
return null;
}
@@ -967,37 +981,100 @@
* Takes next task, if one exists, in order specified by mode.
*/
final ForkJoinTask<?> nextLocalTask() {
- return (config & FIFO_QUEUE) == 0 ? pop() : poll();
+ return (config < 0) ? poll() : pop();
}
/**
* Returns next task, if one exists, in order specified by mode.
*/
final ForkJoinTask<?> peek() {
- ForkJoinTask<?>[] a = array; int m;
- if (a == null || (m = a.length - 1) < 0)
- return null;
- int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base;
- int j = ((i & m) << ASHIFT) + ABASE;
- return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+ int al; ForkJoinTask<?>[] a;
+ return ((a = array) != null && (al = a.length) > 0) ?
+ a[(al - 1) & (config < 0 ? base : top - 1)] : null;
}
/**
* Pops the given task only if it is at the current top.
- * (A shared version is available only via FJP.tryExternalUnpush)
- */
- final boolean tryUnpush(ForkJoinTask<?> t) {
- ForkJoinTask<?>[] a; int s;
- if ((a = array) != null && (s = top) != base &&
- U.compareAndSwapObject
- (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
- U.putOrderedInt(this, QTOP, s);
- return true;
+ */
+ final boolean tryUnpush(ForkJoinTask<?> task) {
+ int b = base, s = top, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && b != s && (al = a.length) > 0) {
+ int index = (al - 1) & --s;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ if (U.compareAndSwapObject(a, offset, task, null)) {
+ top = s;
+ return true;
+ }
}
return false;
}
/**
+ * Shared version of push. Fails if already locked.
+ *
+ * @return status: > 0 locked, 0 possibly was empty, < 0 was nonempty
+ */
+ final int sharedPush(ForkJoinTask<?> task) {
+ int stat;
+ if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+ int b = base, s = top, al, d; ForkJoinTask<?>[] a;
+ if ((a = array) != null && (al = a.length) > 0 &&
+ al - 1 + (d = b - s) > 0) {
+ a[(al - 1) & s] = task;
+ top = s + 1; // relaxed writes OK here
+ qlock = 0;
+ stat = (d < 0 && b == base) ? d : 0;
+ }
+ else {
+ growAndSharedPush(task);
+ stat = 0;
+ }
+ }
+ else
+ stat = 1;
+ return stat;
+ }
+
+ /**
+ * Helper for sharedPush; called only when locked and resize
+ * needed.
+ */
+ private void growAndSharedPush(ForkJoinTask<?> task) {
+ try {
+ growArray();
+ int s = top, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && (al = a.length) > 0) {
+ a[(al - 1) & s] = task;
+ top = s + 1;
+ }
+ } finally {
+ qlock = 0;
+ }
+ }
+
+ /**
+ * Shared version of pop.
+ */
+ final boolean trySharedUnpush(ForkJoinTask<?> task) {
+ boolean popped = false;
+ int s = top - 1, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && (al = a.length) > 0) {
+ int index = (al - 1) & s;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>) U.getObject(a, offset);
+ if (t == task &&
+ U.compareAndSwapInt(this, QLOCK, 0, 1)) {
+ if (U.compareAndSwapObject(a, offset, task, null)) {
+ popped = true;
+ top = s;
+ }
+ U.putOrderedInt(this, QLOCK, 0);
+ }
+ }
+ return popped;
+ }
+
+ /**
* Removes and cancels all known tasks, ignoring any exceptions.
*/
final void cancelAll() {
@@ -1017,66 +1094,88 @@
// Specialized execution methods
/**
- * Polls and runs tasks until empty.
+ * Pops and executes up to POLL_LIMIT tasks or until empty.
*/
- final void pollAndExecAll() {
- for (ForkJoinTask<?> t; (t = poll()) != null;)
- t.doExec();
+ final void localPopAndExec() {
+ for (int nexec = 0;;) {
+ int b = base, s = top, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && b != s && (al = a.length) > 0) {
+ int index = (al - 1) & --s;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getAndSetObject(a, offset, null);
+ if (t != null) {
+ top = s;
+ (currentSteal = t).doExec();
+ if (++nexec > POLL_LIMIT)
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
}
/**
- * Removes and executes all local tasks. If LIFO, invokes
- * pollAndExecAll. Otherwise implements a specialized pop loop
- * to exec until empty.
+ * Polls and executes up to POLL_LIMIT tasks or until empty.
*/
- final void execLocalTasks() {
- int b = base, m, s;
- ForkJoinTask<?>[] a = array;
- if (b - (s = top - 1) <= 0 && a != null &&
- (m = a.length - 1) >= 0) {
- if ((config & FIFO_QUEUE) == 0) {
- for (ForkJoinTask<?> t;;) {
- if ((t = (ForkJoinTask<?>)U.getAndSetObject
- (a, ((m & s) << ASHIFT) + ABASE, null)) == null)
- break;
- U.putOrderedInt(this, QTOP, s);
+ final void localPollAndExec() {
+ for (int nexec = 0;;) {
+ int b = base, s = top, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && b != s && (al = a.length) > 0) {
+ int index = (al - 1) & b++;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getAndSetObject(a, offset, null);
+ if (t != null) {
+ base = b;
t.doExec();
- if (base - (s = top - 1) > 0)
+ if (++nexec > POLL_LIMIT)
break;
}
}
else
- pollAndExecAll();
+ break;
}
}
/**
- * Executes the given task and any remaining local tasks.
+ * Executes the given task and (some) remaining local tasks.
*/
final void runTask(ForkJoinTask<?> task) {
if (task != null) {
- scanState &= ~SCANNING; // mark as busy
- (currentSteal = task).doExec();
- U.putOrderedObject(this, QCURRENTSTEAL, null); // release for GC
- execLocalTasks();
+ task.doExec();
+ if (config < 0)
+ localPollAndExec();
+ else
+ localPopAndExec();
+ int ns = ++nsteals;
ForkJoinWorkerThread thread = owner;
- if (++nsteals < 0) // collect on overflow
+ currentSteal = null;
+ if (ns < 0) // collect on overflow
transferStealCount(pool);
- scanState |= SCANNING;
if (thread != null)
thread.afterTopLevelExec();
}
}
/**
- * Adds steal count to pool stealCounter if it exists, and resets.
+ * Adds steal count to pool steal count if it exists, and resets.
*/
final void transferStealCount(ForkJoinPool p) {
- AtomicLong sc;
- if (p != null && (sc = p.stealCounter) != null) {
- int s = nsteals;
+ AuxState aux;
+ if (p != null && (aux = p.auxState) != null) {
+ long s = nsteals;
nsteals = 0; // if negative, correct for overflow
- sc.getAndAdd((long)(s < 0 ? Integer.MAX_VALUE : s));
+ if (s < 0) s = Integer.MAX_VALUE;
+ aux.lock();
+ try {
+ aux.stealCount += s;
+ } finally {
+ aux.unlock();
+ }
}
}
@@ -1087,36 +1186,46 @@
* @return true if queue empty and task not known to be done
*/
final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
- ForkJoinTask<?>[] a; int m, s, b, n;
- if ((a = array) != null && (m = a.length - 1) >= 0 &&
- task != null) {
- while ((n = (s = top) - (b = base)) > 0) {
- for (ForkJoinTask<?> t;;) { // traverse from s to b
- long j = ((--s & m) << ASHIFT) + ABASE;
- if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
- return s + 1 == top; // shorter than expected
+ if (task != null && task.status >= 0) {
+ int b, s, d, al; ForkJoinTask<?>[] a;
+ while ((d = (b = base) - (s = top)) < 0 &&
+ (a = array) != null && (al = a.length) > 0) {
+ for (;;) { // traverse from s to b
+ int index = --s & (al - 1);
+ long offset = (index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (t == null)
+ break; // restart
else if (t == task) {
boolean removed = false;
if (s + 1 == top) { // pop
- if (U.compareAndSwapObject(a, j, task, null)) {
- U.putOrderedInt(this, QTOP, s);
+ if (U.compareAndSwapObject(a, offset, t, null)) {
+ top = s;
removed = true;
}
}
else if (base == b) // replace with proxy
- removed = U.compareAndSwapObject(
- a, j, task, new EmptyTask());
- if (removed)
- task.doExec();
+ removed = U.compareAndSwapObject(a, offset, t,
+ new EmptyTask());
+ if (removed) {
+ ForkJoinTask<?> ps = currentSteal;
+ (currentSteal = task).doExec();
+ currentSteal = ps;
+ }
break;
}
else if (t.status < 0 && s + 1 == top) {
- if (U.compareAndSwapObject(a, j, t, null))
- U.putOrderedInt(this, QTOP, s);
+ if (U.compareAndSwapObject(a, offset, t, null)) {
+ top = s;
+ }
break; // was cancelled
}
- if (--n == 0)
+ else if (++d == 0) {
+ if (base != b) // rescan
+ break;
return false;
+ }
}
if (task.status < 0)
return false;
@@ -1130,27 +1239,31 @@
* in either shared or owned mode. Used only by helpComplete.
*/
final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) {
- int s; ForkJoinTask<?>[] a; Object o;
- if (base - (s = top) < 0 && (a = array) != null) {
- long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
- if ((o = U.getObjectVolatile(a, j)) != null &&
- (o instanceof CountedCompleter)) {
+ int b = base, s = top, al; ForkJoinTask<?>[] a;
+ if ((a = array) != null && b != s && (al = a.length) > 0) {
+ int index = (al - 1) & (s - 1);
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> o = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (o instanceof CountedCompleter) {
CountedCompleter<?> t = (CountedCompleter<?>)o;
for (CountedCompleter<?> r = t;;) {
if (r == task) {
- if (mode < 0) { // must lock
+ if ((mode & IS_OWNED) == 0) {
+ boolean popped;
if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
- if (top == s && array == a &&
- U.compareAndSwapObject(a, j, t, null)) {
- U.putOrderedInt(this, QTOP, s - 1);
- U.putOrderedInt(this, QLOCK, 0);
+ if (popped =
+ U.compareAndSwapObject(a, offset,
+ t, null))
+ top = s - 1;
+ U.putOrderedInt(this, QLOCK, 0);
+ if (popped)
return t;
- }
- U.compareAndSwapInt(this, QLOCK, 1, 0);
}
}
- else if (U.compareAndSwapObject(a, j, t, null)) {
- U.putOrderedInt(this, QTOP, s - 1);
+ else if (U.compareAndSwapObject(a, offset,
+ t, null)) {
+ top = s - 1;
return t;
}
break;
@@ -1174,36 +1287,40 @@
* the base index, forced negative.
*/
final int pollAndExecCC(CountedCompleter<?> task) {
- int b, h; ForkJoinTask<?>[] a; Object o;
- if ((b = base) - top >= 0 || (a = array) == null)
- h = b | Integer.MIN_VALUE; // to sense movement on re-poll
- else {
- long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((o = U.getObjectVolatile(a, j)) == null)
- h = 2; // retryable
+ ForkJoinTask<?>[] a;
+ int b = base, s = top, al, h;
+ if ((a = array) != null && b != s && (al = a.length) > 0) {
+ int index = (al - 1) & b;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> o = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (o == null)
+ h = 2; // retryable
else if (!(o instanceof CountedCompleter))
- h = -1; // unmatchable
+ h = -1; // unmatchable
else {
CountedCompleter<?> t = (CountedCompleter<?>)o;
for (CountedCompleter<?> r = t;;) {
if (r == task) {
- if (base == b &&
- U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
+ if (b++ == base &&
+ U.compareAndSwapObject(a, offset, t, null)) {
+ base = b;
t.doExec();
- h = 1; // success
+ h = 1; // success
}
else
- h = 2; // lost CAS
+ h = 2; // lost CAS
break;
}
else if ((r = r.completer) == null) {
- h = -1; // unmatched
+ h = -1; // unmatched
break;
}
}
}
}
+ else
+ h = b | Integer.MIN_VALUE; // to sense movement on re-poll
return h;
}
@@ -1220,29 +1337,20 @@
}
// Unsafe mechanics. Note that some are (and must be) the same as in FJP
- private static final sun.misc.Unsafe U;
- private static final int ABASE;
- private static final int ASHIFT;
- private static final long QTOP;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long QLOCK;
- private static final long QCURRENTSTEAL;
+ private static final int ABASE;
+ private static final int ASHIFT;
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> wk = WorkQueue.class;
- Class<?> ak = ForkJoinTask[].class;
- QTOP = U.objectFieldOffset
- (wk.getDeclaredField("top"));
QLOCK = U.objectFieldOffset
- (wk.getDeclaredField("qlock"));
- QCURRENTSTEAL = U.objectFieldOffset
- (wk.getDeclaredField("currentSteal"));
- ABASE = U.arrayBaseOffset(ak);
- int scale = U.arrayIndexScale(ak);
+ (WorkQueue.class.getDeclaredField("qlock"));
+ ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
+ int scale = U.arrayIndexScale(ForkJoinTask[].class);
if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
+ throw new Error("array index scale not a power of two");
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
- } catch (Exception e) {
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -1259,9 +1367,9 @@
/**
* Permission required for callers of methods that may start or
- * kill threads.
+ * kill threads. Also used as a static lock in tryInitialize.
*/
- private static final RuntimePermission modifyThreadPermission;
+ static final RuntimePermission modifyThreadPermission;
/**
* Common (static) pool. Non-null for public use unless a static
@@ -1277,12 +1385,12 @@
* common.parallelism field to be zero, but in that case still report
* parallelism as 1 to reflect resulting caller-runs mechanics.
*/
- static final int commonParallelism;
+ static final int COMMON_PARALLELISM;
/**
* Limit on spare thread construction in tryCompensate.
*/
- private static int commonMaxSpares;
+ private static final int COMMON_MAX_SPARES;
/**
* Sequence number for creating workerNamePrefix.
@@ -1300,44 +1408,28 @@
// static configuration constants
/**
- * Initial timeout value (in nanoseconds) for the thread
+ * Initial timeout value (in milliseconds) for the thread
* triggering quiescence to park waiting for new work. On timeout,
- * the thread will instead try to shrink the number of
- * workers. The value should be large enough to avoid overly
- * aggressive shrinkage during most transient stalls (long GCs
- * etc).
+ * the thread will instead try to shrink the number of workers.
+ * The value should be large enough to avoid overly aggressive
+ * shrinkage during most transient stalls (long GCs etc).
*/
- private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec
-
- /**
- * Tolerance for idle timeouts, to cope with timer undershoots
- */
- private static final long TIMEOUT_SLOP = 20L * 1000L * 1000L; // 20ms
+ private static final long IDLE_TIMEOUT_MS = 2000L; // 2sec
/**
- * The initial value for commonMaxSpares during static
- * initialization unless overridden using System property
- * "java.util.concurrent.ForkJoinPool.common.maximumSpares". The
- * default value is far in excess of normal requirements, but also
- * far short of MAX_CAP and typical OS thread limits, so allows
- * JVMs to catch misuse/abuse before running out of resources
- * needed to do so.
+ * Tolerance for idle timeouts, to cope with timer undershoots.
*/
- private static final int DEFAULT_COMMON_MAX_SPARES = 256;
+ private static final long TIMEOUT_SLOP_MS = 20L; // 20ms
/**
- * Number of times to spin-wait before blocking. The spins (in
- * awaitRunStateLock and awaitWork) currently use randomized
- * spins. Currently set to zero to reduce CPU usage.
- *
- * If greater than zero the value of SPINS must be a power
- * of two, at least 4. A value of 2048 causes spinning for a
- * small fraction of typical context-switch times.
- *
- * If/when MWAIT-like intrinsics becomes available, they
- * may allow quieter spinning.
+ * The default value for COMMON_MAX_SPARES. Overridable using the
+ * "java.util.concurrent.ForkJoinPool.common.maximumSpares" system
+ * property. The default value is far in excess of normal
+ * requirements, but also far short of MAX_CAP and typical OS
+ * thread limits, so allows JVMs to catch misuse/abuse before
+ * running out of resources needed to do so.
*/
- private static final int SPINS = 0;
+ private static final int DEFAULT_COMMON_MAX_SPARES = 256;
/**
* Increment for seed generators. See class ThreadLocal for
@@ -1384,92 +1476,49 @@
private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
// runState bits: SHUTDOWN must be negative, others arbitrary powers of two
- private static final int RSLOCK = 1;
- private static final int RSIGNAL = 1 << 1;
- private static final int STARTED = 1 << 2;
- private static final int STOP = 1 << 29;
- private static final int TERMINATED = 1 << 30;
+ private static final int STARTED = 1;
+ private static final int STOP = 1 << 1;
+ private static final int TERMINATED = 1 << 2;
private static final int SHUTDOWN = 1 << 31;
// Instance fields
volatile long ctl; // main pool control
- volatile int runState; // lockable status
+ volatile int runState;
final int config; // parallelism, mode
- int indexSeed; // to generate worker index
+ AuxState auxState; // lock, steal counts
volatile WorkQueue[] workQueues; // main registry
+ final String workerNamePrefix; // to create worker name string
final ForkJoinWorkerThreadFactory factory;
final UncaughtExceptionHandler ueh; // per-worker UEH
- final String workerNamePrefix; // to create worker name string
- volatile AtomicLong stealCounter; // also used as sync monitor
-
- /**
- * Acquires the runState lock; returns current (locked) runState.
- */
- private int lockRunState() {
- int rs;
- return ((((rs = runState) & RSLOCK) != 0 ||
- !U.compareAndSwapInt(this, RUNSTATE, rs, rs |= RSLOCK)) ?
- awaitRunStateLock() : rs);
- }
/**
- * Spins and/or blocks until runstate lock is available. See
- * above for explanation.
+ * Instantiates fields upon first submission, or upon shutdown if
+ * no submissions. If checkTermination true, also responds to
+ * termination by external calls submitting tasks.
*/
- private int awaitRunStateLock() {
- Object lock;
- boolean wasInterrupted = false;
- for (int spins = SPINS, r = 0, rs, ns;;) {
- if (((rs = runState) & RSLOCK) == 0) {
- if (U.compareAndSwapInt(this, RUNSTATE, rs, ns = rs | RSLOCK)) {
- if (wasInterrupted) {
- try {
- Thread.currentThread().interrupt();
- } catch (SecurityException ignore) {
- }
- }
- return ns;
- }
- }
- else if (r == 0)
- r = ThreadLocalRandom.nextSecondarySeed();
- else if (spins > 0) {
- r ^= r << 6; r ^= r >>> 21; r ^= r << 7; // xorshift
- if (r >= 0)
- --spins;
- }
- else if ((rs & STARTED) == 0 || (lock = stealCounter) == null)
- Thread.yield(); // initialization race
- else if (U.compareAndSwapInt(this, RUNSTATE, rs, rs | RSIGNAL)) {
- synchronized (lock) {
- if ((runState & RSIGNAL) != 0) {
- try {
- lock.wait();
- } catch (InterruptedException ie) {
- if (!(Thread.currentThread() instanceof
- ForkJoinWorkerThread))
- wasInterrupted = true;
- }
- }
- else
- lock.notifyAll();
+ private void tryInitialize(boolean checkTermination) {
+ if (runState == 0) { // bootstrap by locking static field
+ int p = config & SMASK;
+ int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
+ n |= n >>> 1; // create workQueues array with size a power of two
+ n |= n >>> 2;
+ n |= n >>> 4;
+ n |= n >>> 8;
+ n |= n >>> 16;
+ n = ((n + 1) << 1) & SMASK;
+ AuxState aux = new AuxState();
+ WorkQueue[] ws = new WorkQueue[n];
+ synchronized (modifyThreadPermission) { // double-check
+ if (runState == 0) {
+ workQueues = ws;
+ auxState = aux;
+ runState = STARTED;
}
}
}
- }
-
- /**
- * Unlocks and sets runState to newRunState.
- *
- * @param oldRunState a value returned from lockRunState
- * @param newRunState the next value (must have lock bit clear).
- */
- private void unlockRunState(int oldRunState, int newRunState) {
- if (!U.compareAndSwapInt(this, RUNSTATE, oldRunState, newRunState)) {
- Object lock = stealCounter;
- runState = newRunState; // clears RSIGNAL bit
- if (lock != null)
- synchronized (lock) { lock.notifyAll(); }
+ if (checkTermination && runState < 0) {
+ tryTerminate(false, false); // help terminate
+ throw new RejectedExecutionException();
}
}
@@ -1480,14 +1529,18 @@
* count has already been incremented as a reservation. Invokes
* deregisterWorker on any failure.
*
+ * @param isSpare true if this is a spare thread
* @return true if successful
*/
- private boolean createWorker() {
+ private boolean createWorker(boolean isSpare) {
ForkJoinWorkerThreadFactory fac = factory;
Throwable ex = null;
ForkJoinWorkerThread wt = null;
+ WorkQueue q;
try {
if (fac != null && (wt = fac.newThread(this)) != null) {
+ if (isSpare && (q = wt.workQueue) != null)
+ q.config |= SPARE_WORKER;
wt.start();
return true;
}
@@ -1507,21 +1560,12 @@
* this holds (otherwise, a new worker is not needed).
*/
private void tryAddWorker(long c) {
- boolean add = false;
do {
long nc = ((AC_MASK & (c + AC_UNIT)) |
(TC_MASK & (c + TC_UNIT)));
- if (ctl == c) {
- int rs, stop; // check if terminating
- if ((stop = (rs = lockRunState()) & STOP) == 0)
- add = U.compareAndSwapLong(this, CTL, c, nc);
- unlockRunState(rs, rs & ~RSLOCK);
- if (stop != 0)
- break;
- if (add) {
- createWorker();
- break;
- }
+ if (ctl == c && U.compareAndSwapLong(this, CTL, c, nc)) {
+ createWorker(false);
+ break;
}
} while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
}
@@ -1535,37 +1579,39 @@
*/
final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
UncaughtExceptionHandler handler;
+ AuxState aux;
wt.setDaemon(true); // configure thread
if ((handler = ueh) != null)
wt.setUncaughtExceptionHandler(handler);
WorkQueue w = new WorkQueue(this, wt);
int i = 0; // assign a pool index
int mode = config & MODE_MASK;
- int rs = lockRunState();
- try {
- WorkQueue[] ws; int n; // skip if no array
- if ((ws = workQueues) != null && (n = ws.length) > 0) {
- int s = indexSeed += SEED_INCREMENT; // unlikely to collide
- int m = n - 1;
- i = ((s << 1) | 1) & m; // odd-numbered indices
- if (ws[i] != null) { // collision
- int probes = 0; // step by approx half n
- int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
- while (ws[i = (i + step) & m] != null) {
- if (++probes >= n) {
- workQueues = ws = Arrays.copyOf(ws, n <<= 1);
- m = n - 1;
- probes = 0;
+ if ((aux = auxState) != null) {
+ aux.lock();
+ try {
+ int s = (int)(aux.indexSeed += SEED_INCREMENT), n, m;
+ WorkQueue[] ws = workQueues;
+ if (ws != null && (n = ws.length) > 0) {
+ i = (m = n - 1) & ((s << 1) | 1); // odd-numbered indices
+ if (ws[i] != null) { // collision
+ int probes = 0; // step by approx half n
+ int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
+ while (ws[i = (i + step) & m] != null) {
+ if (++probes >= n) {
+ workQueues = ws = Arrays.copyOf(ws, n <<= 1);
+ m = n - 1;
+ probes = 0;
+ }
}
}
+ w.hint = s; // use as random seed
+ w.config = i | mode;
+ w.scanState = i | (s & 0x7fff0000); // random seq bits
+ ws[i] = w;
}
- w.hint = s; // use as random seed
- w.config = i | mode;
- w.scanState = i; // publication fence
- ws[i] = w;
+ } finally {
+ aux.unlock();
}
- } finally {
- unlockRunState(rs, rs & ~RSLOCK);
}
wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
return w;
@@ -1583,31 +1629,40 @@
final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
WorkQueue w = null;
if (wt != null && (w = wt.workQueue) != null) {
- WorkQueue[] ws; // remove index from array
+ AuxState aux; WorkQueue[] ws; // remove index from array
int idx = w.config & SMASK;
- int rs = lockRunState();
- if ((ws = workQueues) != null && ws.length > idx && ws[idx] == w)
- ws[idx] = null;
- unlockRunState(rs, rs & ~RSLOCK);
+ int ns = w.nsteals;
+ if ((aux = auxState) != null) {
+ aux.lock();
+ try {
+ if ((ws = workQueues) != null && ws.length > idx &&
+ ws[idx] == w)
+ ws[idx] = null;
+ aux.stealCount += ns;
+ } finally {
+ aux.unlock();
+ }
+ }
}
- long c; // decrement counts
- do {} while (!U.compareAndSwapLong
- (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
- (TC_MASK & (c - TC_UNIT)) |
- (SP_MASK & c))));
+ if (w == null || (w.config & UNREGISTERED) == 0) { // else pre-adjusted
+ long c; // decrement counts
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
+ (TC_MASK & (c - TC_UNIT)) |
+ (SP_MASK & c))));
+ }
if (w != null) {
+ w.currentSteal = null;
w.qlock = -1; // ensure set
- w.transferStealCount(this);
w.cancelAll(); // cancel remaining tasks
}
- for (;;) { // possibly replace
- WorkQueue[] ws; int m, sp;
- if (tryTerminate(false, false) || w == null || w.array == null ||
- (runState & STOP) != 0 || (ws = workQueues) == null ||
- (m = ws.length - 1) < 0) // already terminating
+ while (tryTerminate(false, false) >= 0) { // possibly replace
+ WorkQueue[] ws; int wl, sp; long c;
+ if (w == null || w.array == null ||
+ (ws = workQueues) == null || (wl = ws.length) <= 0)
break;
- if ((sp = (int)(c = ctl)) != 0) { // wake up replacement
- if (tryRelease(c, ws[sp & m], AC_UNIT))
+ else if ((sp = (int)(c = ctl)) != 0) { // wake up replacement
+ if (tryRelease(c, ws[(wl - 1) & sp], AC_UNIT))
break;
}
else if (ex != null && (c & ADD_WORKER) != 0L) {
@@ -1627,35 +1682,33 @@
/**
* Tries to create or activate a worker if too few are active.
- *
- * @param ws the worker array to use to find signallees
- * @param q a WorkQueue --if non-null, don't retry if now empty
*/
- final void signalWork(WorkQueue[] ws, WorkQueue q) {
- long c; int sp, i; WorkQueue v; Thread p;
- while ((c = ctl) < 0L) { // too few active
- if ((sp = (int)c) == 0) { // no idle workers
- if ((c & ADD_WORKER) != 0L) // too few workers
+ final void signalWork() {
+ for (;;) {
+ long c; int sp, i; WorkQueue v; WorkQueue[] ws;
+ if ((c = ctl) >= 0L) // enough workers
+ break;
+ else if ((sp = (int)c) == 0) { // no idle workers
+ if ((c & ADD_WORKER) != 0L) // too few workers
tryAddWorker(c);
break;
}
- if (ws == null) // unstarted/terminated
- break;
- if (ws.length <= (i = sp & SMASK)) // terminated
- break;
- if ((v = ws[i]) == null) // terminating
- break;
- int vs = (sp + SS_SEQ) & ~INACTIVE; // next scanState
- int d = sp - v.scanState; // screen CAS
- long nc = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & v.stackPred);
- if (d == 0 && U.compareAndSwapLong(this, CTL, c, nc)) {
- v.scanState = vs; // activate v
- if ((p = v.parker) != null)
- U.unpark(p);
- break;
+ else if ((ws = workQueues) == null)
+ break; // unstarted/terminated
+ else if (ws.length <= (i = sp & SMASK))
+ break; // terminated
+ else if ((v = ws[i]) == null)
+ break; // terminating
+ else {
+ int ns = sp & ~UNSIGNALLED;
+ int vs = v.scanState;
+ long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
+ if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
+ v.scanState = ns;
+ LockSupport.unpark(v.parker);
+ break;
+ }
}
- if (q != null && q.base == q.top) // no more work
- break;
}
}
@@ -1670,174 +1723,287 @@
* @return true if successful
*/
private boolean tryRelease(long c, WorkQueue v, long inc) {
- int sp = (int)c, vs = (sp + SS_SEQ) & ~INACTIVE; Thread p;
- if (v != null && v.scanState == sp) { // v is at top of stack
- long nc = (UC_MASK & (c + inc)) | (SP_MASK & v.stackPred);
- if (U.compareAndSwapLong(this, CTL, c, nc)) {
- v.scanState = vs;
- if ((p = v.parker) != null)
- U.unpark(p);
+ int sp = (int)c, ns = sp & ~UNSIGNALLED;
+ if (v != null) {
+ int vs = v.scanState;
+ long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + inc));
+ if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
+ v.scanState = ns;
+ LockSupport.unpark(v.parker);
return true;
}
}
return false;
}
- // Scanning for tasks
+ /**
+ * With approx probability of a missed signal, tries (once) to
+ * reactivate worker w (or some other worker), failing if stale or
+ * known to be already active.
+ *
+ * @param w the worker
+ * @param ws the workQueue array to use
+ * @param r random seed
+ */
+ private void tryReactivate(WorkQueue w, WorkQueue[] ws, int r) {
+ long c; int sp, wl; WorkQueue v;
+ if ((sp = (int)(c = ctl)) != 0 && w != null &&
+ ws != null && (wl = ws.length) > 0 &&
+ ((sp ^ r) & SS_SEQ) == 0 &&
+ (v = ws[(wl - 1) & sp]) != null) {
+ long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
+ int ns = sp & ~UNSIGNALLED;
+ if (w.scanState < 0 &&
+ v.scanState == sp &&
+ U.compareAndSwapLong(this, CTL, c, nc)) {
+ v.scanState = ns;
+ LockSupport.unpark(v.parker);
+ }
+ }
+ }
+
+ /**
+ * If worker w exists and is active, enqueues and sets status to inactive.
+ *
+ * @param w the worker
+ * @param ss current (non-negative) scanState
+ */
+ private void inactivate(WorkQueue w, int ss) {
+ int ns = (ss + SS_SEQ) | UNSIGNALLED;
+ long lc = ns & SP_MASK, nc, c;
+ if (w != null) {
+ w.scanState = ns;
+ do {
+ nc = lc | (UC_MASK & ((c = ctl) - AC_UNIT));
+ w.stackPred = (int)c;
+ } while (!U.compareAndSwapLong(this, CTL, c, nc));
+ }
+ }
+
+ /**
+ * Possibly blocks worker w waiting for signal, or returns
+ * negative status if the worker should terminate. May return
+ * without status change if multiple stale unparks and/or
+ * interrupts occur.
+ *
+ * @param w the calling worker
+ * @return negative if w should terminate
+ */
+ private int awaitWork(WorkQueue w) {
+ int stat = 0;
+ if (w != null && w.scanState < 0) {
+ long c = ctl;
+ if ((int)(c >> AC_SHIFT) + (config & SMASK) <= 0)
+ stat = timedAwaitWork(w, c); // possibly quiescent
+ else if ((runState & STOP) != 0)
+ stat = w.qlock = -1; // pool terminating
+ else if (w.scanState < 0) {
+ w.parker = Thread.currentThread();
+ if (w.scanState < 0) // recheck after write
+ LockSupport.park(this);
+ w.parker = null;
+ if ((runState & STOP) != 0)
+ stat = w.qlock = -1; // recheck
+ else if (w.scanState < 0)
+ Thread.interrupted(); // clear status
+ }
+ }
+ return stat;
+ }
+
+ /**
+ * Possibly triggers shutdown and tries (once) to block worker
+ * when pool is (or may be) quiescent. Waits up to a duration
+ * determined by number of workers. On timeout, if ctl has not
+ * changed, terminates the worker, which will in turn wake up
+ * another worker to possibly repeat this process.
+ *
+ * @param w the calling worker
+ * @return negative if w should terminate
+ */
+ private int timedAwaitWork(WorkQueue w, long c) {
+ int stat = 0;
+ int scale = 1 - (short)(c >>> TC_SHIFT);
+ long deadline = (((scale <= 0) ? 1 : scale) * IDLE_TIMEOUT_MS +
+ System.currentTimeMillis());
+ if ((runState >= 0 || (stat = tryTerminate(false, false)) > 0) &&
+ w != null && w.scanState < 0) {
+ int ss; AuxState aux;
+ w.parker = Thread.currentThread();
+ if (w.scanState < 0)
+ LockSupport.parkUntil(this, deadline);
+ w.parker = null;
+ if ((runState & STOP) != 0)
+ stat = w.qlock = -1; // pool terminating
+ else if ((ss = w.scanState) < 0 && !Thread.interrupted() &&
+ (int)c == ss && (aux = auxState) != null && ctl == c &&
+ deadline - System.currentTimeMillis() <= TIMEOUT_SLOP_MS) {
+ aux.lock();
+ try { // pre-deregister
+ WorkQueue[] ws;
+ int cfg = w.config, idx = cfg & SMASK;
+ long nc = ((UC_MASK & (c - TC_UNIT)) |
+ (SP_MASK & w.stackPred));
+ if ((runState & STOP) == 0 &&
+ (ws = workQueues) != null &&
+ idx < ws.length && idx >= 0 && ws[idx] == w &&
+ U.compareAndSwapLong(this, CTL, c, nc)) {
+ ws[idx] = null;
+ w.config = cfg | UNREGISTERED;
+ stat = w.qlock = -1;
+ }
+ } finally {
+ aux.unlock();
+ }
+ }
+ }
+ return stat;
+ }
+
+ /**
+ * If the given worker is a spare with no queued tasks, and there
+ * are enough existing workers, drops it from ctl counts and sets
+ * its state to terminated.
+ *
+ * @param w the calling worker -- must be a spare
+ * @return true if dropped (in which case it must not process more tasks)
+ */
+ private boolean tryDropSpare(WorkQueue w) {
+ if (w != null && w.isEmpty()) { // no local tasks
+ long c; int sp, wl; WorkQueue[] ws; WorkQueue v;
+ while ((short)((c = ctl) >> TC_SHIFT) > 0 &&
+ ((sp = (int)c) != 0 || (int)(c >> AC_SHIFT) > 0) &&
+ (ws = workQueues) != null && (wl = ws.length) > 0) {
+ boolean dropped, canDrop;
+ if (sp == 0) { // no queued workers
+ long nc = ((AC_MASK & (c - AC_UNIT)) |
+ (TC_MASK & (c - TC_UNIT)) | (SP_MASK & c));
+ dropped = U.compareAndSwapLong(this, CTL, c, nc);
+ }
+ else if (
+ (v = ws[(wl - 1) & sp]) == null || v.scanState != sp)
+ dropped = false; // stale; retry
+ else {
+ long nc = v.stackPred & SP_MASK;
+ if (w == v || w.scanState >= 0) {
+ canDrop = true; // w unqueued or topmost
+ nc |= ((AC_MASK & c) | // ensure replacement
+ (TC_MASK & (c - TC_UNIT)));
+ }
+ else { // w may be queued
+ canDrop = false; // help uncover
+ nc |= ((AC_MASK & (c + AC_UNIT)) |
+ (TC_MASK & c));
+ }
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ v.scanState = sp & ~UNSIGNALLED;
+ LockSupport.unpark(v.parker);
+ dropped = canDrop;
+ }
+ else
+ dropped = false;
+ }
+ if (dropped) { // pre-deregister
+ int cfg = w.config, idx = cfg & SMASK;
+ if (idx >= 0 && idx < ws.length && ws[idx] == w)
+ ws[idx] = null;
+ w.config = cfg | UNREGISTERED;
+ w.qlock = -1;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
/**
* Top-level runloop for workers, called by ForkJoinWorkerThread.run.
*/
final void runWorker(WorkQueue w) {
- w.growArray(); // allocate queue
- int seed = w.hint; // initially holds randomization hint
- int r = (seed == 0) ? 1 : seed; // avoid 0 for xorShift
- for (ForkJoinTask<?> t;;) {
- if ((t = scan(w, r)) != null)
- w.runTask(t);
- else if (!awaitWork(w, r))
- break;
- r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
+ w.growArray(); // allocate queue
+ int bound = (w.config & SPARE_WORKER) != 0 ? 0 : POLL_LIMIT;
+ long seed = w.hint * 0xdaba0b6eb09322e3L; // initial random seed
+ if ((runState & STOP) == 0) {
+ for (long r = (seed == 0L) ? 1L : seed;;) { // ensure nonzero
+ if (bound == 0 && tryDropSpare(w))
+ break;
+ // high bits of prev seed for step; current low bits for idx
+ int step = (int)(r >>> 48) | 1;
+ r ^= r >>> 12; r ^= r << 25; r ^= r >>> 27; // xorshift
+ if (scan(w, bound, step, (int)r) < 0 && awaitWork(w) < 0)
+ break;
+ }
}
}
+ // Scanning for tasks
+
/**
- * Scans for and tries to steal a top-level task. Scans start at a
- * random location, randomly moving on apparent contention,
- * otherwise continuing linearly until reaching two consecutive
- * empty passes over all queues with the same checksum (summing
- * each base index of each queue, that moves on each steal), at
- * which point the worker tries to inactivate and then re-scans,
- * attempting to re-activate (itself or some other worker) if
- * finding a task; otherwise returning null to await work. Scans
- * otherwise touch as little memory as possible, to reduce
- * disruption on other scanning threads.
+ * Repeatedly scans for and tries to steal and execute (via
+ * workQueue.runTask) a queued task. Each scan traverses queues in
+ * pseudorandom permutation. Upon finding a non-empty queue, makes
+ * at most the given bound attempts to re-poll (fewer if
+ * contended) on the same queue before returning (impossible
+ * scanState value) 0 to restart scan. Else returns after at least
+ * 1 and at most 32 full scans.
*
* @param w the worker (via its WorkQueue)
- * @param r a random seed
- * @return a task, or null if none found
+ * @param bound repoll bound as bitmask (0 if spare)
+ * @param step (circular) index increment per iteration (must be odd)
+ * @param r a random seed for origin index
+ * @return negative if should await signal
*/
- private ForkJoinTask<?> scan(WorkQueue w, int r) {
- WorkQueue[] ws; int m;
- if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) {
- int ss = w.scanState; // initially non-negative
- for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
- WorkQueue q; ForkJoinTask<?>[] a; ForkJoinTask<?> t;
- int b, n; long c;
- if ((q = ws[k]) != null) {
- if ((n = (b = q.base) - q.top) < 0 &&
- (a = q.array) != null) { // non-empty
- long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
- if ((t = ((ForkJoinTask<?>)
- U.getObjectVolatile(a, i))) != null &&
- q.base == b) {
- if (ss >= 0) {
- if (U.compareAndSwapObject(a, i, t, null)) {
- q.base = b + 1;
- if (n < -1) // signal others
- signalWork(ws, q);
- return t;
- }
- }
- else if (oldSum == 0 && // try to activate
- w.scanState < 0)
- tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
- }
- if (ss < 0) // refresh
- ss = w.scanState;
- r ^= r << 1; r ^= r >>> 3; r ^= r << 10;
- origin = k = r & m; // move and rescan
- oldSum = checkSum = 0;
- continue;
+ private int scan(WorkQueue w, int bound, int step, int r) {
+ int stat = 0, wl; WorkQueue[] ws;
+ if ((ws = workQueues) != null && w != null && (wl = ws.length) > 0) {
+ for (int m = wl - 1,
+ origin = m & r, idx = origin,
+ npolls = 0,
+ ss = w.scanState;;) { // negative if inactive
+ WorkQueue q; ForkJoinTask<?>[] a; int b, al;
+ if ((q = ws[idx]) != null && (b = q.base) - q.top < 0 &&
+ (a = q.array) != null && (al = a.length) > 0) {
+ int index = (al - 1) & b;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (t == null)
+ break; // empty or busy
+ else if (b++ != q.base)
+ break; // busy
+ else if (ss < 0) {
+ tryReactivate(w, ws, r);
+ break; // retry upon rescan
}
- checkSum += b;
- }
- if ((k = (k + 1) & m) == origin) { // continue until stable
- if ((ss >= 0 || (ss == (ss = w.scanState))) &&
- oldSum == (oldSum = checkSum)) {
- if (ss < 0 || w.qlock < 0) // already inactive
+ else if (!U.compareAndSwapObject(a, offset, t, null))
+ break; // contended
+ else {
+ q.base = b;
+ w.currentSteal = t;
+ if (b != q.top) // propagate signal
+ signalWork();
+ w.runTask(t);
+ if (++npolls > bound)
break;
- int ns = ss | INACTIVE; // try to inactivate
- long nc = ((SP_MASK & ns) |
- (UC_MASK & ((c = ctl) - AC_UNIT)));
- w.stackPred = (int)c; // hold prev stack top
- U.putInt(w, QSCANSTATE, ns);
- if (U.compareAndSwapLong(this, CTL, c, nc))
- ss = ns;
- else
- w.scanState = ss; // back out
}
- checkSum = 0;
+ }
+ else if (npolls != 0) // rescan
+ break;
+ else if ((idx = (idx + step) & m) == origin) {
+ if (ss < 0) { // await signal
+ stat = ss;
+ break;
+ }
+ else if (r >= 0) {
+ inactivate(w, ss);
+ break;
+ }
+ else
+ r <<= 1; // at most 31 rescans
}
}
}
- return null;
- }
-
- /**
- * Possibly blocks worker w waiting for a task to steal, or
- * returns false if the worker should terminate. If inactivating
- * w has caused the pool to become quiescent, checks for pool
- * termination, and, so long as this is not the only worker, waits
- * for up to a given duration. On timeout, if ctl has not
- * changed, terminates the worker, which will in turn wake up
- * another worker to possibly repeat this process.
- *
- * @param w the calling worker
- * @param r a random seed (for spins)
- * @return false if the worker should terminate
- */
- private boolean awaitWork(WorkQueue w, int r) {
- if (w == null || w.qlock < 0) // w is terminating
- return false;
- for (int pred = w.stackPred, spins = SPINS, ss;;) {
- if ((ss = w.scanState) >= 0)
- break;
- else if (spins > 0) {
- r ^= r << 6; r ^= r >>> 21; r ^= r << 7;
- if (r >= 0 && --spins == 0) { // randomize spins
- WorkQueue v; WorkQueue[] ws; int s, j; AtomicLong sc;
- if (pred != 0 && (ws = workQueues) != null &&
- (j = pred & SMASK) < ws.length &&
- (v = ws[j]) != null && // see if pred parking
- (v.parker == null || v.scanState >= 0))
- spins = SPINS; // continue spinning
- }
- }
- else if (w.qlock < 0) // recheck after spins
- return false;
- else if (!Thread.interrupted()) {
- long c, prevctl, parkTime, deadline;
- int ac = (int)((c = ctl) >> AC_SHIFT) + (config & SMASK);
- if ((ac <= 0 && tryTerminate(false, false)) ||
- (runState & STOP) != 0) // pool terminating
- return false;
- if (ac <= 0 && ss == (int)c) { // is last waiter
- prevctl = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & pred);
- int t = (short)(c >>> TC_SHIFT); // shrink excess spares
- if (t > 2 && U.compareAndSwapLong(this, CTL, c, prevctl))
- return false; // else use timed wait
- parkTime = IDLE_TIMEOUT * ((t >= 0) ? 1 : 1 - t);
- deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
- }
- else
- prevctl = parkTime = deadline = 0L;
- Thread wt = Thread.currentThread();
- U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport
- w.parker = wt;
- if (w.scanState < 0 && ctl == c) // recheck before park
- U.park(false, parkTime);
- U.putOrderedObject(w, QPARKER, null);
- U.putObject(wt, PARKBLOCKER, null);
- if (w.scanState >= 0)
- break;
- if (parkTime != 0L && ctl == c &&
- deadline - System.nanoTime() <= 0L &&
- U.compareAndSwapLong(this, CTL, c, prevctl))
- return false; // shrink pool
- }
- }
- return true;
+ return stat;
}
// Joining tasks
@@ -1849,7 +2015,7 @@
* eligible tasks popped from the worker's own queue (via
* popCC). Otherwise it scans others, randomly moving on
* contention or execution, deciding to give up based on a
- * checksum (via return codes frob pollAndExecCC). The maxTasks
+ * checksum (via return codes from pollAndExecCC). The maxTasks
* argument supports external usages; internal calls use zero,
* allowing unbounded steps (external calls trap non-positive
* values).
@@ -1860,15 +2026,17 @@
*/
final int helpComplete(WorkQueue w, CountedCompleter<?> task,
int maxTasks) {
- WorkQueue[] ws; int s = 0, m;
- if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
+ WorkQueue[] ws; int s = 0, wl;
+ if ((ws = workQueues) != null && (wl = ws.length) > 1 &&
task != null && w != null) {
- int mode = w.config; // for popCC
- int r = w.hint ^ w.top; // arbitrary seed for origin
- int origin = r & m; // first queue to scan
- int h = 1; // 1:ran, >1:contended, <0:hash
- for (int k = origin, oldSum = 0, checkSum = 0;;) {
- CountedCompleter<?> p; WorkQueue q;
+ for (int m = wl - 1,
+ mode = w.config,
+ r = ~mode, // scanning seed
+ origin = r & m, k = origin, // first queue to scan
+ step = 3, // first scan step
+ h = 1, // 1:ran, >1:contended, <0:hash
+ oldSum = 0, checkSum = 0;;) {
+ CountedCompleter<?> p; WorkQueue q; int i;
if ((s = task.status) < 0)
break;
if (h == 1 && (p = w.popCC(task, mode)) != null) {
@@ -1878,19 +2046,20 @@
origin = k; // reset
oldSum = checkSum = 0;
}
- else { // poll other queues
- if ((q = ws[k]) == null)
+ else { // poll other worker queues
+ if ((i = k | 1) < 0 || i > m || (q = ws[i]) == null)
h = 0;
else if ((h = q.pollAndExecCC(task)) < 0)
checkSum += h;
if (h > 0) {
if (h == 1 && maxTasks != 0 && --maxTasks == 0)
break;
+ step = (r >>> 16) | 3;
r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
- origin = k = r & m; // move and restart
+ k = origin = r & m; // move and restart
oldSum = checkSum = 0;
}
- else if ((k = (k + 1) & m) == origin) {
+ else if ((k = (k + step) & m) == origin) {
if (oldSum == (oldSum = checkSum))
break;
checkSum = 0;
@@ -1903,7 +2072,7 @@
/**
* Tries to locate and execute tasks for a stealer of the given
- * task, or in turn one of its stealers, Traces currentSteal ->
+ * task, or in turn one of its stealers. Traces currentSteal ->
* currentJoin links looking for a thread working on a descendant
* of the given task and with a non-empty queue to steal back and
* execute tasks from. The first call to this method upon a
@@ -1915,63 +2084,74 @@
* @param task the task to join
*/
private void helpStealer(WorkQueue w, ForkJoinTask<?> task) {
- WorkQueue[] ws = workQueues;
- int oldSum = 0, checkSum, m;
- if (ws != null && (m = ws.length - 1) >= 0 && w != null &&
- task != null) {
- do { // restart point
- checkSum = 0; // for stability check
+ if (task != null && w != null) {
+ ForkJoinTask<?> ps = w.currentSteal;
+ WorkQueue[] ws; int wl, oldSum = 0;
+ outer: while (w.tryRemoveAndExec(task) && task.status >= 0 &&
+ (ws = workQueues) != null && (wl = ws.length) > 0) {
ForkJoinTask<?> subtask;
+ int m = wl - 1, checkSum = 0; // for stability check
WorkQueue j = w, v; // v is subtask stealer
descent: for (subtask = task; subtask.status >= 0; ) {
- for (int h = j.hint | 1, k = 0, i; ; k += 2) {
- if (k > m) // can't find stealer
- break descent;
- if ((v = ws[i = (h + k) & m]) != null) {
+ for (int h = j.hint | 1, k = 0, i;;) {
+ if ((v = ws[i = (h + (k << 1)) & m]) != null) {
if (v.currentSteal == subtask) {
j.hint = i;
break;
}
checkSum += v.base;
}
+ if (++k > m) // can't find stealer
+ break outer;
}
+
for (;;) { // help v or descend
- ForkJoinTask<?>[] a; int b;
+ ForkJoinTask<?>[] a; int b, al;
+ if (subtask.status < 0) // too late to help
+ break descent;
checkSum += (b = v.base);
ForkJoinTask<?> next = v.currentJoin;
- if (subtask.status < 0 || j.currentJoin != subtask ||
- v.currentSteal != subtask) // stale
- break descent;
- if (b - v.top >= 0 || (a = v.array) == null) {
- if ((subtask = next) == null)
+ ForkJoinTask<?> t = null;
+ if ((a = v.array) != null && (al = a.length) > 0) {
+ int index = (al - 1) & b;
+ long offset = ((long)index << ASHIFT) + ABASE;
+ t = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, offset);
+ if (t != null && b++ == v.base) {
+ if (j.currentJoin != subtask ||
+ v.currentSteal != subtask ||
+ subtask.status < 0)
+ break descent; // stale
+ if (U.compareAndSwapObject(a, offset, t, null)) {
+ v.base = b;
+ w.currentSteal = t;
+ for (int top = w.top;;) {
+ t.doExec(); // help
+ w.currentSteal = ps;
+ if (task.status < 0)
+ break outer;
+ if (w.top == top)
+ break; // run local tasks
+ if ((t = w.pop()) == null)
+ break descent;
+ w.currentSteal = t;
+ }
+ }
+ }
+ }
+ if (t == null && b == v.base && b - v.top >= 0) {
+ if ((subtask = next) == null) { // try to descend
+ if (next == v.currentJoin &&
+ oldSum == (oldSum = checkSum))
+ break outer;
break descent;
+ }
j = v;
break;
}
- int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
- ForkJoinTask<?> t = ((ForkJoinTask<?>)
- U.getObjectVolatile(a, i));
- if (v.base == b) {
- if (t == null) // stale
- break descent;
- if (U.compareAndSwapObject(a, i, t, null)) {
- v.base = b + 1;
- ForkJoinTask<?> ps = w.currentSteal;
- int top = w.top;
- do {
- U.putOrderedObject(w, QCURRENTSTEAL, t);
- t.doExec(); // clear local tasks too
- } while (task.status >= 0 &&
- w.top != top &&
- (t = w.pop()) != null);
- U.putOrderedObject(w, QCURRENTSTEAL, ps);
- if (w.base != w.top)
- return; // can't further help
- }
- }
}
}
- } while (task.status >= 0 && oldSum != (oldSum = checkSum));
+ }
}
}
@@ -1984,45 +2164,44 @@
* @param w caller
*/
private boolean tryCompensate(WorkQueue w) {
- boolean canBlock;
- WorkQueue[] ws; long c; int m, pc, sp;
- if (w == null || w.qlock < 0 || // caller terminating
- (ws = workQueues) == null || (m = ws.length - 1) <= 0 ||
- (pc = config & SMASK) == 0) // parallelism disabled
+ boolean canBlock; int wl;
+ long c = ctl;
+ WorkQueue[] ws = workQueues;
+ int pc = config & SMASK;
+ int ac = pc + (int)(c >> AC_SHIFT);
+ int tc = pc + (short)(c >> TC_SHIFT);
+ if (w == null || w.qlock < 0 || pc == 0 || // terminating or disabled
+ ws == null || (wl = ws.length) <= 0)
canBlock = false;
- else if ((sp = (int)(c = ctl)) != 0) // release idle worker
- canBlock = tryRelease(c, ws[sp & m], 0L);
else {
- int ac = (int)(c >> AC_SHIFT) + pc;
- int tc = (short)(c >> TC_SHIFT) + pc;
- int nbusy = 0; // validate saturation
- for (int i = 0; i <= m; ++i) { // two passes of odd indices
- WorkQueue v;
- if ((v = ws[((i << 1) | 1) & m]) != null) {
- if ((v.scanState & SCANNING) != 0)
- break;
- ++nbusy;
+ int m = wl - 1, sp;
+ boolean busy = true; // validate ac
+ for (int i = 0; i <= m; ++i) {
+ int k; WorkQueue v;
+ if ((k = (i << 1) | 1) <= m && k >= 0 && (v = ws[k]) != null &&
+ v.scanState >= 0 && v.currentSteal == null) {
+ busy = false;
+ break;
}
}
- if (nbusy != (tc << 1) || ctl != c)
- canBlock = false; // unstable or stale
+ if (!busy || ctl != c)
+ canBlock = false; // unstable or stale
+ else if ((sp = (int)c) != 0) // release idle worker
+ canBlock = tryRelease(c, ws[m & sp], 0L);
else if (tc >= pc && ac > 1 && w.isEmpty()) {
long nc = ((AC_MASK & (c - AC_UNIT)) |
- (~AC_MASK & c)); // uncompensated
+ (~AC_MASK & c)); // uncompensated
canBlock = U.compareAndSwapLong(this, CTL, c, nc);
}
else if (tc >= MAX_CAP ||
- (this == common && tc >= pc + commonMaxSpares))
+ (this == common && tc >= pc + COMMON_MAX_SPARES))
throw new RejectedExecutionException(
"Thread limit exceeded replacing blocked worker");
- else { // similar to tryAddWorker
- boolean add = false; int rs; // CAS within lock
- long nc = ((AC_MASK & c) |
- (TC_MASK & (c + TC_UNIT)));
- if (((rs = lockRunState()) & STOP) == 0)
- add = U.compareAndSwapLong(this, CTL, c, nc);
- unlockRunState(rs, rs & ~RSLOCK);
- canBlock = add && createWorker(); // throws on exception
+ else { // similar to tryAddWorker
+ boolean isSpare = (tc >= pc);
+ long nc = (AC_MASK & c) | (TC_MASK & (c + TC_UNIT));
+ canBlock = (U.compareAndSwapLong(this, CTL, c, nc) &&
+ createWorker(isSpare)); // throws on exception
}
}
return canBlock;
@@ -2038,33 +2217,35 @@
*/
final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
int s = 0;
- if (task != null && w != null) {
+ if (w != null) {
ForkJoinTask<?> prevJoin = w.currentJoin;
- U.putOrderedObject(w, QCURRENTJOIN, task);
- CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
- (CountedCompleter<?>)task : null;
- for (;;) {
- if ((s = task.status) < 0)
- break;
- if (cc != null)
- helpComplete(w, cc, 0);
- else if (w.base == w.top || w.tryRemoveAndExec(task))
- helpStealer(w, task);
- if ((s = task.status) < 0)
- break;
- long ms, ns;
- if (deadline == 0L)
- ms = 0L;
- else if ((ns = deadline - System.nanoTime()) <= 0L)
- break;
- else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
- ms = 1L;
- if (tryCompensate(w)) {
- task.internalWait(ms);
- U.getAndAddLong(this, CTL, AC_UNIT);
+ if (task != null && (s = task.status) >= 0) {
+ w.currentJoin = task;
+ CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
+ (CountedCompleter<?>)task : null;
+ for (;;) {
+ if (cc != null)
+ helpComplete(w, cc, 0);
+ else
+ helpStealer(w, task);
+ if ((s = task.status) < 0)
+ break;
+ long ms, ns;
+ if (deadline == 0L)
+ ms = 0L;
+ else if ((ns = deadline - System.nanoTime()) <= 0L)
+ break;
+ else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
+ ms = 1L;
+ if (tryCompensate(w)) {
+ task.internalWait(ms);
+ U.getAndAddLong(this, CTL, AC_UNIT);
+ }
+ if ((s = task.status) < 0)
+ break;
}
+ w.currentJoin = prevJoin;
}
- U.putOrderedObject(w, QCURRENTJOIN, prevJoin);
}
return s;
}
@@ -2077,10 +2258,11 @@
* caller if, by the time it tries to use the queue, it is empty.
*/
private WorkQueue findNonEmptyStealQueue() {
- WorkQueue[] ws; int m; // one-shot version of scan loop
+ WorkQueue[] ws; int wl; // one-shot version of scan loop
int r = ThreadLocalRandom.nextSecondarySeed();
- if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) {
- for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) {
+ if ((ws = workQueues) != null && (wl = ws.length) > 0) {
+ int m = wl - 1, origin = r & m;
+ for (int k = origin, oldSum = 0, checkSum = 0;;) {
WorkQueue q; int b;
if ((q = ws[k]) != null) {
if ((b = q.base) - q.top < 0)
@@ -2105,25 +2287,27 @@
*/
final void helpQuiescePool(WorkQueue w) {
ForkJoinTask<?> ps = w.currentSteal; // save context
+ int wc = w.config;
for (boolean active = true;;) {
- long c; WorkQueue q; ForkJoinTask<?> t; int b;
- w.execLocalTasks(); // run locals before each scan
- if ((q = findNonEmptyStealQueue()) != null) {
+ long c; WorkQueue q; ForkJoinTask<?> t;
+ if (wc >= 0 && (t = w.pop()) != null) { // run locals if LIFO
+ (w.currentSteal = t).doExec();
+ w.currentSteal = ps;
+ }
+ else if ((q = findNonEmptyStealQueue()) != null) {
if (!active) { // re-establish active count
active = true;
U.getAndAddLong(this, CTL, AC_UNIT);
}
- if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) {
- U.putOrderedObject(w, QCURRENTSTEAL, t);
- t.doExec();
+ if ((t = q.pollAt(q.base)) != null) {
+ (w.currentSteal = t).doExec();
+ w.currentSteal = ps;
if (++w.nsteals < 0)
w.transferStealCount(this);
}
}
else if (active) { // decrement active count without queuing
long nc = (AC_MASK & ((c = ctl) - AC_UNIT)) | (~AC_MASK & c);
- if ((int)(nc >> AC_SHIFT) + (config & SMASK) <= 0)
- break; // bypass decrement-then-increment
if (U.compareAndSwapLong(this, CTL, c, nc))
active = false;
}
@@ -2131,7 +2315,6 @@
U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
break;
}
- U.putOrderedObject(w, QCURRENTSTEAL, ps);
}
/**
@@ -2141,12 +2324,12 @@
*/
final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
for (ForkJoinTask<?> t;;) {
- WorkQueue q; int b;
+ WorkQueue q;
if ((t = w.nextLocalTask()) != null)
return t;
if ((q = findNonEmptyStealQueue()) == null)
return null;
- if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
+ if ((t = q.pollAt(q.base)) != null)
return t;
}
}
@@ -2195,9 +2378,8 @@
*/
static int getSurplusQueuedTaskCount() {
Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
- if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
- int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).
- config & SMASK;
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
+ int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).config & SMASK;
int n = (q = wt.workQueue).top - q.base;
int a = (int)(pool.ctl >> AC_SHIFT) + p;
return n - (a > (p >>>= 1) ? 0 :
@@ -2216,212 +2398,165 @@
*
* @param now if true, unconditionally terminate, else only
* if no work and no active workers
- * @param enable if true, enable shutdown when next possible
- * @return true if now terminating or terminated
+ * @param enable if true, terminate when next possible
+ * @return -1: terminating/terminated, 0: retry if internal caller, else 1
*/
- private boolean tryTerminate(boolean now, boolean enable) {
- int rs;
- if (this == common) // cannot shut down
- return false;
- if ((rs = runState) >= 0) {
- if (!enable)
- return false;
- rs = lockRunState(); // enter SHUTDOWN phase
- unlockRunState(rs, (rs & ~RSLOCK) | SHUTDOWN);
+ private int tryTerminate(boolean now, boolean enable) {
+ int rs; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
+
+ while ((rs = runState) >= 0) {
+ if (!enable || this == common) // cannot shutdown
+ return 1;
+ else if (rs == 0)
+ tryInitialize(false); // ensure initialized
+ else
+ U.compareAndSwapInt(this, RUNSTATE, rs, rs | SHUTDOWN);
}
- if ((rs & STOP) == 0) {
+ if ((rs & STOP) == 0) { // try to initiate termination
if (!now) { // check quiescence
for (long oldSum = 0L;;) { // repeat until stable
- WorkQueue[] ws; WorkQueue w; int m, b; long c;
+ WorkQueue[] ws; WorkQueue w; int b;
long checkSum = ctl;
if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0)
- return false; // still active workers
- if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
- break; // check queues
- for (int i = 0; i <= m; ++i) {
- if ((w = ws[i]) != null) {
- if ((b = w.base) != w.top || w.scanState >= 0 ||
- w.currentSteal != null) {
- tryRelease(c = ctl, ws[m & (int)c], AC_UNIT);
- return false; // arrange for recheck
+ return 0; // still active workers
+ if ((ws = workQueues) != null) {
+ for (int i = 0; i < ws.length; ++i) {
+ if ((w = ws[i]) != null) {
+ checkSum += (b = w.base);
+ if (w.currentSteal != null || b != w.top)
+ return 0; // retry if internal caller
}
- checkSum += b;
- if ((i & 1) == 0)
- w.qlock = -1; // try to disable external
}
}
if (oldSum == (oldSum = checkSum))
break;
}
}
- if ((runState & STOP) == 0) {
- rs = lockRunState(); // enter STOP phase
- unlockRunState(rs, (rs & ~RSLOCK) | STOP);
- }
+ do {} while (!U.compareAndSwapInt(this, RUNSTATE,
+ rs = runState, rs | STOP));
}
- int pass = 0; // 3 passes to help terminate
- for (long oldSum = 0L;;) { // or until done or stable
- WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt; int m;
+ for (long oldSum = 0L;;) { // repeat until stable
+ WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt;
long checkSum = ctl;
- if ((short)(checkSum >>> TC_SHIFT) + (config & SMASK) <= 0 ||
- (ws = workQueues) == null || (m = ws.length - 1) <= 0) {
- if ((runState & TERMINATED) == 0) {
- rs = lockRunState(); // done
- unlockRunState(rs, (rs & ~RSLOCK) | TERMINATED);
- synchronized (this) { notifyAll(); } // for awaitTermination
- }
- break;
- }
- for (int i = 0; i <= m; ++i) {
- if ((w = ws[i]) != null) {
- checkSum += w.base;
- w.qlock = -1; // try to disable
- if (pass > 0) {
- w.cancelAll(); // clear queue
- if (pass > 1 && (wt = w.owner) != null) {
- if (!wt.isInterrupted()) {
- try { // unblock join
+ if ((ws = workQueues) != null) { // help terminate others
+ for (int i = 0; i < ws.length; ++i) {
+ if ((w = ws[i]) != null) {
+ w.cancelAll(); // clear queues
+ checkSum += w.base;
+ if (w.qlock >= 0) {
+ w.qlock = -1; // racy set OK
+ if ((wt = w.owner) != null) {
+ try { // unblock join or park
wt.interrupt();
} catch (Throwable ignore) {
}
}
- if (w.scanState < 0)
- U.unpark(wt); // wake up
}
}
}
}
- if (checkSum != oldSum) { // unstable
- oldSum = checkSum;
- pass = 0;
- }
- else if (pass > 3 && pass > m) // can't further help
+ if (oldSum == (oldSum = checkSum))
break;
- else if (++pass > 1) { // try to dequeue
- long c; int j = 0, sp; // bound attempts
- while (j++ <= m && (sp = (int)(c = ctl)) != 0)
- tryRelease(c, ws[sp & m], AC_UNIT);
+ }
+
+ if ((short)(ctl >>> TC_SHIFT) + (config & SMASK) <= 0) {
+ runState = (STARTED | SHUTDOWN | STOP | TERMINATED); // final write
+ synchronized (this) {
+ notifyAll(); // for awaitTermination
}
}
- return true;
+
+ return -1;
}
// External operations
/**
- * Full version of externalPush, handling uncommon cases, as well
- * as performing secondary initialization upon the first
- * submission of the first task to the pool. It also detects
+ * Constructs and tries to install a new external queue,
+ * failing if the workQueues array already has a queue at
+ * the given index.
+ *
+ * @param index the index of the new queue
+ */
+ private void tryCreateExternalQueue(int index) {
+ AuxState aux;
+ if ((aux = auxState) != null && index >= 0) {
+ WorkQueue q = new WorkQueue(this, null);
+ q.config = index;
+ q.scanState = ~UNSIGNALLED;
+ q.qlock = 1; // lock queue
+ boolean installed = false;
+ aux.lock();
+ try { // lock pool to install
+ WorkQueue[] ws;
+ if ((ws = workQueues) != null && index < ws.length &&
+ ws[index] == null) {
+ ws[index] = q; // else throw away
+ installed = true;
+ }
+ } finally {
+ aux.unlock();
+ }
+ if (installed) {
+ try {
+ q.growArray();
+ } finally {
+ q.qlock = 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the given task to a submission queue at submitter's
+ * current queue. Also performs secondary initialization upon the
+ * first submission of the first task to the pool, and detects
* first submission by an external thread and creates a new shared
* queue if the one at index if empty or contended.
*
* @param task the task. Caller must ensure non-null.
*/
- private void externalSubmit(ForkJoinTask<?> task) {
- int r; // initialize caller's probe
+ final void externalPush(ForkJoinTask<?> task) {
+ int r; // initialize caller's probe
if ((r = ThreadLocalRandom.getProbe()) == 0) {
ThreadLocalRandom.localInit();
r = ThreadLocalRandom.getProbe();
}
for (;;) {
- WorkQueue[] ws; WorkQueue q; int rs, m, k;
- boolean move = false;
- if ((rs = runState) < 0) {
- tryTerminate(false, false); // help terminate
- throw new RejectedExecutionException();
- }
- else if ((rs & STARTED) == 0 || // initialize
- ((ws = workQueues) == null || (m = ws.length - 1) < 0)) {
- int ns = 0;
- rs = lockRunState();
- try {
- if ((rs & STARTED) == 0) {
- U.compareAndSwapObject(this, STEALCOUNTER, null,
- new AtomicLong());
- // create workQueues array with size a power of two
- int p = config & SMASK; // ensure at least 2 slots
- int n = (p > 1) ? p - 1 : 1;
- n |= n >>> 1; n |= n >>> 2; n |= n >>> 4;
- n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1;
- workQueues = new WorkQueue[n];
- ns = STARTED;
- }
- } finally {
- unlockRunState(rs, (rs & ~RSLOCK) | ns);
- }
+ WorkQueue q; int wl, k, stat;
+ int rs = runState;
+ WorkQueue[] ws = workQueues;
+ if (rs <= 0 || ws == null || (wl = ws.length) <= 0)
+ tryInitialize(true);
+ else if ((q = ws[k = (wl - 1) & r & SQMASK]) == null)
+ tryCreateExternalQueue(k);
+ else if ((stat = q.sharedPush(task)) < 0)
+ break;
+ else if (stat == 0) {
+ signalWork();
+ break;
}
- else if ((q = ws[k = r & m & SQMASK]) != null) {
- if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
- ForkJoinTask<?>[] a = q.array;
- int s = q.top;
- boolean submitted = false; // initial submission or resizing
- try { // locked version of push
- if ((a != null && a.length > s + 1 - q.base) ||
- (a = q.growArray()) != null) {
- int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
- U.putOrderedObject(a, j, task);
- U.putOrderedInt(q, QTOP, s + 1);
- submitted = true;
- }
- } finally {
- U.compareAndSwapInt(q, QLOCK, 1, 0);
- }
- if (submitted) {
- signalWork(ws, q);
- return;
- }
- }
- move = true; // move on failure
- }
- else if (((rs = runState) & RSLOCK) == 0) { // create new queue
- q = new WorkQueue(this, null);
- q.hint = r;
- q.config = k | SHARED_QUEUE;
- q.scanState = INACTIVE;
- rs = lockRunState(); // publish index
- if (rs > 0 && (ws = workQueues) != null &&
- k < ws.length && ws[k] == null)
- ws[k] = q; // else terminated
- unlockRunState(rs, rs & ~RSLOCK);
- }
- else
- move = true; // move if busy
- if (move)
+ else // move if busy
r = ThreadLocalRandom.advanceProbe(r);
}
}
/**
- * Tries to add the given task to a submission queue at
- * submitter's current queue. Only the (vastly) most common path
- * is directly handled in this method, while screening for need
- * for externalSubmit.
- *
- * @param task the task. Caller must ensure non-null.
+ * Pushes a possibly-external submission.
*/
- final void externalPush(ForkJoinTask<?> task) {
- WorkQueue[] ws; WorkQueue q; int m;
- int r = ThreadLocalRandom.getProbe();
- int rs = runState;
- if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
- (q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 &&
- U.compareAndSwapInt(q, QLOCK, 0, 1)) {
- ForkJoinTask<?>[] a; int am, n, s;
- if ((a = q.array) != null &&
- (am = a.length - 1) > (n = (s = q.top) - q.base)) {
- int j = ((am & s) << ASHIFT) + ABASE;
- U.putOrderedObject(a, j, task);
- U.putOrderedInt(q, QTOP, s + 1);
- U.putIntVolatile(q, QLOCK, 0);
- if (n <= 1)
- signalWork(ws, q);
- return;
- }
- U.compareAndSwapInt(q, QLOCK, 1, 0);
- }
- externalSubmit(task);
+ private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
+ Thread t; ForkJoinWorkerThread w; WorkQueue q;
+ if (task == null)
+ throw new NullPointerException();
+ if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
+ (w = (ForkJoinWorkerThread)t).pool == this &&
+ (q = w.workQueue) != null)
+ q.push(task);
+ else
+ externalPush(task);
+ return task;
}
/**
@@ -2430,46 +2565,32 @@
static WorkQueue commonSubmitterQueue() {
ForkJoinPool p = common;
int r = ThreadLocalRandom.getProbe();
- WorkQueue[] ws; int m;
+ WorkQueue[] ws; int wl;
return (p != null && (ws = p.workQueues) != null &&
- (m = ws.length - 1) >= 0) ?
- ws[m & r & SQMASK] : null;
+ (wl = ws.length) > 0) ?
+ ws[(wl - 1) & r & SQMASK] : null;
}
/**
- * Performs tryUnpush for an external submitter: Finds queue,
- * locks if apparently non-empty, validates upon locking, and
- * adjusts top. Each check can fail but rarely does.
+ * Performs tryUnpush for an external submitter.
*/
final boolean tryExternalUnpush(ForkJoinTask<?> task) {
- WorkQueue[] ws; WorkQueue w; ForkJoinTask<?>[] a; int m, s;
int r = ThreadLocalRandom.getProbe();
- if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 &&
- (w = ws[m & r & SQMASK]) != null &&
- (a = w.array) != null && (s = w.top) != w.base) {
- long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
- if (U.compareAndSwapInt(w, QLOCK, 0, 1)) {
- if (w.top == s && w.array == a &&
- U.getObject(a, j) == task &&
- U.compareAndSwapObject(a, j, task, null)) {
- U.putOrderedInt(w, QTOP, s - 1);
- U.putOrderedInt(w, QLOCK, 0);
- return true;
- }
- U.compareAndSwapInt(w, QLOCK, 1, 0);
- }
- }
- return false;
+ WorkQueue[] ws; WorkQueue w; int wl;
+ return ((ws = workQueues) != null &&
+ (wl = ws.length) > 0 &&
+ (w = ws[(wl - 1) & r & SQMASK]) != null &&
+ w.trySharedUnpush(task));
}
/**
* Performs helpComplete for an external submitter.
*/
final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
- WorkQueue[] ws; int n;
+ WorkQueue[] ws; int wl;
int r = ThreadLocalRandom.getProbe();
- return ((ws = workQueues) == null || (n = ws.length) == 0) ? 0 :
- helpComplete(ws[(n - 1) & r & SQMASK], task, maxTasks);
+ return ((ws = workQueues) != null && (wl = ws.length) > 0) ?
+ helpComplete(ws[(wl - 1) & r & SQMASK], task, maxTasks) : 0;
}
// Exported methods
@@ -2617,7 +2738,7 @@
public <T> T invoke(ForkJoinTask<T> task) {
if (task == null)
throw new NullPointerException();
- externalPush(task);
+ externalSubmit(task);
return task.join();
}
@@ -2630,9 +2751,7 @@
* scheduled for execution
*/
public void execute(ForkJoinTask<?> task) {
- if (task == null)
- throw new NullPointerException();
- externalPush(task);
+ externalSubmit(task);
}
// AbstractExecutorService methods
@@ -2650,7 +2769,7 @@
job = (ForkJoinTask<?>) task;
else
job = new ForkJoinTask.RunnableExecuteAction(task);
- externalPush(job);
+ externalSubmit(job);
}
/**
@@ -2664,10 +2783,7 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
- if (task == null)
- throw new NullPointerException();
- externalPush(task);
- return task;
+ return externalSubmit(task);
}
/**
@@ -2676,9 +2792,7 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(Callable<T> task) {
- ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
- externalPush(job);
- return job;
+ return externalSubmit(new ForkJoinTask.AdaptedCallable<T>(task));
}
/**
@@ -2687,9 +2801,7 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(Runnable task, T result) {
- ForkJoinTask<T> job = new ForkJoinTask.AdaptedRunnable<T>(task, result);
- externalPush(job);
- return job;
+ return externalSubmit(new ForkJoinTask.AdaptedRunnable<T>(task, result));
}
/**
@@ -2705,8 +2817,7 @@
job = (ForkJoinTask<?>) task;
else
job = new ForkJoinTask.AdaptedRunnableAction(task);
- externalPush(job);
- return job;
+ return externalSubmit(job);
}
/**
@@ -2719,21 +2830,19 @@
// invocation of multiple tasks is at least as efficient.
ArrayList<Future<T>> futures = new ArrayList<>(tasks.size());
- boolean done = false;
try {
for (Callable<T> t : tasks) {
ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t);
futures.add(f);
- externalPush(f);
+ externalSubmit(f);
}
for (int i = 0, size = futures.size(); i < size; i++)
((ForkJoinTask<?>)futures.get(i)).quietlyJoin();
- done = true;
return futures;
- } finally {
- if (!done)
- for (int i = 0, size = futures.size(); i < size; i++)
- futures.get(i).cancel(false);
+ } catch (Throwable t) {
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(false);
+ throw t;
}
}
@@ -2773,7 +2882,7 @@
* @since 1.8
*/
public static int getCommonPoolParallelism() {
- return commonParallelism;
+ return COMMON_PARALLELISM;
}
/**
@@ -2857,8 +2966,8 @@
* @return the number of steals
*/
public long getStealCount() {
- AtomicLong sc = stealCounter;
- long count = (sc == null) ? 0L : sc.get();
+ AuxState sc = auxState;
+ long count = (sc == null) ? 0L : sc.stealCount;
WorkQueue[] ws; WorkQueue w;
if ((ws = workQueues) != null) {
for (int i = 1; i < ws.length; i += 2) {
@@ -2935,10 +3044,11 @@
* @return the next submission, or {@code null} if none
*/
protected ForkJoinTask<?> pollSubmission() {
- WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
- if ((ws = workQueues) != null) {
- for (int i = 0; i < ws.length; i += 2) {
- if ((w = ws[i]) != null && (t = w.poll()) != null)
+ WorkQueue[] ws; int wl; WorkQueue w; ForkJoinTask<?> t;
+ int r = ThreadLocalRandom.nextSecondarySeed();
+ if ((ws = workQueues) != null && (wl = ws.length) > 0) {
+ for (int m = wl - 1, i = 0; i < wl; ++i) {
+ if ((w = ws[(i << 1) & m]) != null && (t = w.poll()) != null)
return t;
}
}
@@ -2988,8 +3098,8 @@
public String toString() {
// Use a single pass through workQueues to collect counts
long qt = 0L, qs = 0L; int rc = 0;
- AtomicLong sc = stealCounter;
- long st = (sc == null) ? 0L : sc.get();
+ AuxState sc = auxState;
+ long st = (sc == null) ? 0L : sc.stealCount;
long c = ctl;
WorkQueue[] ws; WorkQueue w;
if ((ws = workQueues) != null) {
@@ -3171,17 +3281,17 @@
}
long startTime = System.nanoTime();
WorkQueue[] ws;
- int r = 0, m;
+ int r = 0, wl;
boolean found = true;
while (!isQuiescent() && (ws = workQueues) != null &&
- (m = ws.length - 1) >= 0) {
+ (wl = ws.length) > 0) {
if (!found) {
if ((System.nanoTime() - startTime) > nanos)
return false;
Thread.yield(); // cannot block
}
found = false;
- for (int j = (m + 1) << 2; j >= 0; --j) {
+ for (int m = wl - 1, j = (m + 1) << 2; j >= 0; --j) {
ForkJoinTask<?> t; WorkQueue q; int b, k;
if ((k = r++ & m) <= m && k >= 0 && (q = ws[k]) != null &&
(b = q.base) - q.top < 0) {
@@ -3223,7 +3333,7 @@
*
* <p>For example, here is a ManagedBlocker based on a
* ReentrantLock:
- * <pre> {@code
+ * <pre> {@code
* class ManagedLocker implements ManagedBlocker {
* final ReentrantLock lock;
* boolean hasLock = false;
@@ -3240,7 +3350,7 @@
*
* <p>Here is a class that possibly blocks waiting for an
* item on a given queue:
- * <pre> {@code
+ * <pre> {@code
* class QueueTaker<E> implements ManagedBlocker {
* final BlockingQueue<E> queue;
* volatile E item = null;
@@ -3291,7 +3401,7 @@
*
* <p>If not running in a ForkJoinPool, this method is
* behaviorally equivalent to
- * <pre> {@code
+ * <pre> {@code
* while (!blocker.isReleasable())
* if (blocker.block())
* break;}</pre>
@@ -3342,58 +3452,40 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
- private static final int ABASE;
- private static final int ASHIFT;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long CTL;
private static final long RUNSTATE;
- private static final long STEALCOUNTER;
- private static final long PARKBLOCKER;
- private static final long QTOP;
- private static final long QLOCK;
- private static final long QSCANSTATE;
- private static final long QPARKER;
- private static final long QCURRENTSTEAL;
- private static final long QCURRENTJOIN;
+ private static final int ABASE;
+ private static final int ASHIFT;
static {
- // initialize field offsets for CAS etc
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ForkJoinPool.class;
CTL = U.objectFieldOffset
- (k.getDeclaredField("ctl"));
+ (ForkJoinPool.class.getDeclaredField("ctl"));
RUNSTATE = U.objectFieldOffset
- (k.getDeclaredField("runState"));
- STEALCOUNTER = U.objectFieldOffset
- (k.getDeclaredField("stealCounter"));
- Class<?> tk = Thread.class;
- PARKBLOCKER = U.objectFieldOffset
- (tk.getDeclaredField("parkBlocker"));
- Class<?> wk = WorkQueue.class;
- QTOP = U.objectFieldOffset
- (wk.getDeclaredField("top"));
- QLOCK = U.objectFieldOffset
- (wk.getDeclaredField("qlock"));
- QSCANSTATE = U.objectFieldOffset
- (wk.getDeclaredField("scanState"));
- QPARKER = U.objectFieldOffset
- (wk.getDeclaredField("parker"));
- QCURRENTSTEAL = U.objectFieldOffset
- (wk.getDeclaredField("currentSteal"));
- QCURRENTJOIN = U.objectFieldOffset
- (wk.getDeclaredField("currentJoin"));
- Class<?> ak = ForkJoinTask[].class;
- ABASE = U.arrayBaseOffset(ak);
- int scale = U.arrayIndexScale(ak);
+ (ForkJoinPool.class.getDeclaredField("runState"));
+ ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
+ int scale = U.arrayIndexScale(ForkJoinTask[].class);
if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
+ throw new Error("array index scale not a power of two");
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
- } catch (Exception e) {
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
- commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
+
+ int commonMaxSpares = DEFAULT_COMMON_MAX_SPARES;
+ try {
+ String p = System.getProperty
+ ("java.util.concurrent.ForkJoinPool.common.maximumSpares");
+ if (p != null)
+ commonMaxSpares = Integer.parseInt(p);
+ } catch (Exception ignore) {}
+ COMMON_MAX_SPARES = commonMaxSpares;
+
defaultForkJoinWorkerThreadFactory =
new DefaultForkJoinWorkerThreadFactory();
modifyThreadPermission = new RuntimePermission("modifyThread");
@@ -3401,15 +3493,16 @@
common = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<ForkJoinPool>() {
public ForkJoinPool run() { return makeCommonPool(); }});
- int par = common.config & SMASK; // report 1 even if threads disabled
- commonParallelism = par > 0 ? par : 1;
+
+ // report 1 even if threads disabled
+ COMMON_PARALLELISM = Math.max(common.config & SMASK, 1);
}
/**
* Creates and returns the common pool, respecting user settings
* specified via system properties.
*/
- private static ForkJoinPool makeCommonPool() {
+ static ForkJoinPool makeCommonPool() {
int parallelism = -1;
ForkJoinWorkerThreadFactory factory = null;
UncaughtExceptionHandler handler = null;
@@ -3420,8 +3513,6 @@
("java.util.concurrent.ForkJoinPool.common.threadFactory");
String hp = System.getProperty
("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
- String mp = System.getProperty
- ("java.util.concurrent.ForkJoinPool.common.maximumSpares");
if (pp != null)
parallelism = Integer.parseInt(pp);
if (fp != null)
@@ -3430,8 +3521,6 @@
if (hp != null)
handler = ((UncaughtExceptionHandler)ClassLoader.
getSystemClassLoader().loadClass(hp).newInstance());
- if (mp != null)
- commonMaxSpares = Integer.parseInt(mp);
} catch (Exception ignore) {
}
if (factory == null) {
@@ -3450,9 +3539,9 @@
}
/**
- * Factory for innocuous worker threads
+ * Factory for innocuous worker threads.
*/
- static final class InnocuousForkJoinWorkerThreadFactory
+ private static final class InnocuousForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
/**
@@ -3473,9 +3562,8 @@
}
public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
- return (ForkJoinWorkerThread.InnocuousForkJoinWorkerThread)
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
+ return java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<ForkJoinWorkerThread>() {
public ForkJoinWorkerThread run() {
return new ForkJoinWorkerThread.
InnocuousForkJoinWorkerThread(pool);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,21 +36,13 @@
package java.util.concurrent;
import java.io.Serializable;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.List;
import java.util.RandomAccess;
-import java.lang.ref.WeakReference;
-import java.lang.ref.ReferenceQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.RunnableFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
-import java.lang.reflect.Constructor;
/**
* Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -442,7 +434,8 @@
ExceptionNode next;
final long thrower; // use id not ref to avoid weak cycles
final int hashCode; // store task hashCode before weak ref disappears
- ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next) {
+ ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next,
+ ReferenceQueue<Object> exceptionTableRefQueue) {
super(task, exceptionTableRefQueue);
this.ex = ex;
this.next = next;
@@ -468,7 +461,8 @@
int i = h & (t.length - 1);
for (ExceptionNode e = t[i]; ; e = e.next) {
if (e == null) {
- t[i] = new ExceptionNode(this, ex, t[i]);
+ t[i] = new ExceptionNode(this, ex, t[i],
+ exceptionTableRefQueue);
break;
}
if (e.get() == this) // already present
@@ -561,8 +555,6 @@
* @return the exception, or null if none
*/
private Throwable getThrowableException() {
- if ((status & DONE_MASK) != EXCEPTIONAL)
- return null;
int h = System.identityHashCode(this);
ExceptionNode e;
final ReentrantLock lock = exceptionTableLock;
@@ -608,7 +600,7 @@
}
/**
- * Poll stale refs and remove them. Call only while holding lock.
+ * Polls stale refs and removes them. Call only while holding lock.
*/
private static void expungeStaleExceptions() {
for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
@@ -635,7 +627,7 @@
}
/**
- * If lock is available, poll stale refs and remove them.
+ * If lock is available, polls stale refs and removes them.
* Called from ForkJoinPool when pools become quiescent.
*/
static final void helpExpungeStaleExceptions() {
@@ -650,21 +642,23 @@
}
/**
- * A version of "sneaky throw" to relay exceptions
+ * A version of "sneaky throw" to relay exceptions.
*/
static void rethrow(Throwable ex) {
- if (ex != null)
- ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
+ ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
}
/**
* The sneaky part of sneaky throw, relying on generics
* limitations to evade compiler complaints about rethrowing
- * unchecked exceptions
+ * unchecked exceptions.
*/
@SuppressWarnings("unchecked") static <T extends Throwable>
- void uncheckedThrow(Throwable t) throws T {
- throw (T)t; // rely on vacuous cast
+ void uncheckedThrow(Throwable t) throws T {
+ if (t != null)
+ throw (T)t; // rely on vacuous cast
+ else
+ throw new Error("Unknown Exception");
}
/**
@@ -999,11 +993,10 @@
public final V get() throws InterruptedException, ExecutionException {
int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
doJoin() : externalInterruptibleAwaitDone();
- Throwable ex;
if ((s &= DONE_MASK) == CANCELLED)
throw new CancellationException();
- if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
- throw new ExecutionException(ex);
+ if (s == EXCEPTIONAL)
+ throw new ExecutionException(getThrowableException());
return getRawResult();
}
@@ -1058,13 +1051,11 @@
if (s >= 0)
s = status;
if ((s &= DONE_MASK) != NORMAL) {
- Throwable ex;
if (s == CANCELLED)
throw new CancellationException();
if (s != EXCEPTIONAL)
throw new TimeoutException();
- if ((ex = getThrowableException()) != null)
- throw new ExecutionException(ex);
+ throw new ExecutionException(getThrowableException());
}
return getRawResult();
}
@@ -1090,10 +1081,10 @@
/**
* Possibly executes tasks until the pool hosting the current task
- * {@link ForkJoinPool#isQuiescent is quiescent}. This method may
- * be of use in designs in which many tasks are forked, but none
- * are explicitly joined, instead executing them until all are
- * processed.
+ * {@linkplain ForkJoinPool#isQuiescent is quiescent}. This
+ * method may be of use in designs in which many tasks are forked,
+ * but none are explicitly joined, instead executing them until
+ * all are processed.
*/
public static void helpQuiesce() {
Thread t;
@@ -1129,10 +1120,12 @@
}
/**
- * Returns the pool hosting the current task execution, or null
- * if this task is executing outside of any ForkJoinPool.
+ * Returns the pool hosting the current thread, or {@code null}
+ * if the current thread is executing outside of any ForkJoinPool.
*
- * @see #inForkJoinPool
+ * <p>This method returns {@code null} if and only if {@link
+ * #inForkJoinPool} returns {@code false}.
+ *
* @return the pool, or {@code null} if none
*/
public static ForkJoinPool getPool() {
@@ -1299,6 +1292,23 @@
null;
}
+ /**
+ * If the current thread is operating in a ForkJoinPool,
+ * unschedules and returns, without executing, a task externally
+ * submitted to the pool, if one is available. Availability may be
+ * transient, so a {@code null} result does not necessarily imply
+ * quiescence of the pool. This method is designed primarily to
+ * support extensions, and is unlikely to be useful otherwise.
+ *
+ * @return a task, or {@code null} if none are available
+ * @since 1.9
+ */
+ protected static ForkJoinTask<?> pollSubmission() {
+ Thread t;
+ return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+ ((ForkJoinWorkerThread)t).pool.pollSubmission() : null;
+ }
+
// tag operations
/**
@@ -1312,16 +1322,16 @@
}
/**
- * Atomically sets the tag value for this task.
+ * Atomically sets the tag value for this task and returns the old value.
*
- * @param tag the tag value
+ * @param newValue the new tag value
* @return the previous value of the tag
* @since 1.8
*/
- public final short setForkJoinTaskTag(short tag) {
+ public final short setForkJoinTaskTag(short newValue) {
for (int s;;) {
if (U.compareAndSwapInt(this, STATUS, s = status,
- (s & ~SMASK) | (tag & SMASK)))
+ (s & ~SMASK) | (newValue & SMASK)))
return (short)s;
}
}
@@ -1334,24 +1344,24 @@
* before processing, otherwise exiting because the node has
* already been visited.
*
- * @param e the expected tag value
- * @param tag the new tag value
+ * @param expect the expected tag value
+ * @param update the new tag value
* @return {@code true} if successful; i.e., the current value was
- * equal to e and is now tag.
+ * equal to {@code expect} and was changed to {@code update}.
* @since 1.8
*/
- public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
+ public final boolean compareAndSetForkJoinTaskTag(short expect, short update) {
for (int s;;) {
- if ((short)(s = status) != e)
+ if ((short)(s = status) != expect)
return false;
if (U.compareAndSwapInt(this, STATUS, s,
- (s & ~SMASK) | (tag & SMASK)))
+ (s & ~SMASK) | (update & SMASK)))
return true;
}
}
/**
- * Adaptor for Runnables. This implements RunnableFuture
+ * Adapter for Runnables. This implements RunnableFuture
* to be compliant with AbstractExecutorService constraints
* when used in ForkJoinPool.
*/
@@ -1372,7 +1382,7 @@
}
/**
- * Adaptor for Runnables without results
+ * Adapter for Runnables without results.
*/
static final class AdaptedRunnableAction extends ForkJoinTask<Void>
implements RunnableFuture<Void> {
@@ -1389,7 +1399,7 @@
}
/**
- * Adaptor for Runnables in which failure forces worker exception
+ * Adapter for Runnables in which failure forces worker exception.
*/
static final class RunnableExecuteAction extends ForkJoinTask<Void> {
final Runnable runnable;
@@ -1407,7 +1417,7 @@
}
/**
- * Adaptor for Callables
+ * Adapter for Callables.
*/
static final class AdaptedCallable<T> extends ForkJoinTask<T>
implements RunnableFuture<T> {
@@ -1423,8 +1433,6 @@
try {
result = callable.call();
return true;
- } catch (Error err) {
- throw err;
} catch (RuntimeException rex) {
throw rex;
} catch (Exception ex) {
@@ -1509,7 +1517,7 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long STATUS;
static {
@@ -1517,11 +1525,9 @@
exceptionTableRefQueue = new ReferenceQueue<Object>();
exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> k = ForkJoinTask.class;
STATUS = U.objectFieldOffset
- (k.getDeclaredField("status"));
- } catch (Exception e) {
+ (ForkJoinTask.class.getDeclaredField("status"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Tue Oct 20 08:24:37 2015 -0700
@@ -87,7 +87,7 @@
}
/**
- * Version for InnocuousForkJoinWorkerThread
+ * Version for InnocuousForkJoinWorkerThread.
*/
ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
AccessControlContext acc) {
@@ -179,28 +179,25 @@
}
/**
- * Non-public hook method for InnocuousForkJoinWorkerThread
+ * Non-public hook method for InnocuousForkJoinWorkerThread.
*/
void afterTopLevelExec() {
}
// Set up to allow setting thread fields in constructor
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long THREADLOCALS;
private static final long INHERITABLETHREADLOCALS;
private static final long INHERITEDACCESSCONTROLCONTEXT;
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> tk = Thread.class;
THREADLOCALS = U.objectFieldOffset
- (tk.getDeclaredField("threadLocals"));
+ (Thread.class.getDeclaredField("threadLocals"));
INHERITABLETHREADLOCALS = U.objectFieldOffset
- (tk.getDeclaredField("inheritableThreadLocals"));
+ (Thread.class.getDeclaredField("inheritableThreadLocals"));
INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
- (tk.getDeclaredField("inheritedAccessControlContext"));
-
- } catch (Exception e) {
+ (Thread.class.getDeclaredField("inheritedAccessControlContext"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -252,10 +249,10 @@
private static ThreadGroup createThreadGroup() {
try {
sun.misc.Unsafe u = sun.misc.Unsafe.getUnsafe();
- Class<?> tk = Thread.class;
- Class<?> gk = ThreadGroup.class;
- long tg = u.objectFieldOffset(tk.getDeclaredField("group"));
- long gp = u.objectFieldOffset(gk.getDeclaredField("parent"));
+ long tg = u.objectFieldOffset
+ (Thread.class.getDeclaredField("group"));
+ long gp = u.objectFieldOffset
+ (ThreadGroup.class.getDeclaredField("parent"));
ThreadGroup group = (ThreadGroup)
u.getObject(Thread.currentThread(), tg);
while (group != null) {
@@ -265,7 +262,7 @@
"InnocuousForkJoinWorkerThreadGroup");
group = parent;
}
- } catch (Exception e) {
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
// fall through if null as cannot-happen safeguard
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Future.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Future.java Tue Oct 20 08:24:37 2015 -0700
@@ -53,6 +53,7 @@
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
* made-up.)
+ *
* <pre> {@code
* interface ArchiveSearcher { String search(String target); }
* class App {
@@ -75,9 +76,9 @@
* The {@link FutureTask} class is an implementation of {@code Future} that
* implements {@code Runnable}, and so may be executed by an {@code Executor}.
* For example, the above construction with {@code submit} could be replaced by:
- * <pre> {@code
+ * <pre> {@code
* FutureTask<String> future =
- * new FutureTask<String>(new Callable<String>() {
+ * new FutureTask<>(new Callable<String>() {
* public String call() {
* return searcher.search(target);
* }});
--- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+
import java.util.concurrent.locks.LockSupport;
/**
@@ -395,7 +396,7 @@
throws InterruptedException {
// The code below is very delicate, to achieve these goals:
// - call nanoTime exactly once for each call to park
- // - if nanos <= 0, return promptly without allocation or nanoTime
+ // - if nanos <= 0L, return promptly without allocation or nanoTime
// - if nanos == Long.MIN_VALUE, don't underflow
// - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
// and we suffer a spurious wakeup, we will do no worse than
@@ -404,19 +405,20 @@
WaitNode q = null;
boolean queued = false;
for (;;) {
- if (Thread.interrupted()) {
- removeWaiter(q);
- throw new InterruptedException();
- }
-
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
- else if (s == COMPLETING) // cannot time out yet
+ else if (s == COMPLETING)
+ // We may have already promised (via isDone) that we are done
+ // so never return empty-handed or throw InterruptedException
Thread.yield();
+ else if (Thread.interrupted()) {
+ removeWaiter(q);
+ throw new InterruptedException();
+ }
else if (q == null) {
if (timed && nanos <= 0L)
return s;
@@ -440,7 +442,9 @@
}
parkNanos = nanos - elapsed;
}
- LockSupport.parkNanos(this, parkNanos);
+ // nanoTime may be slow; recheck before parking
+ if (state < COMPLETING)
+ LockSupport.parkNanos(this, parkNanos);
}
else
LockSupport.park(this);
@@ -480,20 +484,25 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long STATE;
private static final long RUNNER;
private static final long WAITERS;
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> k = FutureTask.class;
- STATE = U.objectFieldOffset(k.getDeclaredField("state"));
- RUNNER = U.objectFieldOffset(k.getDeclaredField("runner"));
- WAITERS = U.objectFieldOffset(k.getDeclaredField("waiters"));
- } catch (Exception e) {
+ STATE = U.objectFieldOffset
+ (FutureTask.class.getDeclaredField("state"));
+ RUNNER = U.objectFieldOffset
+ (FutureTask.class.getDeclaredField("runner"));
+ WAITERS = U.objectFieldOffset
+ (FutureTask.class.getDeclaredField("waiters"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Helpers.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,118 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+import java.util.Collection;
+
+/** Shared implementation code for java.util.concurrent. */
+class Helpers {
+ private Helpers() {} // non-instantiable
+
+ /**
+ * An implementation of Collection.toString() suitable for classes
+ * with locks. Instead of holding a lock for the entire duration of
+ * toString(), or acquiring a lock for each call to Iterator.next(),
+ * we hold the lock only during the call to toArray() (less
+ * disruptive to other threads accessing the collection) and follows
+ * the maxim "Never call foreign code while holding a lock".
+ */
+ static String collectionToString(Collection<?> c) {
+ final Object[] a = c.toArray();
+ final int size = a.length;
+ if (size == 0)
+ return "[]";
+ int charLength = 0;
+
+ // Replace every array element with its string representation
+ for (int i = 0; i < size; i++) {
+ Object e = a[i];
+ // Extreme compatibility with AbstractCollection.toString()
+ String s = (e == c) ? "(this Collection)" : objectToString(e);
+ a[i] = s;
+ charLength += s.length();
+ }
+
+ return toString(a, size, charLength);
+ }
+
+ /**
+ * Like Arrays.toString(), but caller guarantees that size > 0,
+ * each element with index 0 <= i < size is a non-null String,
+ * and charLength is the sum of the lengths of the input Strings.
+ */
+ static String toString(Object[] a, int size, int charLength) {
+ // assert a != null;
+ // assert size > 0;
+
+ // Copy each string into a perfectly sized char[]
+ // Length of [ , , , ] == 2 * size
+ final char[] chars = new char[charLength + 2 * size];
+ chars[0] = '[';
+ int j = 1;
+ for (int i = 0; i < size; i++) {
+ if (i > 0) {
+ chars[j++] = ',';
+ chars[j++] = ' ';
+ }
+ String s = (String) a[i];
+ int len = s.length();
+ s.getChars(0, len, chars, j);
+ j += len;
+ }
+ chars[j] = ']';
+ // assert j == chars.length - 1;
+ return new String(chars);
+ }
+
+ /** Optimized form of: key + "=" + val */
+ static String mapEntryToString(Object key, Object val) {
+ final String k, v;
+ final int klen, vlen;
+ final char[] chars =
+ new char[(klen = (k = objectToString(key)).length()) +
+ (vlen = (v = objectToString(val)).length()) + 1];
+ k.getChars(0, klen, chars, 0);
+ chars[klen] = '=';
+ v.getChars(0, vlen, chars, klen + 1);
+ return new String(chars);
+ }
+
+ private static String objectToString(Object x) {
+ // Extreme compatibility with StringBuilder.append(null)
+ String s;
+ return (x == null || (s = x.toString()) == null) ? "null" : s;
+ }
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java Tue Oct 20 08:24:37 2015 -0700
@@ -39,10 +39,10 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.Spliterator;
-import java.util.Spliterators;
import java.util.function.Consumer;
/**
@@ -72,7 +72,7 @@
*
* @since 1.6
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this deque
*/
public class LinkedBlockingDeque<E>
extends AbstractQueue<E>
@@ -412,7 +412,7 @@
lock.lockInterruptibly();
try {
while (!linkFirst(node)) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return false;
nanos = notFull.awaitNanos(nanos);
}
@@ -435,7 +435,7 @@
lock.lockInterruptibly();
try {
while (!linkLast(node)) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return false;
nanos = notFull.awaitNanos(nanos);
}
@@ -517,7 +517,7 @@
try {
E x;
while ( (x = unlinkFirst()) == null) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
@@ -535,7 +535,7 @@
try {
E x;
while ( (x = unlinkLast()) == null) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
@@ -924,7 +924,7 @@
* The following code can be used to dump the deque into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -959,26 +959,7 @@
}
public String toString() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- Node<E> p = first;
- if (p == null)
- return "[]";
-
- StringBuilder sb = new StringBuilder();
- sb.append('[');
- for (;;) {
- E e = p.item;
- sb.append(e == this ? "(this Collection)" : e);
- p = p.next;
- if (p == null)
- return sb.append(']').toString();
- sb.append(',').append(' ');
- }
- } finally {
- lock.unlock();
- }
+ return Helpers.collectionToString(this);
}
/**
@@ -1032,11 +1013,11 @@
}
/**
- * Base class for Iterators for LinkedBlockingDeque
+ * Base class for LinkedBlockingDeque iterators.
*/
private abstract class AbstractItr implements Iterator<E> {
/**
- * The next node to return in next()
+ * The next node to return in next().
*/
Node<E> next;
@@ -1192,8 +1173,9 @@
if (i > 0) {
batch = i;
return Spliterators.spliterator
- (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT);
+ (a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
}
return null;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedBlockingQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,15 +35,15 @@
package java.util.concurrent;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
/**
@@ -75,7 +75,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
@@ -117,7 +117,7 @@
*/
/**
- * Linked list node class
+ * Linked list node class.
*/
static class Node<E> {
E item;
@@ -380,7 +380,7 @@
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return false;
nanos = notFull.awaitNanos(nanos);
}
@@ -462,7 +462,7 @@
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
@@ -507,11 +507,7 @@
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
- Node<E> first = head.next;
- if (first == null)
- return null;
- else
- return first.item;
+ return (count.get() > 0) ? head.next.item : null;
} finally {
takeLock.unlock();
}
@@ -630,7 +626,7 @@
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -665,25 +661,7 @@
}
public String toString() {
- fullyLock();
- try {
- Node<E> p = head.next;
- if (p == null)
- return "[]";
-
- StringBuilder sb = new StringBuilder();
- sb.append('[');
- for (;;) {
- E e = p.item;
- sb.append(e == this ? "(this Collection)" : e);
- p = p.next;
- if (p == null)
- return sb.append(']').toString();
- sb.append(',').append(' ');
- }
- } finally {
- fullyUnlock();
- }
+ return Helpers.collectionToString(this);
}
/**
@@ -801,34 +779,26 @@
return current != null;
}
- /**
- * Returns the next live successor of p, or null if no such.
- *
- * Unlike other traversal methods, iterators need to handle both:
- * - dequeued nodes (p.next == p)
- * - (possibly multiple) interior removed nodes (p.item == null)
- */
- private Node<E> nextNode(Node<E> p) {
- for (;;) {
- Node<E> s = p.next;
- if (s == p)
- return head.next;
- if (s == null || s.item != null)
- return s;
- p = s;
- }
- }
-
public E next() {
fullyLock();
try {
if (current == null)
throw new NoSuchElementException();
- E x = currentElement;
lastRet = current;
- current = nextNode(current);
- currentElement = (current == null) ? null : current.item;
- return x;
+ E item = null;
+ // Unlike other traversal methods, iterators must handle both:
+ // - dequeued nodes (p.next == p)
+ // - (possibly multiple) interior removed nodes (p.item == null)
+ for (Node<E> p = current, q;; p = q) {
+ if ((q = p.next) == p)
+ q = head.next;
+ if (q == null || (item = q.item) != null) {
+ current = q;
+ E x = currentElement;
+ currentElement = item;
+ return x;
+ }
+ }
} finally {
fullyUnlock();
}
@@ -901,8 +871,9 @@
if (i > 0) {
batch = i;
return Spliterators.spliterator
- (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT);
+ (a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
}
return null;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,14 +36,14 @@
package java.util.concurrent;
import java.util.AbstractQueue;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.LockSupport;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.locks.LockSupport;
import java.util.function.Consumer;
/**
@@ -83,7 +83,7 @@
*
* @since 1.7
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class LinkedTransferQueue<E> extends AbstractQueue<E>
implements TransferQueue<E>, java.io.Serializable {
@@ -108,7 +108,7 @@
*
* A FIFO dual queue may be implemented using a variation of the
* Michael & Scott (M&S) lock-free queue algorithm
- * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf).
+ * (http://www.cs.rochester.edu/~scott/papers/1996_PODC_queues.pdf).
* It maintains two pointer fields, "head", pointing to a
* (matched) node that in turn points to the first actual
* (unmatched) queue node (or null if empty); and "tail" that
@@ -215,7 +215,7 @@
* of costly-to-reclaim garbage caused by the sequential "next"
* links of nodes starting at old forgotten head nodes: As first
* described in detail by Boehm
- * (http://portal.acm.org/citation.cfm?doid=503272.503282) if a GC
+ * (http://portal.acm.org/citation.cfm?doid=503272.503282), if a GC
* delays noticing that any arbitrarily old node has become
* garbage, all newer dead nodes will also be unreclaimed.
* (Similar issues arise in non-GC environments.) To cope with
@@ -456,12 +456,12 @@
// CAS methods for fields
final boolean casNext(Node cmp, Node val) {
- return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+ return U.compareAndSwapObject(this, NEXT, cmp, val);
}
final boolean casItem(Object cmp, Object val) {
// assert cmp == null || cmp.getClass() != Node.class;
- return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+ return U.compareAndSwapObject(this, ITEM, cmp, val);
}
/**
@@ -469,7 +469,7 @@
* only be seen after publication via casNext.
*/
Node(Object item, boolean isData) {
- UNSAFE.putObject(this, itemOffset, item); // relaxed write
+ U.putObject(this, ITEM, item); // relaxed write
this.isData = isData;
}
@@ -478,7 +478,7 @@
* only after CASing head field, so uses relaxed write.
*/
final void forgetNext() {
- UNSAFE.putObject(this, nextOffset, this);
+ U.putObject(this, NEXT, this);
}
/**
@@ -491,8 +491,8 @@
* else we don't care).
*/
final void forgetContents() {
- UNSAFE.putObject(this, itemOffset, this);
- UNSAFE.putObject(this, waiterOffset, null);
+ U.putObject(this, ITEM, this);
+ U.putObject(this, WAITER, null);
}
/**
@@ -538,21 +538,19 @@
private static final long serialVersionUID = -3375979862319811754L;
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long itemOffset;
- private static final long nextOffset;
- private static final long waiterOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long ITEM;
+ private static final long NEXT;
+ private static final long WAITER;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = Node.class;
- itemOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("item"));
- nextOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("next"));
- waiterOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("waiter"));
- } catch (Exception e) {
+ ITEM = U.objectFieldOffset
+ (Node.class.getDeclaredField("item"));
+ NEXT = U.objectFieldOffset
+ (Node.class.getDeclaredField("next"));
+ WAITER = U.objectFieldOffset
+ (Node.class.getDeclaredField("waiter"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -569,15 +567,15 @@
// CAS methods for fields
private boolean casTail(Node cmp, Node val) {
- return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+ return U.compareAndSwapObject(this, TAIL, cmp, val);
}
private boolean casHead(Node cmp, Node val) {
- return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+ return U.compareAndSwapObject(this, HEAD, cmp, val);
}
private boolean casSweepVotes(int cmp, int val) {
- return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
+ return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val);
}
/*
@@ -588,12 +586,6 @@
private static final int SYNC = 2; // for transfer, take
private static final int TIMED = 3; // for timed poll, tryTransfer
- @SuppressWarnings("unchecked")
- static <E> E cast(Object item) {
- // assert item == null || item.getClass() != Node.class;
- return (E) item;
- }
-
/**
* Implements all queuing methods. See above for explanation.
*
@@ -630,7 +622,8 @@
break; // unless slack < 2
}
LockSupport.unpark(p.waiter);
- return LinkedTransferQueue.<E>cast(item);
+ @SuppressWarnings("unchecked") E itemE = (E) item;
+ return itemE;
}
}
Node n = p.next;
@@ -708,15 +701,15 @@
if (item != e) { // matched
// assert item != s;
s.forgetContents(); // avoid garbage
- return LinkedTransferQueue.<E>cast(item);
+ @SuppressWarnings("unchecked") E itemE = (E) item;
+ return itemE;
}
- if ((w.isInterrupted() || (timed && nanos <= 0)) &&
- s.casItem(e, s)) { // cancel
- unsplice(pred, s);
- return e;
+ else if (w.isInterrupted() || (timed && nanos <= 0L)) {
+ unsplice(pred, s); // try to unlink and cancel
+ if (s.casItem(e, s)) // return normally if lost CAS
+ return e;
}
-
- if (spins < 0) { // establish spins at/near front
+ else if (spins < 0) { // establish spins at/near front
if ((spins = spinsFor(pred, s.isData)) > 0)
randomYields = ThreadLocalRandom.current();
}
@@ -768,52 +761,25 @@
}
/**
- * Returns the first unmatched node of the given mode, or null if
- * none. Used by methods isEmpty, hasWaitingConsumer.
- */
- private Node firstOfMode(boolean isData) {
- for (Node p = head; p != null; p = succ(p)) {
- if (!p.isMatched())
- return (p.isData == isData) ? p : null;
- }
- return null;
- }
-
- /**
- * Version of firstOfMode used by Spliterator. Callers must
- * recheck if the returned node's item field is null or
- * self-linked before using.
+ * Returns the first unmatched data node, or null if none.
+ * Callers must recheck if the returned node's item field is null
+ * or self-linked before using.
*/
final Node firstDataNode() {
- for (Node p = head; p != null;) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p)
- return p;
+ restartFromHead: for (;;) {
+ for (Node p = head; p != null;) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p)
+ return p;
+ }
+ else if (item == null)
+ break;
+ if (p == (p = p.next))
+ continue restartFromHead;
}
- else if (item == null)
- break;
- if (p == (p = p.next))
- p = head;
+ return null;
}
- return null;
- }
-
- /**
- * Returns the item in the first unmatched node with isData; or
- * null if none. Used by peek.
- */
- private E firstDataItem() {
- for (Node p = head; p != null; p = succ(p)) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p)
- return LinkedTransferQueue.<E>cast(item);
- }
- else if (item == null)
- return null;
- }
- return null;
}
/**
@@ -821,23 +787,140 @@
* Used by methods size and getWaitingConsumerCount.
*/
private int countOfMode(boolean data) {
- int count = 0;
- for (Node p = head; p != null; ) {
- if (!p.isMatched()) {
- if (p.isData != data)
- return 0;
- if (++count == Integer.MAX_VALUE) // saturated
+ restartFromHead: for (;;) {
+ int count = 0;
+ for (Node p = head; p != null;) {
+ if (!p.isMatched()) {
+ if (p.isData != data)
+ return 0;
+ if (++count == Integer.MAX_VALUE)
+ break; // @see Collection.size()
+ }
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ return count;
+ }
+ }
+
+ public String toString() {
+ String[] a = null;
+ restartFromHead: for (;;) {
+ int charLength = 0;
+ int size = 0;
+ for (Node p = head; p != null;) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p) {
+ if (a == null)
+ a = new String[4];
+ else if (size == a.length)
+ a = Arrays.copyOf(a, 2 * size);
+ String s = item.toString();
+ a[size++] = s;
+ charLength += s.length();
+ }
+ } else if (item == null)
break;
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+
+ if (size == 0)
+ return "[]";
+
+ return Helpers.toString(a, size, charLength);
+ }
+ }
+
+ private Object[] toArrayInternal(Object[] a) {
+ Object[] x = a;
+ restartFromHead: for (;;) {
+ int size = 0;
+ for (Node p = head; p != null;) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p) {
+ if (x == null)
+ x = new Object[4];
+ else if (size == x.length)
+ x = Arrays.copyOf(x, 2 * (size + 4));
+ x[size++] = item;
+ }
+ } else if (item == null)
+ break;
+ if (p == (p = p.next))
+ continue restartFromHead;
}
- Node n = p.next;
- if (n != p)
- p = n;
- else {
- count = 0;
- p = head;
+ if (x == null)
+ return new Object[0];
+ else if (a != null && size <= a.length) {
+ if (a != x)
+ System.arraycopy(x, 0, a, 0, size);
+ if (size < a.length)
+ a[size] = null;
+ return a;
}
+ return (size == x.length) ? x : Arrays.copyOf(x, size);
}
- return count;
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this queue
+ */
+ public Object[] toArray() {
+ return toArrayInternal(null);
+ }
+
+ /**
+ * Returns an array containing all of the elements in this queue, in
+ * proper sequence; the runtime type of the returned array is that of
+ * the specified array. If the queue fits in the specified array, it
+ * is returned therein. Otherwise, a new array is allocated with the
+ * runtime type of the specified array and the size of this queue.
+ *
+ * <p>If this queue fits in the specified array with room to spare
+ * (i.e., the array has more elements than this queue), the element in
+ * the array immediately following the end of the queue is set to
+ * {@code null}.
+ *
+ * <p>Like the {@link #toArray()} method, this method acts as bridge between
+ * array-based and collection-based APIs. Further, this method allows
+ * precise control over the runtime type of the output array, and may,
+ * under certain circumstances, be used to save allocation costs.
+ *
+ * <p>Suppose {@code x} is a queue known to contain only strings.
+ * The following code can be used to dump the queue into a newly
+ * allocated array of {@code String}:
+ *
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ *
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
+ *
+ * @param a the array into which the elements of the queue are to
+ * be stored, if it is big enough; otherwise, a new array of the
+ * same runtime type is allocated for this purpose
+ * @return an array containing all of the elements in this queue
+ * @throws ArrayStoreException if the runtime type of the specified array
+ * is not a supertype of the runtime type of every element in
+ * this queue
+ * @throws NullPointerException if the specified array is null
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T[] toArray(T[] a) {
+ if (a == null) throw new NullPointerException();
+ return (T[]) toArrayInternal(a);
}
final class Itr implements Iterator<E> {
@@ -886,7 +969,8 @@
Object item = s.item;
if (s.isData) {
if (item != null && item != s) {
- nextItem = LinkedTransferQueue.<E>cast(item);
+ @SuppressWarnings("unchecked") E itemE = (E) item;
+ nextItem = itemE;
nextNode = s;
return;
}
@@ -934,23 +1018,19 @@
}
/** A customized variant of Spliterators.IteratorSpliterator */
- static final class LTQSpliterator<E> implements Spliterator<E> {
+ final class LTQSpliterator<E> implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
- final LinkedTransferQueue<E> queue;
- Node current; // current node; null until initialized
+ Node current; // current node; null until initialized
int batch; // batch size for splits
boolean exhausted; // true when no more nodes
- LTQSpliterator(LinkedTransferQueue<E> queue) {
- this.queue = queue;
- }
+ LTQSpliterator() {}
public Spliterator<E> trySplit() {
Node p;
- final LinkedTransferQueue<E> q = this.queue;
int b = batch;
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
- ((p = current) != null || (p = q.firstDataNode()) != null) &&
+ ((p = current) != null || (p = firstDataNode()) != null) &&
p.next != null) {
Object[] a = new Object[n];
int i = 0;
@@ -959,15 +1039,16 @@
if (e != p && (a[i] = e) != null)
++i;
if (p == (p = p.next))
- p = q.firstDataNode();
+ p = firstDataNode();
} while (p != null && i < n && p.isData);
if ((current = p) == null)
exhausted = true;
if (i > 0) {
batch = i;
return Spliterators.spliterator
- (a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
- Spliterator.CONCURRENT);
+ (a, 0, i, (Spliterator.ORDERED |
+ Spliterator.NONNULL |
+ Spliterator.CONCURRENT));
}
}
return null;
@@ -977,16 +1058,15 @@
public void forEachRemaining(Consumer<? super E> action) {
Node p;
if (action == null) throw new NullPointerException();
- final LinkedTransferQueue<E> q = this.queue;
if (!exhausted &&
- ((p = current) != null || (p = q.firstDataNode()) != null)) {
+ ((p = current) != null || (p = firstDataNode()) != null)) {
exhausted = true;
do {
Object e = p.item;
if (e != null && e != p)
action.accept((E)e);
if (p == (p = p.next))
- p = q.firstDataNode();
+ p = firstDataNode();
} while (p != null && p.isData);
}
}
@@ -995,15 +1075,14 @@
public boolean tryAdvance(Consumer<? super E> action) {
Node p;
if (action == null) throw new NullPointerException();
- final LinkedTransferQueue<E> q = this.queue;
if (!exhausted &&
- ((p = current) != null || (p = q.firstDataNode()) != null)) {
+ ((p = current) != null || (p = firstDataNode()) != null)) {
Object e;
do {
if ((e = p.item) == p)
e = null;
if (p == (p = p.next))
- p = q.firstDataNode();
+ p = firstDataNode();
} while (e == null && p != null && p.isData);
if ((current = p) == null)
exhausted = true;
@@ -1040,7 +1119,7 @@
* @since 1.8
*/
public Spliterator<E> spliterator() {
- return new LTQSpliterator<E>(this);
+ return new LTQSpliterator<E>();
}
/* -------------- Removal methods -------------- */
@@ -1054,7 +1133,7 @@
* @param s the node to be unspliced
*/
final void unsplice(Node pred, Node s) {
- s.forgetContents(); // forget unneeded fields
+ s.waiter = null; // disable signals
/*
* See above for rationale. Briefly: if pred still points to
* s, try to unlink s. If s cannot be unlinked, because it is
@@ -1332,7 +1411,22 @@
}
public E peek() {
- return firstDataItem();
+ restartFromHead: for (;;) {
+ for (Node p = head; p != null;) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p) {
+ @SuppressWarnings("unchecked") E e = (E) item;
+ return e;
+ }
+ }
+ else if (item == null)
+ break;
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ return null;
+ }
}
/**
@@ -1341,15 +1435,24 @@
* @return {@code true} if this queue contains no elements
*/
public boolean isEmpty() {
- for (Node p = head; p != null; p = succ(p)) {
- if (!p.isMatched())
- return !p.isData;
- }
- return true;
+ return firstDataNode() == null;
}
public boolean hasWaitingConsumer() {
- return firstOfMode(false) != null;
+ restartFromHead: for (;;) {
+ for (Node p = head; p != null;) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p)
+ break;
+ }
+ else if (item == null)
+ return true;
+ if (p == (p = p.next))
+ continue restartFromHead;
+ }
+ return false;
+ }
}
/**
@@ -1396,15 +1499,16 @@
* @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
- if (o == null) return false;
- for (Node p = head; p != null; p = succ(p)) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p && o.equals(item))
- return true;
+ if (o != null) {
+ for (Node p = head; p != null; p = succ(p)) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p && o.equals(item))
+ return true;
+ }
+ else if (item == null)
+ break;
}
- else if (item == null)
- break;
}
return false;
}
@@ -1460,22 +1564,24 @@
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long headOffset;
- private static final long tailOffset;
- private static final long sweepVotesOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long HEAD;
+ private static final long TAIL;
+ private static final long SWEEPVOTES;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = LinkedTransferQueue.class;
- headOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("head"));
- tailOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("tail"));
- sweepVotesOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("sweepVotes"));
- } catch (Exception e) {
+ HEAD = U.objectFieldOffset
+ (LinkedTransferQueue.class.getDeclaredField("head"));
+ TAIL = U.objectFieldOffset
+ (LinkedTransferQueue.class.getDeclaredField("tail"));
+ SWEEPVOTES = U.objectFieldOffset
+ (LinkedTransferQueue.class.getDeclaredField("sweepVotes"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,8 +35,6 @@
package java.util.concurrent;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
@@ -73,7 +71,7 @@
*
* <ul>
*
- * <li> <b>Arrival.</b> Methods {@link #arrive} and
+ * <li><b>Arrival.</b> Methods {@link #arrive} and
* {@link #arriveAndDeregister} record arrival. These methods
* do not block, but return an associated <em>arrival phase
* number</em>; that is, the phase number of the phaser to which
@@ -86,7 +84,7 @@
* flexible than, providing a barrier action to a {@code
* CyclicBarrier}.
*
- * <li> <b>Waiting.</b> Method {@link #awaitAdvance} requires an
+ * <li><b>Waiting.</b> Method {@link #awaitAdvance} requires an
* argument indicating an arrival phase number, and returns when
* the phaser advances to (or is already at) a different phase.
* Unlike similar constructions using {@code CyclicBarrier},
@@ -97,9 +95,10 @@
* state of the phaser. If necessary, you can perform any
* associated recovery within handlers of those exceptions,
* often after invoking {@code forceTermination}. Phasers may
- * also be used by tasks executing in a {@link ForkJoinPool},
- * which will ensure sufficient parallelism to execute tasks
- * when others are blocked waiting for a phase to advance.
+ * also be used by tasks executing in a {@link ForkJoinPool}.
+ * Progress is ensured if the pool's parallelismLevel can
+ * accommodate the maximum number of simultaneously blocked
+ * parties.
*
* </ul>
*
@@ -155,7 +154,7 @@
* The typical idiom is for the method setting this up to first
* register, then start the actions, then deregister, as in:
*
- * <pre> {@code
+ * <pre> {@code
* void runTasks(List<Runnable> tasks) {
* final Phaser phaser = new Phaser(1); // "1" to register self
* // create and start threads
@@ -176,7 +175,7 @@
* <p>One way to cause a set of threads to repeatedly perform actions
* for a given number of iterations is to override {@code onAdvance}:
*
- * <pre> {@code
+ * <pre> {@code
* void startTasks(List<Runnable> tasks, final int iterations) {
* final Phaser phaser = new Phaser() {
* protected boolean onAdvance(int phase, int registeredParties) {
@@ -200,7 +199,7 @@
*
* If the main task must later await termination, it
* may re-register and then execute a similar loop:
- * <pre> {@code
+ * <pre> {@code
* // ...
* phaser.register();
* while (!phaser.isTerminated())
@@ -210,7 +209,7 @@
* in contexts where you are sure that the phase will never wrap around
* {@code Integer.MAX_VALUE}. For example:
*
- * <pre> {@code
+ * <pre> {@code
* void awaitPhase(Phaser phaser, int phase) {
* int p = phaser.register(); // assumes caller not already registered
* while (p < phase) {
@@ -230,7 +229,7 @@
* new Phaser())}, these tasks could then be started, for example by
* submitting to a pool:
*
- * <pre> {@code
+ * <pre> {@code
* void build(Task[] tasks, int lo, int hi, Phaser ph) {
* if (hi - lo > TASKS_PER_PHASER) {
* for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
@@ -331,7 +330,7 @@
}
/**
- * The parent of this phaser, or null if none
+ * The parent of this phaser, or null if none.
*/
private final Phaser parent;
@@ -389,7 +388,7 @@
int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
if (unarrived <= 0)
throw new IllegalStateException(badArrive(s));
- if (UNSAFE.compareAndSwapLong(this, stateOffset, s, s-=adjust)) {
+ if (U.compareAndSwapLong(this, STATE, s, s-=adjust)) {
if (unarrived == 1) {
long n = s & PARTIES_MASK; // base of next state
int nextUnarrived = (int)n >>> PARTIES_SHIFT;
@@ -402,13 +401,12 @@
n |= nextUnarrived;
int nextPhase = (phase + 1) & MAX_PHASE;
n |= (long)nextPhase << PHASE_SHIFT;
- UNSAFE.compareAndSwapLong(this, stateOffset, s, n);
+ U.compareAndSwapLong(this, STATE, s, n);
releaseWaiters(phase);
}
else if (nextUnarrived == 0) { // propagate deregistration
phase = parent.doArrive(ONE_DEREGISTER);
- UNSAFE.compareAndSwapLong(this, stateOffset,
- s, s | EMPTY);
+ U.compareAndSwapLong(this, STATE, s, s | EMPTY);
}
else
phase = parent.doArrive(ONE_ARRIVAL);
@@ -419,7 +417,7 @@
}
/**
- * Implementation of register, bulkRegister
+ * Implementation of register, bulkRegister.
*
* @param registrations number to add to both parties and
* unarrived fields. Must be greater than zero.
@@ -443,14 +441,13 @@
if (parent == null || reconcileState() == s) {
if (unarrived == 0) // wait out advance
root.internalAwaitAdvance(phase, null);
- else if (UNSAFE.compareAndSwapLong(this, stateOffset,
- s, s + adjust))
+ else if (U.compareAndSwapLong(this, STATE, s, s + adjust))
break;
}
}
else if (parent == null) { // 1st root registration
long next = ((long)phase << PHASE_SHIFT) | adjust;
- if (UNSAFE.compareAndSwapLong(this, stateOffset, s, next))
+ if (U.compareAndSwapLong(this, STATE, s, next))
break;
}
else {
@@ -462,8 +459,8 @@
// finish registration whenever parent registration
// succeeded, even when racing with termination,
// since these are part of the same "transaction".
- while (!UNSAFE.compareAndSwapLong
- (this, stateOffset, s,
+ while (!U.compareAndSwapLong
+ (this, STATE, s,
((long)phase << PHASE_SHIFT) | adjust)) {
s = state;
phase = (int)(root.state >>> PHASE_SHIFT);
@@ -494,8 +491,8 @@
// CAS to root phase with current parties, tripping unarrived
while ((phase = (int)(root.state >>> PHASE_SHIFT)) !=
(int)(s >>> PHASE_SHIFT) &&
- !UNSAFE.compareAndSwapLong
- (this, stateOffset, s,
+ !U.compareAndSwapLong
+ (this, STATE, s,
s = (((long)phase << PHASE_SHIFT) |
((phase < 0) ? (s & COUNTS_MASK) :
(((p = (int)s >>> PARTIES_SHIFT) == 0) ? EMPTY :
@@ -684,8 +681,7 @@
int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
if (unarrived <= 0)
throw new IllegalStateException(badArrive(s));
- if (UNSAFE.compareAndSwapLong(this, stateOffset, s,
- s -= ONE_ARRIVAL)) {
+ if (U.compareAndSwapLong(this, STATE, s, s -= ONE_ARRIVAL)) {
if (unarrived > 1)
return root.internalAwaitAdvance(phase, null);
if (root != this)
@@ -700,7 +696,7 @@
n |= nextUnarrived;
int nextPhase = (phase + 1) & MAX_PHASE;
n |= (long)nextPhase << PHASE_SHIFT;
- if (!UNSAFE.compareAndSwapLong(this, stateOffset, s, n))
+ if (!U.compareAndSwapLong(this, STATE, s, n))
return (int)(state >>> PHASE_SHIFT); // terminated
releaseWaiters(phase);
return nextPhase;
@@ -816,8 +812,7 @@
final Phaser root = this.root;
long s;
while ((s = root.state) >= 0) {
- if (UNSAFE.compareAndSwapLong(root, stateOffset,
- s, s | TERMINATION_BIT)) {
+ if (U.compareAndSwapLong(root, STATE, s, s | TERMINATION_BIT)) {
// signal all threads
releaseWaiters(0); // Waiters on evenQ
releaseWaiters(1); // Waiters on oddQ
@@ -956,7 +951,7 @@
}
/**
- * Implementation of toString and string-based error messages
+ * Implementation of toString and string-based error messages.
*/
private String stateToString(long s) {
return super.toString() +
@@ -1065,7 +1060,7 @@
else {
try {
ForkJoinPool.managedBlock(node);
- } catch (InterruptedException ie) {
+ } catch (InterruptedException cantHappen) {
node.wasInterrupted = true;
}
}
@@ -1084,7 +1079,7 @@
}
/**
- * Wait nodes for Treiber stack representing wait queue
+ * Wait nodes for Treiber stack representing wait queue.
*/
static final class QNode implements ForkJoinPool.ManagedBlocker {
final Phaser phaser;
@@ -1121,41 +1116,39 @@
thread = null;
return true;
}
- if (timed) {
- if (nanos > 0L) {
- nanos = deadline - System.nanoTime();
- }
- if (nanos <= 0L) {
- thread = null;
- return true;
- }
+ if (timed &&
+ (nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
+ thread = null;
+ return true;
}
return false;
}
public boolean block() {
- if (isReleasable())
- return true;
- else if (!timed)
- LockSupport.park(this);
- else if (nanos > 0L)
- LockSupport.parkNanos(this, nanos);
- return isReleasable();
+ while (!isReleasable()) {
+ if (timed)
+ LockSupport.parkNanos(this, nanos);
+ else
+ LockSupport.park(this);
+ }
+ return true;
}
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long stateOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long STATE;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = Phaser.class;
- stateOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("state"));
- } catch (Exception e) {
+ STATE = U.objectFieldOffset
+ (Phaser.class.getDeclaredField("state"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,8 +35,6 @@
package java.util.concurrent;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
import java.util.AbstractQueue;
import java.util.Arrays;
import java.util.Collection;
@@ -47,6 +45,8 @@
import java.util.Queue;
import java.util.SortedSet;
import java.util.Spliterator;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
/**
@@ -78,7 +78,7 @@
* tie-breaking to comparable elements. To use it, you would insert a
* {@code new FIFOEntry(anEntry)} instead of a plain entry object.
*
- * <pre> {@code
+ * <pre> {@code
* class FIFOEntry<E extends Comparable<? super E>>
* implements Comparable<FIFOEntry<E>> {
* static final AtomicLong seq = new AtomicLong(0);
@@ -103,7 +103,7 @@
*
* @since 1.5
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
@SuppressWarnings("unchecked")
public class PriorityBlockingQueue<E> extends AbstractQueue<E>
@@ -161,12 +161,12 @@
private transient Comparator<? super E> comparator;
/**
- * Lock used for all public operations
+ * Lock used for all public operations.
*/
private final ReentrantLock lock;
/**
- * Condition for blocking when empty
+ * Condition for blocking when empty.
*/
private final Condition notEmpty;
@@ -289,8 +289,7 @@
lock.unlock(); // must release and then re-acquire main lock
Object[] newArray = null;
if (allocationSpinLock == 0 &&
- UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset,
- 0, 1)) {
+ U.compareAndSwapInt(this, ALLOCATIONSPINLOCK, 0, 1)) {
try {
int newCap = oldCap + ((oldCap < 64) ?
(oldCap + 2) : // grow faster if small
@@ -672,7 +671,7 @@
}
/**
- * Identity-based version for use in Itr.remove
+ * Identity-based version for use in Itr.remove.
*/
void removeEQ(Object o) {
final ReentrantLock lock = this.lock;
@@ -708,48 +707,8 @@
}
}
- /**
- * Returns an array containing all of the elements in this queue.
- * The returned array elements are in no particular order.
- *
- * <p>The returned array will be "safe" in that no references to it are
- * maintained by this queue. (In other words, this method must allocate
- * a new array). The caller is thus free to modify the returned array.
- *
- * <p>This method acts as bridge between array-based and collection-based
- * APIs.
- *
- * @return an array containing all of the elements in this queue
- */
- public Object[] toArray() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- return Arrays.copyOf(queue, size);
- } finally {
- lock.unlock();
- }
- }
-
public String toString() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- int n = size;
- if (n == 0)
- return "[]";
- StringBuilder sb = new StringBuilder();
- sb.append('[');
- for (int i = 0; i < n; ++i) {
- Object e = queue[i];
- sb.append(e == this ? "(this Collection)" : e);
- if (i != n - 1)
- sb.append(',').append(' ');
- }
- return sb.append(']').toString();
- } finally {
- lock.unlock();
- }
+ return Helpers.collectionToString(this);
}
/**
@@ -808,6 +767,29 @@
}
/**
+ * Returns an array containing all of the elements in this queue.
+ * The returned array elements are in no particular order.
+ *
+ * <p>The returned array will be "safe" in that no references to it are
+ * maintained by this queue. (In other words, this method must allocate
+ * a new array). The caller is thus free to modify the returned array.
+ *
+ * <p>This method acts as bridge between array-based and collection-based
+ * APIs.
+ *
+ * @return an array containing all of the elements in this queue
+ */
+ public Object[] toArray() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return Arrays.copyOf(queue, size);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ /**
* Returns an array containing all of the elements in this queue; the
* runtime type of the returned array is that of the specified array.
* The returned array elements are in no particular order.
@@ -829,7 +811,7 @@
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
- * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
+ * <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
@@ -971,7 +953,7 @@
return hi;
}
- public Spliterator<E> trySplit() {
+ public PBQSpliterator<E> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null :
new PBQSpliterator<E>(queue, array, lo, index = mid);
@@ -1028,15 +1010,13 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long allocationSpinLockOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long ALLOCATIONSPINLOCK;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = PriorityBlockingQueue.class;
- allocationSpinLockOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("allocationSpinLock"));
- } catch (Exception e) {
+ ALLOCATIONSPINLOCK = U.objectFieldOffset
+ (PriorityBlockingQueue.class.getDeclaredField("allocationSpinLock"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveAction.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveAction.java Tue Oct 20 08:24:37 2015 -0700
@@ -45,7 +45,7 @@
* <p><b>Sample Usages.</b> Here is a simple but complete ForkJoin
* sort that sorts a given {@code long[]} array:
*
- * <pre> {@code
+ * <pre> {@code
* static class SortTask extends RecursiveAction {
* final long[] array; final int lo, hi;
* SortTask(long[] array, int lo, int hi) {
@@ -79,7 +79,7 @@
* SortTask(anArray)} and invoking it in a ForkJoinPool. As a more
* concrete simple example, the following task increments each element
* of an array:
- * <pre> {@code
+ * <pre> {@code
* class IncrementTask extends RecursiveAction {
* final long[] array; final int lo, hi;
* IncrementTask(long[] array, int lo, int hi) {
@@ -110,7 +110,7 @@
* performing leaf actions on unstolen tasks rather than further
* subdividing.
*
- * <pre> {@code
+ * <pre> {@code
* double sumOfSquares(ForkJoinPool pool, double[] array) {
* int n = array.length;
* Applyer a = new Applyer(array, 0, n, null);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveTask.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/RecursiveTask.java Tue Oct 20 08:24:37 2015 -0700
@@ -40,11 +40,11 @@
*
* <p>For a classic example, here is a task computing Fibonacci numbers:
*
- * <pre> {@code
+ * <pre> {@code
* class Fibonacci extends RecursiveTask<Integer> {
* final int n;
* Fibonacci(int n) { this.n = n; }
- * Integer compute() {
+ * protected Integer compute() {
* if (n <= 1)
* return n;
* Fibonacci f1 = new Fibonacci(n - 1);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java Tue Oct 20 08:24:37 2015 -0700
@@ -70,7 +70,7 @@
* Here is a class with a method that sets up a ScheduledExecutorService
* to beep every ten seconds for an hour:
*
- * <pre> {@code
+ * <pre> {@code
* import static java.util.concurrent.TimeUnit.*;
* class BeeperControl {
* private final ScheduledExecutorService scheduler =
@@ -129,23 +129,37 @@
/**
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
- * period; that is executions will commence after
- * {@code initialDelay} then {@code initialDelay+period}, then
+ * period; that is, executions will commence after
+ * {@code initialDelay}, then {@code initialDelay + period}, then
* {@code initialDelay + 2 * period}, and so on.
- * If any execution of the task
- * encounters an exception, subsequent executions are suppressed.
- * Otherwise, the task will only terminate via cancellation or
- * termination of the executor. If any execution of this task
- * takes longer than its period, then subsequent executions
- * may start late, but will not concurrently execute.
+ *
+ * <p>The sequence of task executions continues indefinitely until
+ * one of the following exceptional completions occur:
+ * <ul>
+ * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+ * via the returned future.
+ * <li>The executor terminates, also resulting in task cancellation.
+ * <li>An execution of the task throws an exception. In this case
+ * calling {@link Future#get() get} on the returned future will
+ * throw {@link ExecutionException}.
+ * </ul>
+ * Subsequent executions are suppressed. Subsequent calls to
+ * {@link Future#isDone isDone()} on the returned future will
+ * return {@code true}.
+ *
+ * <p>If any execution of this task takes longer than its period, then
+ * subsequent executions may start late, but will not concurrently
+ * execute.
*
* @param command the task to execute
* @param initialDelay the time to delay first execution
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
- * the task, and whose {@code get()} method will throw an
- * exception upon cancellation
+ * the series of repeated tasks. The future's {@link
+ * Future#get() get()} method will never return normally,
+ * and will throw an exception upon task cancellation or
+ * abnormal termination of a task execution.
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
@@ -160,10 +174,21 @@
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the
* given delay between the termination of one execution and the
- * commencement of the next. If any execution of the task
- * encounters an exception, subsequent executions are suppressed.
- * Otherwise, the task will only terminate via cancellation or
- * termination of the executor.
+ * commencement of the next.
+ *
+ * <p>The sequence of task executions continues indefinitely until
+ * one of the following exceptional completions occur:
+ * <ul>
+ * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+ * via the returned future.
+ * <li>The executor terminates, also resulting in task cancellation.
+ * <li>An execution of the task throws an exception. In this case
+ * calling {@link Future#get() get} on the returned future will
+ * throw {@link ExecutionException}.
+ * </ul>
+ * Subsequent executions are suppressed. Subsequent calls to
+ * {@link Future#isDone isDone()} on the returned future will
+ * return {@code true}.
*
* @param command the task to execute
* @param initialDelay the time to delay first execution
@@ -171,8 +196,10 @@
* execution and the commencement of the next
* @param unit the time unit of the initialDelay and delay parameters
* @return a ScheduledFuture representing pending completion of
- * the task, and whose {@code get()} method will throw an
- * exception upon cancellation
+ * the series of repeated tasks. The future's {@link
+ * Future#get() get()} method will never return normally,
+ * and will throw an exception upon task cancellation or
+ * abnormal termination of a task execution.
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,19 +34,27 @@
*/
package java.util.concurrent;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.util.AbstractQueue;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
/**
* A {@link ThreadPoolExecutor} that can additionally schedule
- * commands to run after a given delay, or to execute
- * periodically. This class is preferable to {@link java.util.Timer}
- * when multiple worker threads are needed, or when the additional
- * flexibility or capabilities of {@link ThreadPoolExecutor} (which
- * this class extends) are required.
+ * commands to run after a given delay, or to execute periodically.
+ * This class is preferable to {@link java.util.Timer} when multiple
+ * worker threads are needed, or when the additional flexibility or
+ * capabilities of {@link ThreadPoolExecutor} (which this class
+ * extends) are required.
*
* <p>Delayed tasks execute no sooner than they are enabled, but
* without any real-time guarantees about when, after they are
@@ -55,20 +63,19 @@
* submission.
*
* <p>When a submitted task is cancelled before it is run, execution
- * is suppressed. By default, such a cancelled task is not
- * automatically removed from the work queue until its delay
- * elapses. While this enables further inspection and monitoring, it
- * may also cause unbounded retention of cancelled tasks. To avoid
- * this, set {@link #setRemoveOnCancelPolicy} to {@code true}, which
- * causes tasks to be immediately removed from the work queue at
- * time of cancellation.
+ * is suppressed. By default, such a cancelled task is not
+ * automatically removed from the work queue until its delay elapses.
+ * While this enables further inspection and monitoring, it may also
+ * cause unbounded retention of cancelled tasks. To avoid this, use
+ * {@link #setRemoveOnCancelPolicy} to cause tasks to be immediately
+ * removed from the work queue at time of cancellation.
*
- * <p>Successive executions of a task scheduled via
- * {@code scheduleAtFixedRate} or
- * {@code scheduleWithFixedDelay} do not overlap. While different
- * executions may be performed by different threads, the effects of
- * prior executions <a
- * href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * <p>Successive executions of a periodic task scheduled via
+ * {@link #scheduleAtFixedRate scheduleAtFixedRate} or
+ * {@link #scheduleWithFixedDelay scheduleWithFixedDelay}
+ * do not overlap. While different executions may be performed by
+ * different threads, the effects of prior executions
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
* those of subsequent ones.
*
* <p>While this class inherits from {@link ThreadPoolExecutor}, a few
@@ -98,7 +105,7 @@
* {@link FutureTask}. However, this may be modified or replaced using
* subclasses of the form:
*
- * <pre> {@code
+ * <pre> {@code
* public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor {
*
* static class CustomTask<V> implements RunnableScheduledFuture<V> { ... }
@@ -160,9 +167,9 @@
private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
/**
- * True if ScheduledFutureTask.cancel should remove from queue
+ * True if ScheduledFutureTask.cancel should remove from queue.
*/
- private volatile boolean removeOnCancel = false;
+ volatile boolean removeOnCancel;
/**
* Sequence number to break scheduling ties, and in turn to
@@ -173,7 +180,7 @@
/**
* Returns current nanosecond time.
*/
- final long now() {
+ static final long now() {
return System.nanoTime();
}
@@ -184,13 +191,13 @@
private final long sequenceNumber;
/** The time the task is enabled to execute in nanoTime units */
- private long time;
+ private volatile long time;
/**
- * Period in nanoseconds for repeating tasks. A positive
- * value indicates fixed-rate execution. A negative value
- * indicates fixed-delay execution. A value of 0 indicates a
- * non-repeating task.
+ * Period in nanoseconds for repeating tasks.
+ * A positive value indicates fixed-rate execution.
+ * A negative value indicates fixed-delay execution.
+ * A value of 0 indicates a non-repeating (one-shot) task.
*/
private final long period;
@@ -205,31 +212,35 @@
/**
* Creates a one-shot action with given nanoTime-based trigger time.
*/
- ScheduledFutureTask(Runnable r, V result, long ns) {
+ ScheduledFutureTask(Runnable r, V result, long triggerTime,
+ long sequenceNumber) {
super(r, result);
- this.time = ns;
+ this.time = triggerTime;
this.period = 0;
- this.sequenceNumber = sequencer.getAndIncrement();
+ this.sequenceNumber = sequenceNumber;
}
/**
- * Creates a periodic action with given nano time and period.
+ * Creates a periodic action with given nanoTime-based initial
+ * trigger time and period.
*/
- ScheduledFutureTask(Runnable r, V result, long ns, long period) {
+ ScheduledFutureTask(Runnable r, V result, long triggerTime,
+ long period, long sequenceNumber) {
super(r, result);
- this.time = ns;
+ this.time = triggerTime;
this.period = period;
- this.sequenceNumber = sequencer.getAndIncrement();
+ this.sequenceNumber = sequenceNumber;
}
/**
* Creates a one-shot action with given nanoTime-based trigger time.
*/
- ScheduledFutureTask(Callable<V> callable, long ns) {
+ ScheduledFutureTask(Callable<V> callable, long triggerTime,
+ long sequenceNumber) {
super(callable);
- this.time = ns;
+ this.time = triggerTime;
this.period = 0;
- this.sequenceNumber = sequencer.getAndIncrement();
+ this.sequenceNumber = sequenceNumber;
}
public long getDelay(TimeUnit unit) {
@@ -290,8 +301,8 @@
if (!canRunInCurrentRunState(periodic))
cancel(false);
else if (!periodic)
- ScheduledFutureTask.super.run();
- else if (ScheduledFutureTask.super.runAndReset()) {
+ super.run();
+ else if (super.runAndReset()) {
setNextRunTime();
reExecutePeriodic(outerTask);
}
@@ -419,6 +430,22 @@
}
/**
+ * The default keep-alive time for pool threads.
+ *
+ * Normally, this value is unused because all pool threads will be
+ * core threads, but if a user creates a pool with a corePoolSize
+ * of zero (against our advice), we keep a thread alive as long as
+ * there are queued tasks. If the keep alive time is zero (the
+ * historic value), we end up hot-spinning in getTask, wasting a
+ * CPU. But on the other hand, if we set the value too high, and
+ * users create a one-shot pool which they don't cleanly shutdown,
+ * the pool's non-daemon threads will prevent JVM termination. A
+ * small but non-zero value (relative to a JVM's lifetime) seems
+ * best.
+ */
+ private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
+
+ /**
* Creates a new {@code ScheduledThreadPoolExecutor} with the
* given core pool size.
*
@@ -427,7 +454,8 @@
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public ScheduledThreadPoolExecutor(int corePoolSize) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
@@ -444,13 +472,14 @@
*/
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory);
}
/**
- * Creates a new ScheduledThreadPoolExecutor with the given
- * initial parameters.
+ * Creates a new {@code ScheduledThreadPoolExecutor} with the
+ * given initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -461,13 +490,14 @@
*/
public ScheduledThreadPoolExecutor(int corePoolSize,
RejectedExecutionHandler handler) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), handler);
}
/**
- * Creates a new ScheduledThreadPoolExecutor with the given
- * initial parameters.
+ * Creates a new {@code ScheduledThreadPoolExecutor} with the
+ * given initial parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
@@ -482,19 +512,20 @@
public ScheduledThreadPoolExecutor(int corePoolSize,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
- super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
+ super(corePoolSize, Integer.MAX_VALUE,
+ DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue(), threadFactory, handler);
}
/**
- * Returns the trigger time of a delayed action.
+ * Returns the nanoTime-based trigger time of a delayed action.
*/
private long triggerTime(long delay, TimeUnit unit) {
return triggerTime(unit.toNanos((delay < 0) ? 0 : delay));
}
/**
- * Returns the trigger time of a delayed action.
+ * Returns the nanoTime-based trigger time of a delayed action.
*/
long triggerTime(long delay) {
return now() +
@@ -527,9 +558,10 @@
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
- RunnableScheduledFuture<?> t = decorateTask(command,
+ RunnableScheduledFuture<Void> t = decorateTask(command,
new ScheduledFutureTask<Void>(command, null,
- triggerTime(delay, unit)));
+ triggerTime(delay, unit),
+ sequencer.getAndIncrement()));
delayedExecute(t);
return t;
}
@@ -545,7 +577,8 @@
throw new NullPointerException();
RunnableScheduledFuture<V> t = decorateTask(callable,
new ScheduledFutureTask<V>(callable,
- triggerTime(delay, unit)));
+ triggerTime(delay, unit),
+ sequencer.getAndIncrement()));
delayedExecute(t);
return t;
}
@@ -561,13 +594,14 @@
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
- if (period <= 0)
+ if (period <= 0L)
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
- unit.toNanos(period));
+ unit.toNanos(period),
+ sequencer.getAndIncrement());
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
@@ -585,13 +619,14 @@
TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
- if (delay <= 0)
+ if (delay <= 0L)
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command,
null,
triggerTime(initialDelay, unit),
- unit.toNanos(-delay));
+ -unit.toNanos(delay),
+ sequencer.getAndIncrement());
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
@@ -764,7 +799,8 @@
/**
* Attempts to stop all actively executing tasks, halts the
* processing of waiting tasks, and returns a list of the tasks
- * that were awaiting execution.
+ * that were awaiting execution. These tasks are drained (removed)
+ * from the task queue upon return from this method.
*
* <p>This method does not wait for actively executing tasks to
* terminate. Use {@link #awaitTermination awaitTermination} to
@@ -772,13 +808,15 @@
*
* <p>There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. This implementation
- * cancels tasks via {@link Thread#interrupt}, so any task that
+ * interrupts tasks via {@link Thread#interrupt}; any task that
* fails to respond to interrupts may never terminate.
*
* @return list of tasks that never commenced execution.
- * Each element of this list is a {@link ScheduledFuture},
- * including those tasks submitted using {@code execute},
- * which are for scheduling purposes used as the basis of a
+ * Each element of this list is a {@link ScheduledFuture}.
+ * For tasks submitted via one of the {@code schedule}
+ * methods, the element will be identical to the returned
+ * {@code ScheduledFuture}. For tasks submitted using
+ * {@link #execute execute}, the element will be a
* zero-delay {@code ScheduledFuture}.
* @throws SecurityException {@inheritDoc}
*/
@@ -787,13 +825,19 @@
}
/**
- * Returns the task queue used by this executor. Each element of
- * this queue is a {@link ScheduledFuture}, including those
- * tasks submitted using {@code execute} which are for scheduling
- * purposes used as the basis of a zero-delay
- * {@code ScheduledFuture}. Iteration over this queue is
- * <em>not</em> guaranteed to traverse tasks in the order in
- * which they will execute.
+ * Returns the task queue used by this executor. Access to the
+ * task queue is intended primarily for debugging and monitoring.
+ * This queue may be in active use. Retrieving the task queue
+ * does not prevent queued tasks from executing.
+ *
+ * <p>Each element of this queue is a {@link ScheduledFuture}.
+ * For tasks submitted via one of the {@code schedule} methods, the
+ * element will be identical to the returned {@code ScheduledFuture}.
+ * For tasks submitted using {@link #execute execute}, the element
+ * will be a zero-delay {@code ScheduledFuture}.
+ *
+ * <p>Iteration over this queue is <em>not</em> guaranteed to traverse
+ * tasks in the order in which they will execute.
*
* @return the task queue
*/
@@ -836,7 +880,7 @@
private RunnableScheduledFuture<?>[] queue =
new RunnableScheduledFuture<?>[INITIAL_CAPACITY];
private final ReentrantLock lock = new ReentrantLock();
- private int size = 0;
+ private int size;
/**
* Thread designated to wait for the task at the head of the
@@ -854,7 +898,7 @@
* signalled. So waiting threads must be prepared to acquire
* and lose leadership while waiting.
*/
- private Thread leader = null;
+ private Thread leader;
/**
* Condition signalled when a newer task becomes available at the
@@ -1062,10 +1106,9 @@
lock.lock();
try {
RunnableScheduledFuture<?> first = queue[0];
- if (first == null || first.getDelay(NANOSECONDS) > 0)
- return null;
- else
- return finishPoll(first);
+ return (first == null || first.getDelay(NANOSECONDS) > 0)
+ ? null
+ : finishPoll(first);
} finally {
lock.unlock();
}
@@ -1081,7 +1124,7 @@
available.await();
else {
long delay = first.getDelay(NANOSECONDS);
- if (delay <= 0)
+ if (delay <= 0L)
return finishPoll(first);
first = null; // don't retain ref while waiting
if (leader != null)
@@ -1114,15 +1157,15 @@
for (;;) {
RunnableScheduledFuture<?> first = queue[0];
if (first == null) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(NANOSECONDS);
- if (delay <= 0)
+ if (delay <= 0L)
return finishPoll(first);
- if (nanos <= 0)
+ if (nanos <= 0L)
return null;
first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
@@ -1254,8 +1297,8 @@
*/
private class Itr implements Iterator<Runnable> {
final RunnableScheduledFuture<?>[] array;
- int cursor = 0; // index of next element to return
- int lastRet = -1; // index of last element, or -1 if no such
+ int cursor; // index of next element to return; initially 0
+ int lastRet = -1; // index of last element returned; -1 if no such
Itr(RunnableScheduledFuture<?>[] array) {
this.array = array;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Semaphore.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent;
+
import java.util.Collection;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
@@ -48,7 +49,7 @@
* <p>Semaphores are often used to restrict the number of threads than can
* access some (physical or logical) resource. For example, here is
* a class that uses a semaphore to control access to a pool of items:
- * <pre> {@code
+ * <pre> {@code
* class Pool {
* private static final int MAX_AVAILABLE = 100;
* private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
@@ -114,7 +115,7 @@
* ownership). This can be useful in some specialized contexts, such
* as deadlock recovery.
*
- * <p> The constructor for this class optionally accepts a
+ * <p>The constructor for this class optionally accepts a
* <em>fairness</em> parameter. When set false, this class makes no
* guarantees about the order in which threads acquire permits. In
* particular, <em>barging</em> is permitted, that is, a thread
@@ -141,8 +142,13 @@
*
* <p>This class also provides convenience methods to {@link
* #acquire(int) acquire} and {@link #release(int) release} multiple
- * permits at a time. Beware of the increased risk of indefinite
- * postponement when these methods are used without fairness set true.
+ * permits at a time. These methods are generally more efficient and
+ * effective than loops. However, they do not establish any preference
+ * order. For example, if thread A invokes {@code s.acquire(3}) and
+ * thread B invokes {@code s.acquire(2)}, and two permits become
+ * available, then there is no guarantee that thread B will obtain
+ * them unless its acquire came first and Semaphore {@code s} is in
+ * fair mode.
*
* <p>Memory consistency effects: Actions in a thread prior to calling
* a "release" method such as {@code release()}
@@ -433,14 +439,16 @@
*
* <p>Acquires the given number of permits, if they are available,
* and returns immediately, reducing the number of available permits
- * by the given amount.
+ * by the given amount. This method has the same effect as the
+ * loop {@code for (int i = 0; i < permits; ++i) acquire();} except
+ * that it atomically acquires the permits all at once:
*
* <p>If insufficient permits are available then the current thread becomes
* disabled for thread scheduling purposes and lies dormant until
* one of two things happens:
* <ul>
* <li>Some other thread invokes one of the {@link #release() release}
- * methods for this semaphore, the current thread is next to be assigned
+ * methods for this semaphore and the current thread is next to be assigned
* permits and the number of available permits satisfies this request; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
@@ -473,12 +481,14 @@
*
* <p>Acquires the given number of permits, if they are available,
* and returns immediately, reducing the number of available permits
- * by the given amount.
+ * by the given amount. This method has the same effect as the
+ * loop {@code for (int i = 0; i < permits; ++i) acquireUninterruptibly();}
+ * except that it atomically acquires the permits all at once:
*
* <p>If insufficient permits are available then the current thread becomes
* disabled for thread scheduling purposes and lies dormant until
* some other thread invokes one of the {@link #release() release}
- * methods for this semaphore, the current thread is next to be assigned
+ * methods for this semaphore and the current thread is next to be assigned
* permits and the number of available permits satisfies this request.
*
* <p>If the current thread is {@linkplain Thread#interrupt interrupted}
@@ -540,7 +550,7 @@
* purposes and lies dormant until one of three things happens:
* <ul>
* <li>Some other thread invokes one of the {@link #release() release}
- * methods for this semaphore, the current thread is next to be assigned
+ * methods for this semaphore and the current thread is next to be assigned
* permits and the number of available permits satisfies this request; or
* <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
@@ -587,7 +597,7 @@
*
* <p>Releases the given number of permits, increasing the number of
* available permits by that amount.
- * If any threads are trying to acquire permits, then one
+ * If any threads are trying to acquire permits, then one thread
* is selected and given the permits that were just released.
* If the number of available permits satisfies that thread's request
* then that thread is (re)enabled for thread scheduling purposes;
@@ -671,7 +681,7 @@
* Returns an estimate of the number of threads waiting to acquire.
* The value is only an estimate because the number of threads may
* change dynamically while this method traverses internal data
- * structures. This method is designed for use in monitoring of the
+ * structures. This method is designed for use in monitoring
* system state, not for synchronization control.
*
* @return the estimated number of threads waiting for this lock
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,1632 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.locks.LockSupport;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+/**
+ * A {@link Flow.Publisher} that asynchronously issues submitted
+ * (non-null) items to current subscribers until it is closed. Each
+ * current subscriber receives newly submitted items in the same order
+ * unless drops or exceptions are encountered. Using a
+ * SubmissionPublisher allows item generators to act as compliant <a
+ * href="http://www.reactive-streams.org/"> reactive-streams</a>
+ * Publishers relying on drop handling and/or blocking for flow
+ * control.
+ *
+ * <p>A SubmissionPublisher uses the {@link Executor} supplied in its
+ * constructor for delivery to subscribers. The best choice of
+ * Executor depends on expected usage. If the generator(s) of
+ * submitted items run in separate threads, and the number of
+ * subscribers can be estimated, consider using a {@link
+ * Executors#newFixedThreadPool}. Otherwise consider using the
+ * default, normally the {@link ForkJoinPool#commonPool}.
+ *
+ * <p>Buffering allows producers and consumers to transiently operate
+ * at different rates. Each subscriber uses an independent buffer.
+ * Buffers are created upon first use and expanded as needed up to the
+ * given maximum. (The enforced capacity may be rounded up to the
+ * nearest power of two and/or bounded by the largest value supported
+ * by this implementation.) Invocations of {@link
+ * Flow.Subscription#request(long) request} do not directly result in
+ * buffer expansion, but risk saturation if unfilled requests exceed
+ * the maximum capacity. The default value of {@link
+ * Flow#defaultBufferSize()} may provide a useful starting point for
+ * choosing a capacity based on expected rates, resources, and usages.
+ *
+ * <p>Publication methods support different policies about what to do
+ * when buffers are saturated. Method {@link #submit(Object) submit}
+ * blocks until resources are available. This is simplest, but least
+ * responsive. The {@code offer} methods may drop items (either
+ * immediately or with bounded timeout), but provide an opportunity to
+ * interpose a handler and then retry.
+ *
+ * <p>If any Subscriber method throws an exception, its subscription
+ * is cancelled. If a handler is supplied as a constructor argument,
+ * it is invoked before cancellation upon an exception in method
+ * {@link Flow.Subscriber#onNext onNext}, but exceptions in methods
+ * {@link Flow.Subscriber#onSubscribe onSubscribe},
+ * {@link Flow.Subscriber#onError(Throwable) onError} and
+ * {@link Flow.Subscriber#onComplete() onComplete} are not recorded or
+ * handled before cancellation. If the supplied Executor throws
+ * {@link RejectedExecutionException} (or any other RuntimeException
+ * or Error) when attempting to execute a task, or a drop handler
+ * throws an exception when processing a dropped item, then the
+ * exception is rethrown. In these cases, not all subscribers will
+ * have been issued the published item. It is usually good practice to
+ * {@link #closeExceptionally closeExceptionally} in these cases.
+ *
+ * <p>Method {@link #consume(Consumer)} simplifies support for a
+ * common case in which the only action of a subscriber is to request
+ * and process all items using a supplied function.
+ *
+ * <p>This class may also serve as a convenient base for subclasses
+ * that generate items, and use the methods in this class to publish
+ * them. For example here is a class that periodically publishes the
+ * items generated from a supplier. (In practice you might add methods
+ * to independently start and stop generation, to share Executors
+ * among publishers, and so on, or use a SubmissionPublisher as a
+ * component rather than a superclass.)
+ *
+ * <pre> {@code
+ * class PeriodicPublisher<T> extends SubmissionPublisher<T> {
+ * final ScheduledFuture<?> periodicTask;
+ * final ScheduledExecutorService scheduler;
+ * PeriodicPublisher(Executor executor, int maxBufferCapacity,
+ * Supplier<? extends T> supplier,
+ * long period, TimeUnit unit) {
+ * super(executor, maxBufferCapacity);
+ * scheduler = new ScheduledThreadPoolExecutor(1);
+ * periodicTask = scheduler.scheduleAtFixedRate(
+ * () -> submit(supplier.get()), 0, period, unit);
+ * }
+ * public void close() {
+ * periodicTask.cancel(false);
+ * scheduler.shutdown();
+ * super.close();
+ * }
+ * }}</pre>
+ *
+ * <p>Here is an example of a {@link Flow.Processor} implementation.
+ * It uses single-step requests to its publisher for simplicity of
+ * illustration. A more adaptive version could monitor flow using the
+ * lag estimate returned from {@code submit}, along with other utility
+ * methods.
+ *
+ * <pre> {@code
+ * class TransformProcessor<S,T> extends SubmissionPublisher<T>
+ * implements Flow.Processor<S,T> {
+ * final Function<? super S, ? extends T> function;
+ * Flow.Subscription subscription;
+ * TransformProcessor(Executor executor, int maxBufferCapacity,
+ * Function<? super S, ? extends T> function) {
+ * super(executor, maxBufferCapacity);
+ * this.function = function;
+ * }
+ * public void onSubscribe(Flow.Subscription subscription) {
+ * (this.subscription = subscription).request(1);
+ * }
+ * public void onNext(S item) {
+ * subscription.request(1);
+ * submit(function.apply(item));
+ * }
+ * public void onError(Throwable ex) { closeExceptionally(ex); }
+ * public void onComplete() { close(); }
+ * }}</pre>
+ *
+ * @param <T> the published item type
+ * @author Doug Lea
+ * @since 1.9
+ */
+public class SubmissionPublisher<T> implements Flow.Publisher<T>,
+ AutoCloseable {
+ /*
+ * Most mechanics are handled by BufferedSubscription. This class
+ * mainly tracks subscribers and ensures sequentiality, by using
+ * built-in synchronization locks across public methods. (Using
+ * built-in locks works well in the most typical case in which
+ * only one thread submits items).
+ */
+
+ /** The largest possible power of two array size. */
+ static final int BUFFER_CAPACITY_LIMIT = 1 << 30;
+
+ /** Round capacity to power of 2, at most limit. */
+ static final int roundCapacity(int cap) {
+ int n = cap - 1;
+ n |= n >>> 1;
+ n |= n >>> 2;
+ n |= n >>> 4;
+ n |= n >>> 8;
+ n |= n >>> 16;
+ return (n <= 0) ? 1 : // at least 1
+ (n >= BUFFER_CAPACITY_LIMIT) ? BUFFER_CAPACITY_LIMIT : n + 1;
+ }
+
+ // default Executor setup; nearly the same as CompletableFuture
+
+ /**
+ * Default executor -- ForkJoinPool.commonPool() unless it cannot
+ * support parallelism.
+ */
+ private static final Executor ASYNC_POOL =
+ (ForkJoinPool.getCommonPoolParallelism() > 1) ?
+ ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
+
+ /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */
+ private static final class ThreadPerTaskExecutor implements Executor {
+ public void execute(Runnable r) { new Thread(r).start(); }
+ }
+
+ /**
+ * Clients (BufferedSubscriptions) are maintained in a linked list
+ * (via their "next" fields). This works well for publish loops.
+ * It requires O(n) traversal to check for duplicate subscribers,
+ * but we expect that subscribing is much less common than
+ * publishing. Unsubscribing occurs only during traversal loops,
+ * when BufferedSubscription methods return negative values
+ * signifying that they have been disabled. To reduce
+ * head-of-line blocking, submit and offer methods first call
+ * BufferedSubscription.offer on each subscriber, and place
+ * saturated ones in retries list (using nextRetry field), and
+ * retry, possibly blocking or dropping.
+ */
+ BufferedSubscription<T> clients;
+
+ /** Run status, updated only within locks */
+ volatile boolean closed;
+ /** If non-null, the exception in closeExceptionally */
+ volatile Throwable closedException;
+
+ // Parameters for constructing BufferedSubscriptions
+ final Executor executor;
+ final BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> onNextHandler;
+ final int maxBufferCapacity;
+
+ /**
+ * Creates a new SubmissionPublisher using the given Executor for
+ * async delivery to subscribers, with the given maximum buffer size
+ * for each subscriber, and, if non-null, the given handler invoked
+ * when any Subscriber throws an exception in method {@link
+ * Flow.Subscriber#onNext(Object) onNext}.
+ *
+ * @param executor the executor to use for async delivery,
+ * supporting creation of at least one independent thread
+ * @param maxBufferCapacity the maximum capacity for each
+ * subscriber's buffer (the enforced capacity may be rounded up to
+ * the nearest power of two and/or bounded by the largest value
+ * supported by this implementation; method {@link #getMaxBufferCapacity}
+ * returns the actual value)
+ * @param handler if non-null, procedure to invoke upon exception
+ * thrown in method {@code onNext}
+ * @throws NullPointerException if executor is null
+ * @throws IllegalArgumentException if maxBufferCapacity not
+ * positive
+ */
+ public SubmissionPublisher(Executor executor, int maxBufferCapacity,
+ BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> handler) {
+ if (executor == null)
+ throw new NullPointerException();
+ if (maxBufferCapacity <= 0)
+ throw new IllegalArgumentException("capacity must be positive");
+ this.executor = executor;
+ this.onNextHandler = handler;
+ this.maxBufferCapacity = roundCapacity(maxBufferCapacity);
+ }
+
+ /**
+ * Creates a new SubmissionPublisher using the given Executor for
+ * async delivery to subscribers, with the given maximum buffer size
+ * for each subscriber, and no handler for Subscriber exceptions in
+ * method {@link Flow.Subscriber#onNext(Object) onNext}.
+ *
+ * @param executor the executor to use for async delivery,
+ * supporting creation of at least one independent thread
+ * @param maxBufferCapacity the maximum capacity for each
+ * subscriber's buffer (the enforced capacity may be rounded up to
+ * the nearest power of two and/or bounded by the largest value
+ * supported by this implementation; method {@link #getMaxBufferCapacity}
+ * returns the actual value)
+ * @throws NullPointerException if executor is null
+ * @throws IllegalArgumentException if maxBufferCapacity not
+ * positive
+ */
+ public SubmissionPublisher(Executor executor, int maxBufferCapacity) {
+ this(executor, maxBufferCapacity, null);
+ }
+
+ /**
+ * Creates a new SubmissionPublisher using the {@link
+ * ForkJoinPool#commonPool()} for async delivery to subscribers
+ * (unless it does not support a parallelism level of at least two,
+ * in which case, a new Thread is created to run each task), with
+ * maximum buffer capacity of {@link Flow#defaultBufferSize}, and no
+ * handler for Subscriber exceptions in method {@link
+ * Flow.Subscriber#onNext(Object) onNext}.
+ */
+ public SubmissionPublisher() {
+ this(ASYNC_POOL, Flow.defaultBufferSize(), null);
+ }
+
+ /**
+ * Adds the given Subscriber unless already subscribed. If already
+ * subscribed, the Subscriber's {@link
+ * Flow.Subscriber#onError(Throwable) onError} method is invoked on
+ * the existing subscription with an {@link IllegalStateException}.
+ * Otherwise, upon success, the Subscriber's {@link
+ * Flow.Subscriber#onSubscribe onSubscribe} method is invoked
+ * asynchronously with a new {@link Flow.Subscription}. If {@link
+ * Flow.Subscriber#onSubscribe onSubscribe} throws an exception, the
+ * subscription is cancelled. Otherwise, if this SubmissionPublisher
+ * was closed exceptionally, then the subscriber's {@link
+ * Flow.Subscriber#onError onError} method is invoked with the
+ * corresponding exception, or if closed without exception, the
+ * subscriber's {@link Flow.Subscriber#onComplete() onComplete}
+ * method is invoked. Subscribers may enable receiving items by
+ * invoking the {@link Flow.Subscription#request(long) request}
+ * method of the new Subscription, and may unsubscribe by invoking
+ * its {@link Flow.Subscription#cancel() cancel} method.
+ *
+ * @param subscriber the subscriber
+ * @throws NullPointerException if subscriber is null
+ */
+ public void subscribe(Flow.Subscriber<? super T> subscriber) {
+ if (subscriber == null) throw new NullPointerException();
+ BufferedSubscription<T> subscription =
+ new BufferedSubscription<T>(subscriber, executor,
+ onNextHandler, maxBufferCapacity);
+ synchronized (this) {
+ for (BufferedSubscription<T> b = clients, pred = null;;) {
+ if (b == null) {
+ Throwable ex;
+ subscription.onSubscribe();
+ if ((ex = closedException) != null)
+ subscription.onError(ex);
+ else if (closed)
+ subscription.onComplete();
+ else if (pred == null)
+ clients = subscription;
+ else
+ pred.next = subscription;
+ break;
+ }
+ BufferedSubscription<T> next = b.next;
+ if (b.isDisabled()) { // remove
+ b.next = null; // detach
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else if (subscriber.equals(b.subscriber)) {
+ b.onError(new IllegalStateException("Duplicate subscribe"));
+ break;
+ }
+ else
+ pred = b;
+ b = next;
+ }
+ }
+ }
+
+ /**
+ * Publishes the given item to each current subscriber by
+ * asynchronously invoking its {@link Flow.Subscriber#onNext(Object)
+ * onNext} method, blocking uninterruptibly while resources for any
+ * subscriber are unavailable. This method returns an estimate of
+ * the maximum lag (number of items submitted but not yet consumed)
+ * among all current subscribers. This value is at least one
+ * (accounting for this submitted item) if there are any
+ * subscribers, else zero.
+ *
+ * <p>If the Executor for this publisher throws a
+ * RejectedExecutionException (or any other RuntimeException or
+ * Error) when attempting to asynchronously notify subscribers,
+ * then this exception is rethrown, in which case not all
+ * subscribers will have been issued this item.
+ *
+ * @param item the (non-null) item to publish
+ * @return the estimated maximum lag among subscribers
+ * @throws IllegalStateException if closed
+ * @throws NullPointerException if item is null
+ * @throws RejectedExecutionException if thrown by Executor
+ */
+ public int submit(T item) {
+ if (item == null) throw new NullPointerException();
+ int lag = 0;
+ boolean complete;
+ synchronized (this) {
+ complete = closed;
+ BufferedSubscription<T> b = clients;
+ if (!complete) {
+ BufferedSubscription<T> pred = null, r = null, rtail = null;
+ while (b != null) {
+ BufferedSubscription<T> next = b.next;
+ int stat = b.offer(item);
+ if (stat < 0) { // disabled
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else {
+ if (stat > lag)
+ lag = stat;
+ else if (stat == 0) { // place on retry list
+ b.nextRetry = null;
+ if (rtail == null)
+ r = b;
+ else
+ rtail.nextRetry = b;
+ rtail = b;
+ }
+ pred = b;
+ }
+ b = next;
+ }
+ while (r != null) {
+ BufferedSubscription<T> nextRetry = r.nextRetry;
+ r.nextRetry = null;
+ int stat = r.submit(item);
+ if (stat > lag)
+ lag = stat;
+ else if (stat < 0 && clients == r)
+ clients = r.next; // postpone internal unsubscribes
+ r = nextRetry;
+ }
+ }
+ }
+ if (complete)
+ throw new IllegalStateException("Closed");
+ else
+ return lag;
+ }
+
+ /**
+ * Publishes the given item, if possible, to each current subscriber
+ * by asynchronously invoking its {@link
+ * Flow.Subscriber#onNext(Object) onNext} method. The item may be
+ * dropped by one or more subscribers if resource limits are
+ * exceeded, in which case the given handler (if non-null) is
+ * invoked, and if it returns true, retried once. Other calls to
+ * methods in this class by other threads are blocked while the
+ * handler is invoked. Unless recovery is assured, options are
+ * usually limited to logging the error and/or issuing an {@link
+ * Flow.Subscriber#onError(Throwable) onError} signal to the
+ * subscriber.
+ *
+ * <p>This method returns a status indicator: If negative, it
+ * represents the (negative) number of drops (failed attempts to
+ * issue the item to a subscriber). Otherwise it is an estimate of
+ * the maximum lag (number of items submitted but not yet
+ * consumed) among all current subscribers. This value is at least
+ * one (accounting for this submitted item) if there are any
+ * subscribers, else zero.
+ *
+ * <p>If the Executor for this publisher throws a
+ * RejectedExecutionException (or any other RuntimeException or
+ * Error) when attempting to asynchronously notify subscribers, or
+ * the drop handler throws an exception when processing a dropped
+ * item, then this exception is rethrown.
+ *
+ * @param item the (non-null) item to publish
+ * @param onDrop if non-null, the handler invoked upon a drop to a
+ * subscriber, with arguments of the subscriber and item; if it
+ * returns true, an offer is re-attempted (once)
+ * @return if negative, the (negative) number of drops; otherwise
+ * an estimate of maximum lag
+ * @throws IllegalStateException if closed
+ * @throws NullPointerException if item is null
+ * @throws RejectedExecutionException if thrown by Executor
+ */
+ public int offer(T item,
+ BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
+ return doOffer(0L, item, onDrop);
+ }
+
+ /**
+ * Publishes the given item, if possible, to each current subscriber
+ * by asynchronously invoking its {@link
+ * Flow.Subscriber#onNext(Object) onNext} method, blocking while
+ * resources for any subscription are unavailable, up to the
+ * specified timeout or until the caller thread is interrupted, at
+ * which point the given handler (if non-null) is invoked, and if it
+ * returns true, retried once. (The drop handler may distinguish
+ * timeouts from interrupts by checking whether the current thread
+ * is interrupted.) Other calls to methods in this class by other
+ * threads are blocked while the handler is invoked. Unless
+ * recovery is assured, options are usually limited to logging the
+ * error and/or issuing an {@link Flow.Subscriber#onError(Throwable)
+ * onError} signal to the subscriber.
+ *
+ * <p>This method returns a status indicator: If negative, it
+ * represents the (negative) number of drops (failed attempts to
+ * issue the item to a subscriber). Otherwise it is an estimate of
+ * the maximum lag (number of items submitted but not yet
+ * consumed) among all current subscribers. This value is at least
+ * one (accounting for this submitted item) if there are any
+ * subscribers, else zero.
+ *
+ * <p>If the Executor for this publisher throws a
+ * RejectedExecutionException (or any other RuntimeException or
+ * Error) when attempting to asynchronously notify subscribers, or
+ * the drop handler throws an exception when processing a dropped
+ * item, then this exception is rethrown.
+ *
+ * @param item the (non-null) item to publish
+ * @param timeout how long to wait for resources for any subscriber
+ * before giving up, in units of {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @param onDrop if non-null, the handler invoked upon a drop to a
+ * subscriber, with arguments of the subscriber and item; if it
+ * returns true, an offer is re-attempted (once)
+ * @return if negative, the (negative) number of drops; otherwise
+ * an estimate of maximum lag
+ * @throws IllegalStateException if closed
+ * @throws NullPointerException if item is null
+ * @throws RejectedExecutionException if thrown by Executor
+ */
+ public int offer(T item, long timeout, TimeUnit unit,
+ BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
+ return doOffer(unit.toNanos(timeout), item, onDrop);
+ }
+
+ /** Common implementation for both forms of offer */
+ final int doOffer(long nanos, T item,
+ BiPredicate<Flow.Subscriber<? super T>, ? super T> onDrop) {
+ if (item == null) throw new NullPointerException();
+ int lag = 0, drops = 0;
+ boolean complete;
+ synchronized (this) {
+ complete = closed;
+ BufferedSubscription<T> b = clients;
+ if (!complete) {
+ BufferedSubscription<T> pred = null, r = null, rtail = null;
+ while (b != null) {
+ BufferedSubscription<T> next = b.next;
+ int stat = b.offer(item);
+ if (stat < 0) {
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else {
+ if (stat > lag)
+ lag = stat;
+ else if (stat == 0) {
+ b.nextRetry = null;
+ if (rtail == null)
+ r = b;
+ else
+ rtail.nextRetry = b;
+ rtail = b;
+ }
+ else if (stat > lag)
+ lag = stat;
+ pred = b;
+ }
+ b = next;
+ }
+ while (r != null) {
+ BufferedSubscription<T> nextRetry = r.nextRetry;
+ r.nextRetry = null;
+ int stat = (nanos > 0L) ? r.timedOffer(item, nanos) :
+ r.offer(item);
+ if (stat == 0 && onDrop != null &&
+ onDrop.test(r.subscriber, item))
+ stat = r.offer(item);
+ if (stat == 0)
+ ++drops;
+ else if (stat > lag)
+ lag = stat;
+ else if (stat < 0 && clients == r)
+ clients = r.next;
+ r = nextRetry;
+ }
+ }
+ }
+ if (complete)
+ throw new IllegalStateException("Closed");
+ else
+ return (drops > 0) ? -drops : lag;
+ }
+
+ /**
+ * Unless already closed, issues {@link
+ * Flow.Subscriber#onComplete() onComplete} signals to current
+ * subscribers, and disallows subsequent attempts to publish.
+ * Upon return, this method does <em>NOT</em> guarantee that all
+ * subscribers have yet completed.
+ */
+ public void close() {
+ if (!closed) {
+ BufferedSubscription<T> b;
+ synchronized (this) {
+ b = clients;
+ clients = null;
+ closed = true;
+ }
+ while (b != null) {
+ BufferedSubscription<T> next = b.next;
+ b.next = null;
+ b.onComplete();
+ b = next;
+ }
+ }
+ }
+
+ /**
+ * Unless already closed, issues {@link
+ * Flow.Subscriber#onError(Throwable) onError} signals to current
+ * subscribers with the given error, and disallows subsequent
+ * attempts to publish. Future subscribers also receive the given
+ * error. Upon return, this method does <em>NOT</em> guarantee
+ * that all subscribers have yet completed.
+ *
+ * @param error the {@code onError} argument sent to subscribers
+ * @throws NullPointerException if error is null
+ */
+ public void closeExceptionally(Throwable error) {
+ if (error == null)
+ throw new NullPointerException();
+ if (!closed) {
+ BufferedSubscription<T> b;
+ synchronized (this) {
+ b = clients;
+ clients = null;
+ closed = true;
+ closedException = error;
+ }
+ while (b != null) {
+ BufferedSubscription<T> next = b.next;
+ b.next = null;
+ b.onError(error);
+ b = next;
+ }
+ }
+ }
+
+ /**
+ * Returns true if this publisher is not accepting submissions.
+ *
+ * @return true if closed
+ */
+ public boolean isClosed() {
+ return closed;
+ }
+
+ /**
+ * Returns the exception associated with {@link
+ * #closeExceptionally(Throwable) closeExceptionally}, or null if
+ * not closed or if closed normally.
+ *
+ * @return the exception, or null if none
+ */
+ public Throwable getClosedException() {
+ return closedException;
+ }
+
+ /**
+ * Returns true if this publisher has any subscribers.
+ *
+ * @return true if this publisher has any subscribers
+ */
+ public boolean hasSubscribers() {
+ boolean nonEmpty = false;
+ if (!closed) {
+ synchronized (this) {
+ for (BufferedSubscription<T> b = clients; b != null;) {
+ BufferedSubscription<T> next = b.next;
+ if (b.isDisabled()) {
+ b.next = null;
+ b = clients = next;
+ }
+ else {
+ nonEmpty = true;
+ break;
+ }
+ }
+ }
+ }
+ return nonEmpty;
+ }
+
+ /**
+ * Returns the number of current subscribers.
+ *
+ * @return the number of current subscribers
+ */
+ public int getNumberOfSubscribers() {
+ int count = 0;
+ if (!closed) {
+ synchronized (this) {
+ BufferedSubscription<T> pred = null, next;
+ for (BufferedSubscription<T> b = clients; b != null; b = next) {
+ next = b.next;
+ if (b.isDisabled()) {
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else {
+ pred = b;
+ ++count;
+ }
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns the Executor used for asynchronous delivery.
+ *
+ * @return the Executor used for asynchronous delivery
+ */
+ public Executor getExecutor() {
+ return executor;
+ }
+
+ /**
+ * Returns the maximum per-subscriber buffer capacity.
+ *
+ * @return the maximum per-subscriber buffer capacity
+ */
+ public int getMaxBufferCapacity() {
+ return maxBufferCapacity;
+ }
+
+ /**
+ * Returns a list of current subscribers for monitoring and
+ * tracking purposes, not for invoking {@link Flow.Subscriber}
+ * methods on the subscribers.
+ *
+ * @return list of current subscribers
+ */
+ public List<Flow.Subscriber<? super T>> getSubscribers() {
+ ArrayList<Flow.Subscriber<? super T>> subs = new ArrayList<>();
+ synchronized (this) {
+ BufferedSubscription<T> pred = null, next;
+ for (BufferedSubscription<T> b = clients; b != null; b = next) {
+ next = b.next;
+ if (b.isDisabled()) {
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else
+ subs.add(b.subscriber);
+ }
+ }
+ return subs;
+ }
+
+ /**
+ * Returns true if the given Subscriber is currently subscribed.
+ *
+ * @param subscriber the subscriber
+ * @return true if currently subscribed
+ * @throws NullPointerException if subscriber is null
+ */
+ public boolean isSubscribed(Flow.Subscriber<? super T> subscriber) {
+ if (subscriber == null) throw new NullPointerException();
+ if (!closed) {
+ synchronized (this) {
+ BufferedSubscription<T> pred = null, next;
+ for (BufferedSubscription<T> b = clients; b != null; b = next) {
+ next = b.next;
+ if (b.isDisabled()) {
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else if (subscriber.equals(b.subscriber))
+ return true;
+ else
+ pred = b;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns an estimate of the minimum number of items requested
+ * (via {@link Flow.Subscription#request(long) request}) but not
+ * yet produced, among all current subscribers.
+ *
+ * @return the estimate, or zero if no subscribers
+ */
+ public long estimateMinimumDemand() {
+ long min = Long.MAX_VALUE;
+ boolean nonEmpty = false;
+ synchronized (this) {
+ BufferedSubscription<T> pred = null, next;
+ for (BufferedSubscription<T> b = clients; b != null; b = next) {
+ int n; long d;
+ next = b.next;
+ if ((n = b.estimateLag()) < 0) {
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else {
+ if ((d = b.demand - n) < min)
+ min = d;
+ nonEmpty = true;
+ pred = b;
+ }
+ }
+ }
+ return nonEmpty ? min : 0;
+ }
+
+ /**
+ * Returns an estimate of the maximum number of items produced but
+ * not yet consumed among all current subscribers.
+ *
+ * @return the estimate
+ */
+ public int estimateMaximumLag() {
+ int max = 0;
+ synchronized (this) {
+ BufferedSubscription<T> pred = null, next;
+ for (BufferedSubscription<T> b = clients; b != null; b = next) {
+ int n;
+ next = b.next;
+ if ((n = b.estimateLag()) < 0) {
+ b.next = null;
+ if (pred == null)
+ clients = next;
+ else
+ pred.next = next;
+ }
+ else {
+ if (n > max)
+ max = n;
+ pred = b;
+ }
+ }
+ }
+ return max;
+ }
+
+ /**
+ * Processes all published items using the given Consumer function.
+ * Returns a CompletableFuture that is completed normally when this
+ * publisher signals {@link Flow.Subscriber#onComplete()
+ * onComplete}, or completed exceptionally upon any error, or an
+ * exception is thrown by the Consumer, or the returned
+ * CompletableFuture is cancelled, in which case no further items
+ * are processed.
+ *
+ * @param consumer the function applied to each onNext item
+ * @return a CompletableFuture that is completed normally
+ * when the publisher signals onComplete, and exceptionally
+ * upon any error or cancellation
+ * @throws NullPointerException if consumer is null
+ */
+ public CompletableFuture<Void> consume(Consumer<? super T> consumer) {
+ if (consumer == null)
+ throw new NullPointerException();
+ CompletableFuture<Void> status = new CompletableFuture<>();
+ subscribe(new ConsumerSubscriber<T>(status, consumer));
+ return status;
+ }
+
+ /** Subscriber for method consume */
+ private static final class ConsumerSubscriber<T>
+ implements Flow.Subscriber<T> {
+ final CompletableFuture<Void> status;
+ final Consumer<? super T> consumer;
+ Flow.Subscription subscription;
+ ConsumerSubscriber(CompletableFuture<Void> status,
+ Consumer<? super T> consumer) {
+ this.status = status; this.consumer = consumer;
+ }
+ public final void onSubscribe(Flow.Subscription subscription) {
+ this.subscription = subscription;
+ status.whenComplete((v, e) -> subscription.cancel());
+ if (!status.isDone())
+ subscription.request(Long.MAX_VALUE);
+ }
+ public final void onError(Throwable ex) {
+ status.completeExceptionally(ex);
+ }
+ public final void onComplete() {
+ status.complete(null);
+ }
+ public final void onNext(T item) {
+ try {
+ consumer.accept(item);
+ } catch (Throwable ex) {
+ subscription.cancel();
+ status.completeExceptionally(ex);
+ }
+ }
+ }
+
+ /**
+ * A task for consuming buffer items and signals, created and
+ * executed whenever they become available. A task consumes as
+ * many items/signals as possible before terminating, at which
+ * point another task is created when needed. The dual Runnable
+ * and ForkJoinTask declaration saves overhead when executed by
+ * ForkJoinPools, without impacting other kinds of Executors.
+ */
+ @SuppressWarnings("serial")
+ static final class ConsumerTask<T> extends ForkJoinTask<Void>
+ implements Runnable {
+ final BufferedSubscription<T> consumer;
+ ConsumerTask(BufferedSubscription<T> consumer) {
+ this.consumer = consumer;
+ }
+ public final Void getRawResult() { return null; }
+ public final void setRawResult(Void v) {}
+ public final boolean exec() { consumer.consume(); return false; }
+ public final void run() { consumer.consume(); }
+ }
+
+ /**
+ * A bounded (ring) buffer with integrated control to start a
+ * consumer task whenever items are available. The buffer
+ * algorithm is similar to one used inside ForkJoinPool (see its
+ * internal documentation for details) specialized for the case of
+ * at most one concurrent producer and consumer, and power of two
+ * buffer sizes. This allows methods to operate without locks even
+ * while supporting resizing, blocking, task-triggering, and
+ * garbage-free buffers (nulling out elements when consumed),
+ * although supporting these does impose a bit of overhead
+ * compared to plain fixed-size ring buffers.
+ *
+ * The publisher guarantees a single producer via its lock. We
+ * ensure in this class that there is at most one consumer. The
+ * request and cancel methods must be fully thread-safe but are
+ * coded to exploit the most common case in which they are only
+ * called by consumers (usually within onNext).
+ *
+ * Execution control is managed using the ACTIVE ctl bit. We
+ * ensure that a task is active when consumable items (and
+ * usually, SUBSCRIBE, ERROR or COMPLETE signals) are present and
+ * there is demand (unfilled requests). This is complicated on
+ * the creation side by the possibility of exceptions when trying
+ * to execute tasks. These eventually force DISABLED state, but
+ * sometimes not directly. On the task side, termination (clearing
+ * ACTIVE) that would otherwise race with producers or request()
+ * calls uses the CONSUME keep-alive bit to force a recheck.
+ *
+ * The ctl field also manages run state. When DISABLED, no further
+ * updates are possible. Disabling may be preceded by setting
+ * ERROR or COMPLETE (or both -- ERROR has precedence), in which
+ * case the associated Subscriber methods are invoked, possibly
+ * synchronously if there is no active consumer task (including
+ * cases where execute() failed). The cancel() method is supported
+ * by treating as ERROR but suppressing onError signal.
+ *
+ * Support for blocking also exploits the fact that there is only
+ * one possible waiter. ManagedBlocker-compatible control fields
+ * are placed in this class itself rather than in wait-nodes.
+ * Blocking control relies on the "waiter" field. Producers set
+ * the field before trying to block, but must then recheck (via
+ * offer) before parking. Signalling then just unparks and clears
+ * waiter field. If the producer and consumer are both in the same
+ * ForkJoinPool, or consumers are running in commonPool, the
+ * producer attempts to help run consumer tasks that it forked
+ * before blocking. To avoid potential cycles, only one level of
+ * helping is currently supported.
+ *
+ * This class uses @Contended and heuristic field declaration
+ * ordering to reduce false-sharing-based memory contention among
+ * instances of BufferedSubscription, but it does not currently
+ * attempt to avoid memory contention among buffers. This field
+ * and element packing can hurt performance especially when each
+ * publisher has only one client operating at a high rate.
+ * Addressing this may require allocating substantially more space
+ * than users expect.
+ */
+ @SuppressWarnings("serial")
+ @sun.misc.Contended
+ private static final class BufferedSubscription<T>
+ implements Flow.Subscription, ForkJoinPool.ManagedBlocker {
+ // Order-sensitive field declarations
+ long timeout; // > 0 if timed wait
+ volatile long demand; // # unfilled requests
+ int maxCapacity; // reduced on OOME
+ int putStat; // offer result for ManagedBlocker
+ int helpDepth; // nested helping depth (at most 1)
+ volatile int ctl; // atomic run state flags
+ volatile int head; // next position to take
+ int tail; // next position to put
+ Object[] array; // buffer: null if disabled
+ Flow.Subscriber<? super T> subscriber; // null if disabled
+ Executor executor; // null if disabled
+ BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> onNextHandler;
+ volatile Throwable pendingError; // holds until onError issued
+ volatile Thread waiter; // blocked producer thread
+ T putItem; // for offer within ManagedBlocker
+ BufferedSubscription<T> next; // used only by publisher
+ BufferedSubscription<T> nextRetry; // used only by publisher
+
+ // ctl values
+ static final int ACTIVE = 0x01; // consumer task active
+ static final int CONSUME = 0x02; // keep-alive for consumer task
+ static final int DISABLED = 0x04; // final state
+ static final int ERROR = 0x08; // signal onError then disable
+ static final int SUBSCRIBE = 0x10; // signal onSubscribe
+ static final int COMPLETE = 0x20; // signal onComplete when done
+
+ static final long INTERRUPTED = -1L; // timeout vs interrupt sentinel
+
+ /**
+ * Initial buffer capacity used when maxBufferCapacity is
+ * greater. Must be a power of two.
+ */
+ static final int DEFAULT_INITIAL_CAP = 32;
+
+ BufferedSubscription(Flow.Subscriber<? super T> subscriber,
+ Executor executor,
+ BiConsumer<? super Flow.Subscriber<? super T>,
+ ? super Throwable> onNextHandler,
+ int maxBufferCapacity) {
+ this.subscriber = subscriber;
+ this.executor = executor;
+ this.onNextHandler = onNextHandler;
+ this.maxCapacity = maxBufferCapacity;
+ this.array = new Object[maxBufferCapacity < DEFAULT_INITIAL_CAP ?
+ (maxBufferCapacity < 2 ? // at least 2 slots
+ 2 : maxBufferCapacity) :
+ DEFAULT_INITIAL_CAP];
+ }
+
+ final boolean isDisabled() {
+ return ctl == DISABLED;
+ }
+
+ /**
+ * Returns estimated number of buffered items, or -1 if
+ * disabled.
+ */
+ final int estimateLag() {
+ int n;
+ return (ctl == DISABLED) ? -1 : ((n = tail - head) > 0) ? n : 0;
+ }
+
+ /**
+ * Tries to add item and start consumer task if necessary.
+ * @return -1 if disabled, 0 if dropped, else estimated lag
+ */
+ final int offer(T item) {
+ int h = head, t = tail, cap, size, stat;
+ Object[] a = array;
+ if (a != null && (cap = a.length) > 0 && cap >= (size = t + 1 - h)) {
+ a[(cap - 1) & t] = item; // relaxed writes OK
+ tail = t + 1;
+ stat = size;
+ }
+ else
+ stat = growAndAdd(a, item);
+ return (stat > 0 &&
+ (ctl & (ACTIVE | CONSUME)) != (ACTIVE | CONSUME)) ?
+ startOnOffer(stat) : stat;
+ }
+
+ /**
+ * Tries to create or expand buffer, then adds item if possible.
+ */
+ private int growAndAdd(Object[] a, T item) {
+ boolean alloc;
+ int cap, stat;
+ if ((ctl & (ERROR | DISABLED)) != 0) {
+ cap = 0;
+ stat = -1;
+ alloc = false;
+ }
+ else if (a == null || (cap = a.length) <= 0) {
+ cap = 0;
+ stat = 1;
+ alloc = true;
+ }
+ else {
+ U.fullFence(); // recheck
+ int h = head, t = tail, size = t + 1 - h;
+ if (cap >= size) {
+ a[(cap - 1) & t] = item;
+ tail = t + 1;
+ stat = size;
+ alloc = false;
+ }
+ else if (cap >= maxCapacity) {
+ stat = 0; // cannot grow
+ alloc = false;
+ }
+ else {
+ stat = cap + 1;
+ alloc = true;
+ }
+ }
+ if (alloc) {
+ int newCap = (cap > 0) ? cap << 1 : 1;
+ if (newCap <= cap)
+ stat = 0;
+ else {
+ Object[] newArray = null;
+ try {
+ newArray = new Object[newCap];
+ } catch (Throwable ex) { // try to cope with OOME
+ }
+ if (newArray == null) {
+ if (cap > 0)
+ maxCapacity = cap; // avoid continuous failure
+ stat = 0;
+ }
+ else {
+ array = newArray;
+ int t = tail;
+ int newMask = newCap - 1;
+ if (a != null && cap > 0) {
+ int mask = cap - 1;
+ for (int j = head; j != t; ++j) {
+ long k = ((long)(j & mask) << ASHIFT) + ABASE;
+ Object x = U.getObjectVolatile(a, k);
+ if (x != null && // races with consumer
+ U.compareAndSwapObject(a, k, x, null))
+ newArray[j & newMask] = x;
+ }
+ }
+ newArray[t & newMask] = item;
+ tail = t + 1;
+ }
+ }
+ }
+ return stat;
+ }
+
+ /**
+ * Spins/helps/blocks while offer returns 0. Called only if
+ * initial offer return 0.
+ */
+ final int submit(T item) {
+ int stat; Executor e; ForkJoinWorkerThread w;
+ if ((stat = offer(item)) == 0 && helpDepth == 0 &&
+ ((e = executor) instanceof ForkJoinPool)) {
+ helpDepth = 1;
+ Thread thread = Thread.currentThread();
+ if ((thread instanceof ForkJoinWorkerThread) &&
+ ((w = (ForkJoinWorkerThread)thread)).getPool() == e)
+ stat = internalHelpConsume(w.workQueue, item);
+ else if (e == ForkJoinPool.commonPool())
+ stat = externalHelpConsume
+ (ForkJoinPool.commonSubmitterQueue(), item);
+ helpDepth = 0;
+ }
+ if (stat == 0 && (stat = offer(item)) == 0) {
+ putItem = item;
+ timeout = 0L;
+ try {
+ ForkJoinPool.managedBlock(this);
+ } catch (InterruptedException ie) {
+ timeout = INTERRUPTED;
+ }
+ stat = putStat;
+ if (timeout < 0L)
+ Thread.currentThread().interrupt();
+ }
+ return stat;
+ }
+
+ /**
+ * Tries helping for FJ submitter.
+ */
+ private int internalHelpConsume(ForkJoinPool.WorkQueue w, T item) {
+ int stat = 0;
+ if (w != null) {
+ ForkJoinTask<?> t;
+ while ((t = w.peek()) != null && (t instanceof ConsumerTask)) {
+ if ((stat = offer(item)) != 0 || !w.tryUnpush(t))
+ break;
+ ((ConsumerTask<?>)t).consumer.consume();
+ }
+ }
+ return stat;
+ }
+
+ /**
+ * Tries helping for non-FJ submitter.
+ */
+ private int externalHelpConsume(ForkJoinPool.WorkQueue w, T item) {
+ int stat = 0;
+ if (w != null) {
+ ForkJoinTask<?> t;
+ while ((t = w.peek()) != null && (t instanceof ConsumerTask)) {
+ if ((stat = offer(item)) != 0 || !w.trySharedUnpush(t))
+ break;
+ ((ConsumerTask<?>)t).consumer.consume();
+ }
+ }
+ return stat;
+ }
+
+ /**
+ * Timeout version; similar to submit.
+ */
+ final int timedOffer(T item, long nanos) {
+ int stat; Executor e;
+ if ((stat = offer(item)) == 0 && helpDepth == 0 &&
+ ((e = executor) instanceof ForkJoinPool)) {
+ Thread thread = Thread.currentThread();
+ if (((thread instanceof ForkJoinWorkerThread) &&
+ ((ForkJoinWorkerThread)thread).getPool() == e) ||
+ e == ForkJoinPool.commonPool()) {
+ helpDepth = 1;
+ ForkJoinTask<?> t;
+ long deadline = System.nanoTime() + nanos;
+ while ((t = ForkJoinTask.peekNextLocalTask()) != null &&
+ (t instanceof ConsumerTask)) {
+ if ((stat = offer(item)) != 0 ||
+ (nanos = deadline - System.nanoTime()) <= 0L ||
+ !t.tryUnfork())
+ break;
+ ((ConsumerTask<?>)t).consumer.consume();
+ }
+ helpDepth = 0;
+ }
+ }
+ if (stat == 0 && (stat = offer(item)) == 0 &&
+ (timeout = nanos) > 0L) {
+ putItem = item;
+ try {
+ ForkJoinPool.managedBlock(this);
+ } catch (InterruptedException ie) {
+ timeout = INTERRUPTED;
+ }
+ stat = putStat;
+ if (timeout < 0L)
+ Thread.currentThread().interrupt();
+ }
+ return stat;
+ }
+
+ /**
+ * Tries to start consumer task after offer.
+ * @return -1 if now disabled, else argument
+ */
+ private int startOnOffer(int stat) {
+ for (;;) {
+ Executor e; int c;
+ if ((c = ctl) == DISABLED || (e = executor) == null) {
+ stat = -1;
+ break;
+ }
+ else if ((c & ACTIVE) != 0) { // ensure keep-alive
+ if ((c & CONSUME) != 0 ||
+ U.compareAndSwapInt(this, CTL, c,
+ c | CONSUME))
+ break;
+ }
+ else if (demand == 0L || tail == head)
+ break;
+ else if (U.compareAndSwapInt(this, CTL, c,
+ c | (ACTIVE | CONSUME))) {
+ try {
+ e.execute(new ConsumerTask<T>(this));
+ break;
+ } catch (RuntimeException | Error ex) { // back out
+ do {} while (((c = ctl) & DISABLED) == 0 &&
+ (c & ACTIVE) != 0 &&
+ !U.compareAndSwapInt(this, CTL, c,
+ c & ~ACTIVE));
+ throw ex;
+ }
+ }
+ }
+ return stat;
+ }
+
+ private void signalWaiter(Thread w) {
+ waiter = null;
+ LockSupport.unpark(w); // release producer
+ }
+
+ /**
+ * Nulls out most fields, mainly to avoid garbage retention
+ * until publisher unsubscribes, but also to help cleanly stop
+ * upon error by nulling required components.
+ */
+ private void detach() {
+ Thread w = waiter;
+ executor = null;
+ subscriber = null;
+ pendingError = null;
+ signalWaiter(w);
+ }
+
+ /**
+ * Issues error signal, asynchronously if a task is running,
+ * else synchronously.
+ */
+ final void onError(Throwable ex) {
+ for (int c;;) {
+ if (((c = ctl) & (ERROR | DISABLED)) != 0)
+ break;
+ else if ((c & ACTIVE) != 0) {
+ pendingError = ex;
+ if (U.compareAndSwapInt(this, CTL, c, c | ERROR))
+ break; // cause consumer task to exit
+ }
+ else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+ Flow.Subscriber<? super T> s = subscriber;
+ if (s != null && ex != null) {
+ try {
+ s.onError(ex);
+ } catch (Throwable ignore) {
+ }
+ }
+ detach();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Tries to start consumer task upon a signal or request;
+ * disables on failure.
+ */
+ private void startOrDisable() {
+ Executor e;
+ if ((e = executor) != null) { // skip if already disabled
+ try {
+ e.execute(new ConsumerTask<T>(this));
+ } catch (Throwable ex) { // back out and force signal
+ for (int c;;) {
+ if ((c = ctl) == DISABLED || (c & ACTIVE) == 0)
+ break;
+ if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE)) {
+ onError(ex);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ final void onComplete() {
+ for (int c;;) {
+ if ((c = ctl) == DISABLED)
+ break;
+ if (U.compareAndSwapInt(this, CTL, c,
+ c | (ACTIVE | CONSUME | COMPLETE))) {
+ if ((c & ACTIVE) == 0)
+ startOrDisable();
+ break;
+ }
+ }
+ }
+
+ final void onSubscribe() {
+ for (int c;;) {
+ if ((c = ctl) == DISABLED)
+ break;
+ if (U.compareAndSwapInt(this, CTL, c,
+ c | (ACTIVE | CONSUME | SUBSCRIBE))) {
+ if ((c & ACTIVE) == 0)
+ startOrDisable();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Causes consumer task to exit if active (without reporting
+ * onError unless there is already a pending error), and
+ * disables.
+ */
+ public void cancel() {
+ for (int c;;) {
+ if ((c = ctl) == DISABLED)
+ break;
+ else if ((c & ACTIVE) != 0) {
+ if (U.compareAndSwapInt(this, CTL, c,
+ c | (CONSUME | ERROR)))
+ break;
+ }
+ else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+ detach();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Adds to demand and possibly starts task.
+ */
+ public void request(long n) {
+ if (n > 0L) {
+ for (;;) {
+ long prev = demand, d;
+ if ((d = prev + n) < prev) // saturate
+ d = Long.MAX_VALUE;
+ if (U.compareAndSwapLong(this, DEMAND, prev, d)) {
+ for (int c, h;;) {
+ if ((c = ctl) == DISABLED)
+ break;
+ else if ((c & ACTIVE) != 0) {
+ if ((c & CONSUME) != 0 ||
+ U.compareAndSwapInt(this, CTL, c,
+ c | CONSUME))
+ break;
+ }
+ else if ((h = head) != tail) {
+ if (U.compareAndSwapInt(this, CTL, c,
+ c | (ACTIVE|CONSUME))) {
+ startOrDisable();
+ break;
+ }
+ }
+ else if (head == h && tail == h)
+ break; // else stale
+ if (demand == 0L)
+ break;
+ }
+ break;
+ }
+ }
+ }
+ else if (n < 0L)
+ onError(new IllegalArgumentException(
+ "negative subscription request"));
+ }
+
+ public final boolean isReleasable() { // for ManagedBlocker
+ T item = putItem;
+ if (item != null) {
+ if ((putStat = offer(item)) == 0)
+ return false;
+ putItem = null;
+ }
+ return true;
+ }
+
+ public final boolean block() { // for ManagedBlocker
+ T item = putItem;
+ if (item != null) {
+ putItem = null;
+ long nanos = timeout;
+ long deadline = (nanos > 0L) ? System.nanoTime() + nanos : 0L;
+ while ((putStat = offer(item)) == 0) {
+ if (Thread.interrupted()) {
+ timeout = INTERRUPTED;
+ if (nanos > 0L)
+ break;
+ }
+ else if (nanos > 0L &&
+ (nanos = deadline - System.nanoTime()) <= 0L)
+ break;
+ else if (waiter == null)
+ waiter = Thread.currentThread();
+ else {
+ if (nanos > 0L)
+ LockSupport.parkNanos(this, nanos);
+ else
+ LockSupport.park(this);
+ waiter = null;
+ }
+ }
+ }
+ waiter = null;
+ return true;
+ }
+
+ /**
+ * Consumer loop, called from ConsumerTask, or indirectly
+ * when helping during submit.
+ */
+ final void consume() {
+ Flow.Subscriber<? super T> s;
+ int h = head;
+ if ((s = subscriber) != null) { // else disabled
+ for (;;) {
+ long d = demand;
+ int c; Object[] a; int n; long i; Object x; Thread w;
+ if (((c = ctl) & (ERROR | SUBSCRIBE | DISABLED)) != 0) {
+ if (!checkControl(s, c))
+ break;
+ }
+ else if ((a = array) == null || h == tail ||
+ (n = a.length) == 0 ||
+ (x = U.getObjectVolatile
+ (a, (i = ((long)((n - 1) & h) << ASHIFT) + ABASE)))
+ == null) {
+ if (!checkEmpty(s, c))
+ break;
+ }
+ else if (d == 0L) {
+ if (!checkDemand(c))
+ break;
+ }
+ else if (((c & CONSUME) != 0 ||
+ U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
+ U.compareAndSwapObject(a, i, x, null)) {
+ U.putOrderedInt(this, HEAD, ++h);
+ U.getAndAddLong(this, DEMAND, -1L);
+ if ((w = waiter) != null)
+ signalWaiter(w);
+ try {
+ @SuppressWarnings("unchecked") T y = (T) x;
+ s.onNext(y);
+ } catch (Throwable ex) {
+ handleOnNext(s, ex);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Responds to control events in consume().
+ */
+ private boolean checkControl(Flow.Subscriber<? super T> s, int c) {
+ boolean stat = true;
+ if ((c & ERROR) != 0) {
+ Throwable ex = pendingError;
+ ctl = DISABLED; // no need for CAS
+ if (ex != null) { // null if errorless cancel
+ try {
+ if (s != null)
+ s.onError(ex);
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+ else if ((c & SUBSCRIBE) != 0) {
+ if (U.compareAndSwapInt(this, CTL, c, c & ~SUBSCRIBE)) {
+ try {
+ if (s != null)
+ s.onSubscribe(this);
+ } catch (Throwable ex) {
+ onError(ex);
+ }
+ }
+ }
+ else {
+ detach();
+ stat = false;
+ }
+ return stat;
+ }
+
+ /**
+ * Responds to apparent emptiness in consume().
+ */
+ private boolean checkEmpty(Flow.Subscriber<? super T> s, int c) {
+ boolean stat = true;
+ if (head == tail) {
+ if ((c & CONSUME) != 0)
+ U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
+ else if ((c & COMPLETE) != 0) {
+ if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+ try {
+ if (s != null)
+ s.onComplete();
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+ else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE))
+ stat = false;
+ }
+ return stat;
+ }
+
+ /**
+ * Responds to apparent zero demand in consume().
+ */
+ private boolean checkDemand(int c) {
+ boolean stat = true;
+ if (demand == 0L) {
+ if ((c & CONSUME) != 0)
+ U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
+ else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE))
+ stat = false;
+ }
+ return stat;
+ }
+
+ /**
+ * Processes exception in Subscriber.onNext.
+ */
+ private void handleOnNext(Flow.Subscriber<? super T> s, Throwable ex) {
+ BiConsumer<? super Flow.Subscriber<? super T>, ? super Throwable> h;
+ if ((h = onNextHandler) != null) {
+ try {
+ h.accept(s, ex);
+ } catch (Throwable ignore) {
+ }
+ }
+ onError(ex);
+ }
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long CTL;
+ private static final long TAIL;
+ private static final long HEAD;
+ private static final long DEMAND;
+ private static final int ABASE;
+ private static final int ASHIFT;
+
+ static {
+ try {
+ CTL = U.objectFieldOffset
+ (BufferedSubscription.class.getDeclaredField("ctl"));
+ TAIL = U.objectFieldOffset
+ (BufferedSubscription.class.getDeclaredField("tail"));
+ HEAD = U.objectFieldOffset
+ (BufferedSubscription.class.getDeclaredField("head"));
+ DEMAND = U.objectFieldOffset
+ (BufferedSubscription.class.getDeclaredField("demand"));
+
+ ABASE = U.arrayBaseOffset(Object[].class);
+ int scale = U.arrayIndexScale(Object[].class);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
+ }
+ }
+}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,11 +35,15 @@
*/
package java.util.concurrent;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.*;
-import java.util.Spliterator;
-import java.util.Spliterators;
/**
* A {@linkplain BlockingQueue blocking queue} in which each insert
@@ -79,7 +83,7 @@
*
* @since 1.5
* @author Doug Lea and Bill Scherer and Michael Scott
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public class SynchronousQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
@@ -182,9 +186,6 @@
abstract E transfer(E e, boolean timed, long nanos);
}
- /** The number of CPUs, for spin control */
- static final int NCPUS = Runtime.getRuntime().availableProcessors();
-
/**
* The number of times to spin before blocking in timed waits.
* The value is empirically derived -- it works well across a
@@ -192,20 +193,21 @@
* seems not to vary with number of CPUs (beyond 2) so is just
* a constant.
*/
- static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32;
+ static final int MAX_TIMED_SPINS =
+ (Runtime.getRuntime().availableProcessors() < 2) ? 0 : 32;
/**
* The number of times to spin before blocking in untimed waits.
* This is greater than timed value because untimed waits spin
* faster since they don't need to check times on each spin.
*/
- static final int maxUntimedSpins = maxTimedSpins * 16;
+ static final int MAX_UNTIMED_SPINS = MAX_TIMED_SPINS * 16;
/**
* The number of nanoseconds for which it is faster to spin
* rather than to use timed park. A rough estimate suffices.
*/
- static final long spinForTimeoutThreshold = 1000L;
+ static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
/** Dual stack */
static final class TransferStack<E> extends Transferer<E> {
@@ -245,7 +247,7 @@
boolean casNext(SNode cmp, SNode val) {
return cmp == next &&
- UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+ U.compareAndSwapObject(this, NEXT, cmp, val);
}
/**
@@ -258,7 +260,7 @@
*/
boolean tryMatch(SNode s) {
if (match == null &&
- UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) {
+ U.compareAndSwapObject(this, MATCH, null, s)) {
Thread w = waiter;
if (w != null) { // waiters need at most one unpark
waiter = null;
@@ -273,7 +275,7 @@
* Tries to cancel a wait by matching node to itself.
*/
void tryCancel() {
- UNSAFE.compareAndSwapObject(this, matchOffset, null, this);
+ U.compareAndSwapObject(this, MATCH, null, this);
}
boolean isCancelled() {
@@ -281,19 +283,17 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long matchOffset;
- private static final long nextOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long MATCH;
+ private static final long NEXT;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = SNode.class;
- matchOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("match"));
- nextOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("next"));
- } catch (Exception e) {
+ MATCH = U.objectFieldOffset
+ (SNode.class.getDeclaredField("match"));
+ NEXT = U.objectFieldOffset
+ (SNode.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -304,7 +304,7 @@
boolean casHead(SNode h, SNode nh) {
return h == head &&
- UNSAFE.compareAndSwapObject(this, headOffset, h, nh);
+ U.compareAndSwapObject(this, HEAD, h, nh);
}
/**
@@ -353,7 +353,7 @@
for (;;) {
SNode h = head;
if (h == null || h.mode == mode) { // empty or same-mode
- if (timed && nanos <= 0) { // can't wait
+ if (timed && nanos <= 0L) { // can't wait
if (h != null && h.isCancelled())
casHead(h, h.next); // pop cancelled node
else
@@ -435,8 +435,9 @@
*/
final long deadline = timed ? System.nanoTime() + nanos : 0L;
Thread w = Thread.currentThread();
- int spins = (shouldSpin(s) ?
- (timed ? maxTimedSpins : maxUntimedSpins) : 0);
+ int spins = shouldSpin(s)
+ ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
+ : 0;
for (;;) {
if (w.isInterrupted())
s.tryCancel();
@@ -451,12 +452,12 @@
}
}
if (spins > 0)
- spins = shouldSpin(s) ? (spins-1) : 0;
+ spins = shouldSpin(s) ? (spins - 1) : 0;
else if (s.waiter == null)
s.waiter = w; // establish waiter so can park next iter
else if (!timed)
LockSupport.park(this);
- else if (nanos > spinForTimeoutThreshold)
+ else if (nanos > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanos);
}
}
@@ -508,15 +509,13 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long headOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long HEAD;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = TransferStack.class;
- headOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("head"));
- } catch (Exception e) {
+ HEAD = U.objectFieldOffset
+ (TransferStack.class.getDeclaredField("head"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -547,19 +546,19 @@
boolean casNext(QNode cmp, QNode val) {
return next == cmp &&
- UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
+ U.compareAndSwapObject(this, NEXT, cmp, val);
}
boolean casItem(Object cmp, Object val) {
return item == cmp &&
- UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
+ U.compareAndSwapObject(this, ITEM, cmp, val);
}
/**
* Tries to cancel by CAS'ing ref to this as item.
*/
void tryCancel(Object cmp) {
- UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this);
+ U.compareAndSwapObject(this, ITEM, cmp, this);
}
boolean isCancelled() {
@@ -576,19 +575,17 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long itemOffset;
- private static final long nextOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long ITEM;
+ private static final long NEXT;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = QNode.class;
- itemOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("item"));
- nextOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("next"));
- } catch (Exception e) {
+ ITEM = U.objectFieldOffset
+ (QNode.class.getDeclaredField("item"));
+ NEXT = U.objectFieldOffset
+ (QNode.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -617,7 +614,7 @@
*/
void advanceHead(QNode h, QNode nh) {
if (h == head &&
- UNSAFE.compareAndSwapObject(this, headOffset, h, nh))
+ U.compareAndSwapObject(this, HEAD, h, nh))
h.next = h; // forget old next
}
@@ -626,7 +623,7 @@
*/
void advanceTail(QNode t, QNode nt) {
if (tail == t)
- UNSAFE.compareAndSwapObject(this, tailOffset, t, nt);
+ U.compareAndSwapObject(this, TAIL, t, nt);
}
/**
@@ -634,7 +631,7 @@
*/
boolean casCleanMe(QNode cmp, QNode val) {
return cleanMe == cmp &&
- UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
+ U.compareAndSwapObject(this, CLEANME, cmp, val);
}
/**
@@ -684,7 +681,7 @@
advanceTail(t, tn);
continue;
}
- if (timed && nanos <= 0) // can't wait
+ if (timed && nanos <= 0L) // can't wait
return null;
if (s == null)
s = new QNode(e, isData);
@@ -739,8 +736,9 @@
/* Same idea as TransferStack.awaitFulfill */
final long deadline = timed ? System.nanoTime() + nanos : 0L;
Thread w = Thread.currentThread();
- int spins = ((head.next == s) ?
- (timed ? maxTimedSpins : maxUntimedSpins) : 0);
+ int spins = (head.next == s)
+ ? (timed ? MAX_TIMED_SPINS : MAX_UNTIMED_SPINS)
+ : 0;
for (;;) {
if (w.isInterrupted())
s.tryCancel(e);
@@ -760,7 +758,7 @@
s.waiter = w;
else if (!timed)
LockSupport.park(this);
- else if (nanos > spinForTimeoutThreshold)
+ else if (nanos > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanos);
}
}
@@ -819,21 +817,19 @@
}
}
- private static final sun.misc.Unsafe UNSAFE;
- private static final long headOffset;
- private static final long tailOffset;
- private static final long cleanMeOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long HEAD;
+ private static final long TAIL;
+ private static final long CLEANME;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> k = TransferQueue.class;
- headOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("head"));
- tailOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("tail"));
- cleanMeOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("cleanMe"));
- } catch (Exception e) {
+ HEAD = U.objectFieldOffset
+ (TransferQueue.class.getDeclaredField("head"));
+ TAIL = U.objectFieldOffset
+ (TransferQueue.class.getDeclaredField("tail"));
+ CLEANME = U.objectFieldOffset
+ (TransferQueue.class.getDeclaredField("cleanMe"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
@@ -1088,7 +1084,7 @@
}
/**
- * Sets the zeroeth element of the specified array to {@code null}
+ * Sets the zeroth element of the specified array to {@code null}
* (if the array has non-zero length) and returns it.
*
* @param a the array
@@ -1102,6 +1098,14 @@
}
/**
+ * Always returns {@code "[]"}.
+ * @return {@code "[]"}
+ */
+ public String toString() {
+ return "[]";
+ }
+
+ /**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
@@ -1196,17 +1200,9 @@
transferer = new TransferStack<E>();
}
- // Unsafe mechanics
- static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
- String field, Class<?> klazz) {
- try {
- return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
- } catch (NoSuchFieldException e) {
- // Convert Exception to corresponding Error
- NoSuchFieldError error = new NoSuchFieldError(field);
- error.initCause(e);
- throw error;
- }
+ static {
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
-
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -42,7 +42,7 @@
*
* <p>
* The simplest implementation of this interface is just:
- * <pre> {@code
+ * <pre> {@code
* class SimpleThreadFactory implements ThreadFactory {
* public Thread newThread(Runnable r) {
* return new Thread(r);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java Tue Oct 20 08:24:37 2015 -0700
@@ -126,8 +126,7 @@
*/
/** Generates per-thread initialization/probe field */
- private static final AtomicInteger probeGenerator =
- new AtomicInteger();
+ private static final AtomicInteger probeGenerator = new AtomicInteger();
/**
* The next seed for default constructors.
@@ -150,17 +149,17 @@
}
/**
- * The seed increment
+ * The seed increment.
*/
private static final long GAMMA = 0x9e3779b97f4a7c15L;
/**
- * The increment for generating probe values
+ * The increment for generating probe values.
*/
private static final int PROBE_INCREMENT = 0x9e3779b9;
/**
- * The increment of seeder per new instance
+ * The increment of seeder per new instance.
*/
private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL;
@@ -170,7 +169,7 @@
/** Rarely-used holder for the second of a pair of Gaussians */
private static final ThreadLocal<Double> nextLocalGaussian =
- new ThreadLocal<Double>();
+ new ThreadLocal<>();
private static long mix64(long z) {
z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL;
@@ -209,8 +208,8 @@
int probe = (p == 0) ? 1 : p; // skip 0
long seed = mix64(seeder.getAndAdd(SEEDER_INCREMENT));
Thread t = Thread.currentThread();
- UNSAFE.putLong(t, SEED, seed);
- UNSAFE.putInt(t, PROBE, probe);
+ U.putLong(t, SEED, seed);
+ U.putInt(t, PROBE, probe);
}
/**
@@ -219,7 +218,7 @@
* @return the current thread's {@code ThreadLocalRandom}
*/
public static ThreadLocalRandom current() {
- if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
+ if (U.getInt(Thread.currentThread(), PROBE) == 0)
localInit();
return instance;
}
@@ -238,8 +237,8 @@
final long nextSeed() {
Thread t; long r; // read and update per-thread seed
- UNSAFE.putLong(t = Thread.currentThread(), SEED,
- r = UNSAFE.getLong(t, SEED) + GAMMA);
+ U.putLong(t = Thread.currentThread(), SEED,
+ r = U.getLong(t, SEED) + GAMMA);
return r;
}
@@ -249,9 +248,9 @@
}
// IllegalArgumentException messages
- static final String BadBound = "bound must be positive";
- static final String BadRange = "bound must be greater than origin";
- static final String BadSize = "size must be non-negative";
+ static final String BAD_BOUND = "bound must be positive";
+ static final String BAD_RANGE = "bound must be greater than origin";
+ static final String BAD_SIZE = "size must be non-negative";
/**
* The form of nextLong used by LongStream Spliterators. If
@@ -349,7 +348,7 @@
*/
public int nextInt(int bound) {
if (bound <= 0)
- throw new IllegalArgumentException(BadBound);
+ throw new IllegalArgumentException(BAD_BOUND);
int r = mix32(nextSeed());
int m = bound - 1;
if ((bound & m) == 0) // power of two
@@ -376,7 +375,7 @@
*/
public int nextInt(int origin, int bound) {
if (origin >= bound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return internalNextInt(origin, bound);
}
@@ -400,7 +399,7 @@
*/
public long nextLong(long bound) {
if (bound <= 0)
- throw new IllegalArgumentException(BadBound);
+ throw new IllegalArgumentException(BAD_BOUND);
long r = mix64(nextSeed());
long m = bound - 1;
if ((bound & m) == 0L) // power of two
@@ -427,7 +426,7 @@
*/
public long nextLong(long origin, long bound) {
if (origin >= bound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return internalNextLong(origin, bound);
}
@@ -453,9 +452,9 @@
*/
public double nextDouble(double bound) {
if (!(bound > 0.0))
- throw new IllegalArgumentException(BadBound);
+ throw new IllegalArgumentException(BAD_BOUND);
double result = (mix64(nextSeed()) >>> 11) * DOUBLE_UNIT * bound;
- return (result < bound) ? result : // correct for rounding
+ return (result < bound) ? result : // correct for rounding
Double.longBitsToDouble(Double.doubleToLongBits(bound) - 1);
}
@@ -472,7 +471,7 @@
*/
public double nextDouble(double origin, double bound) {
if (!(origin < bound))
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return internalNextDouble(origin, bound);
}
@@ -529,7 +528,7 @@
*/
public IntStream ints(long streamSize) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, streamSize, Integer.MAX_VALUE, 0),
@@ -571,9 +570,9 @@
public IntStream ints(long streamSize, int randomNumberOrigin,
int randomNumberBound) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -598,7 +597,7 @@
*/
public IntStream ints(int randomNumberOrigin, int randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.intStream
(new RandomIntsSpliterator
(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -617,7 +616,7 @@
*/
public LongStream longs(long streamSize) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, streamSize, Long.MAX_VALUE, 0L),
@@ -659,9 +658,9 @@
public LongStream longs(long streamSize, long randomNumberOrigin,
long randomNumberBound) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -686,7 +685,7 @@
*/
public LongStream longs(long randomNumberOrigin, long randomNumberBound) {
if (randomNumberOrigin >= randomNumberBound)
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.longStream
(new RandomLongsSpliterator
(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -706,7 +705,7 @@
*/
public DoubleStream doubles(long streamSize) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, streamSize, Double.MAX_VALUE, 0.0),
@@ -750,9 +749,9 @@
public DoubleStream doubles(long streamSize, double randomNumberOrigin,
double randomNumberBound) {
if (streamSize < 0L)
- throw new IllegalArgumentException(BadSize);
+ throw new IllegalArgumentException(BAD_SIZE);
if (!(randomNumberOrigin < randomNumberBound))
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, streamSize, randomNumberOrigin, randomNumberBound),
@@ -777,7 +776,7 @@
*/
public DoubleStream doubles(double randomNumberOrigin, double randomNumberBound) {
if (!(randomNumberOrigin < randomNumberBound))
- throw new IllegalArgumentException(BadRange);
+ throw new IllegalArgumentException(BAD_RANGE);
return StreamSupport.doubleStream
(new RandomDoublesSpliterator
(0L, Long.MAX_VALUE, randomNumberOrigin, randomNumberBound),
@@ -792,7 +791,8 @@
* approach. The long and double versions of this class are
* identical except for types.
*/
- static final class RandomIntsSpliterator implements Spliterator.OfInt {
+ private static final class RandomIntsSpliterator
+ implements Spliterator.OfInt {
long index;
final long fence;
final int origin;
@@ -846,7 +846,8 @@
/**
* Spliterator for long streams.
*/
- static final class RandomLongsSpliterator implements Spliterator.OfLong {
+ private static final class RandomLongsSpliterator
+ implements Spliterator.OfLong {
long index;
final long fence;
final long origin;
@@ -901,7 +902,8 @@
/**
* Spliterator for double streams.
*/
- static final class RandomDoublesSpliterator implements Spliterator.OfDouble {
+ private static final class RandomDoublesSpliterator
+ implements Spliterator.OfDouble {
long index;
final long fence;
final double origin;
@@ -978,7 +980,7 @@
* can be used to force initialization on zero return.
*/
static final int getProbe() {
- return UNSAFE.getInt(Thread.currentThread(), PROBE);
+ return U.getInt(Thread.currentThread(), PROBE);
}
/**
@@ -989,7 +991,7 @@
probe ^= probe << 13; // xorshift
probe ^= probe >>> 17;
probe ^= probe << 5;
- UNSAFE.putInt(Thread.currentThread(), PROBE, probe);
+ U.putInt(Thread.currentThread(), PROBE, probe);
return probe;
}
@@ -999,17 +1001,14 @@
static final int nextSecondarySeed() {
int r;
Thread t = Thread.currentThread();
- if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
+ if ((r = U.getInt(t, SECONDARY)) != 0) {
r ^= r << 13; // xorshift
r ^= r >>> 17;
r ^= r << 5;
}
- else {
- localInit();
- if ((r = (int)UNSAFE.getLong(t, SEED)) == 0)
- r = 1; // avoid zero
- }
- UNSAFE.putInt(t, SECONDARY, r);
+ else if ((r = mix32(seeder.getAndAdd(SEEDER_INCREMENT))) == 0)
+ r = 1; // avoid zero
+ U.putInt(t, SECONDARY, r);
return r;
}
@@ -1024,8 +1023,8 @@
* always true
*/
private static final ObjectStreamField[] serialPersistentFields = {
- new ObjectStreamField("rnd", long.class),
- new ObjectStreamField("initialized", boolean.class),
+ new ObjectStreamField("rnd", long.class),
+ new ObjectStreamField("initialized", boolean.class),
};
/**
@@ -1037,7 +1036,7 @@
throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields();
- fields.put("rnd", UNSAFE.getLong(Thread.currentThread(), SEED));
+ fields.put("rnd", U.getLong(Thread.currentThread(), SEED));
fields.put("initialized", true);
s.writeFields();
}
@@ -1051,21 +1050,19 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> tk = Thread.class;
- SEED = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomSeed"));
- PROBE = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomProbe"));
- SECONDARY = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
- } catch (Exception e) {
+ SEED = U.objectFieldOffset
+ (Thread.class.getDeclaredField("threadLocalRandomSeed"));
+ PROBE = U.objectFieldOffset
+ (Thread.class.getDeclaredField("threadLocalRandomProbe"));
+ SECONDARY = U.objectFieldOffset
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadPoolExecutor.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,11 +34,16 @@
*/
package java.util.concurrent;
+
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.*;
/**
* An {@link ExecutorService} that executes each submitted task using
@@ -69,7 +74,8 @@
*
* <dt>Core and maximum pool sizes</dt>
*
- * <dd>A {@code ThreadPoolExecutor} will automatically adjust the
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * A {@code ThreadPoolExecutor} will automatically adjust the
* pool size (see {@link #getPoolSize})
* according to the bounds set by
* corePoolSize (see {@link #getCorePoolSize}) and
@@ -91,7 +97,8 @@
*
* <dt>On-demand construction</dt>
*
- * <dd>By default, even core threads are initially created and
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * By default, even core threads are initially created and
* started only when new tasks arrive, but this can be overridden
* dynamically using method {@link #prestartCoreThread} or {@link
* #prestartAllCoreThreads}. You probably want to prestart threads if
@@ -99,7 +106,8 @@
*
* <dt>Creating new threads</dt>
*
- * <dd>New threads are created using a {@link ThreadFactory}. If not
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * New threads are created using a {@link ThreadFactory}. If not
* otherwise specified, a {@link Executors#defaultThreadFactory} is
* used, that creates threads to all be in the same {@link
* ThreadGroup} and with the same {@code NORM_PRIORITY} priority and
@@ -116,7 +124,8 @@
*
* <dt>Keep-alive times</dt>
*
- * <dd>If the pool currently has more than corePoolSize threads,
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * If the pool currently has more than corePoolSize threads,
* excess threads will be terminated if they have been idle for more
* than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}).
* This provides a means of reducing resource consumption when the
@@ -126,36 +135,37 @@
* TimeUnit)}. Using a value of {@code Long.MAX_VALUE} {@link
* TimeUnit#NANOSECONDS} effectively disables idle threads from ever
* terminating prior to shut down. By default, the keep-alive policy
- * applies only when there are more than corePoolSize threads. But
+ * applies only when there are more than corePoolSize threads, but
* method {@link #allowCoreThreadTimeOut(boolean)} can be used to
* apply this time-out policy to core threads as well, so long as the
* keepAliveTime value is non-zero. </dd>
*
* <dt>Queuing</dt>
*
- * <dd>Any {@link BlockingQueue} may be used to transfer and hold
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * Any {@link BlockingQueue} may be used to transfer and hold
* submitted tasks. The use of this queue interacts with pool sizing:
*
* <ul>
*
- * <li> If fewer than corePoolSize threads are running, the Executor
+ * <li>If fewer than corePoolSize threads are running, the Executor
* always prefers adding a new thread
- * rather than queuing.</li>
+ * rather than queuing.
*
- * <li> If corePoolSize or more threads are running, the Executor
+ * <li>If corePoolSize or more threads are running, the Executor
* always prefers queuing a request rather than adding a new
- * thread.</li>
+ * thread.
*
- * <li> If a request cannot be queued, a new thread is created unless
+ * <li>If a request cannot be queued, a new thread is created unless
* this would exceed maximumPoolSize, in which case, the task will be
- * rejected.</li>
+ * rejected.
*
* </ul>
*
* There are three general strategies for queuing:
* <ol>
*
- * <li> <em> Direct handoffs.</em> A good default choice for a work
+ * <li><em> Direct handoffs.</em> A good default choice for a work
* queue is a {@link SynchronousQueue} that hands off tasks to threads
* without otherwise holding them. Here, an attempt to queue a task
* will fail if no threads are immediately available to run it, so a
@@ -164,7 +174,7 @@
* Direct handoffs generally require unbounded maximumPoolSizes to
* avoid rejection of new submitted tasks. This in turn admits the
* possibility of unbounded thread growth when commands continue to
- * arrive on average faster than they can be processed. </li>
+ * arrive on average faster than they can be processed.
*
* <li><em> Unbounded queues.</em> Using an unbounded queue (for
* example a {@link LinkedBlockingQueue} without a predefined
@@ -177,7 +187,7 @@
* While this style of queuing can be useful in smoothing out
* transient bursts of requests, it admits the possibility of
* unbounded work queue growth when commands continue to arrive on
- * average faster than they can be processed. </li>
+ * average faster than they can be processed.
*
* <li><em>Bounded queues.</em> A bounded queue (for example, an
* {@link ArrayBlockingQueue}) helps prevent resource exhaustion when
@@ -190,7 +200,7 @@
* time for more threads than you otherwise allow. Use of small queues
* generally requires larger pool sizes, which keeps CPUs busier but
* may encounter unacceptable scheduling overhead, which also
- * decreases throughput. </li>
+ * decreases throughput.
*
* </ol>
*
@@ -198,7 +208,8 @@
*
* <dt>Rejected tasks</dt>
*
- * <dd>New tasks submitted in method {@link #execute(Runnable)} will be
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * New tasks submitted in method {@link #execute(Runnable)} will be
* <em>rejected</em> when the Executor has been shut down, and also when
* the Executor uses finite bounds for both maximum threads and work queue
* capacity, and is saturated. In either case, the {@code execute} method
@@ -209,22 +220,22 @@
*
* <ol>
*
- * <li> In the default {@link ThreadPoolExecutor.AbortPolicy}, the
+ * <li>In the default {@link ThreadPoolExecutor.AbortPolicy}, the
* handler throws a runtime {@link RejectedExecutionException} upon
- * rejection. </li>
+ * rejection.
*
- * <li> In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
+ * <li>In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
* that invokes {@code execute} itself runs the task. This provides a
* simple feedback control mechanism that will slow down the rate that
- * new tasks are submitted. </li>
+ * new tasks are submitted.
*
- * <li> In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
- * cannot be executed is simply dropped. </li>
+ * <li>In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
+ * cannot be executed is simply dropped.
*
* <li>In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the
* executor is not shut down, the task at the head of the work queue
* is dropped, and then execution is retried (which can fail again,
- * causing this to be repeated.) </li>
+ * causing this to be repeated.)
*
* </ol>
*
@@ -235,7 +246,8 @@
*
* <dt>Hook methods</dt>
*
- * <dd>This class provides {@code protected} overridable
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * This class provides {@code protected} overridable
* {@link #beforeExecute(Thread, Runnable)} and
* {@link #afterExecute(Runnable, Throwable)} methods that are called
* before and after execution of each task. These can be used to
@@ -245,12 +257,14 @@
* any special processing that needs to be done once the Executor has
* fully terminated.
*
- * <p>If hook or callback methods throw exceptions, internal worker
- * threads may in turn fail and abruptly terminate.</dd>
+ * <p>If hook, callback, or BlockingQueue methods throw exceptions,
+ * internal worker threads may in turn fail, abruptly terminate, and
+ * possibly be replaced.</dd>
*
* <dt>Queue maintenance</dt>
*
- * <dd>Method {@link #getQueue()} allows access to the work queue
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * Method {@link #getQueue()} allows access to the work queue
* for purposes of monitoring and debugging. Use of this method for
* any other purpose is strongly discouraged. Two supplied methods,
* {@link #remove(Runnable)} and {@link #purge} are available to
@@ -259,7 +273,8 @@
*
* <dt>Finalization</dt>
*
- * <dd>A pool that is no longer referenced in a program <em>AND</em>
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * A pool that is no longer referenced in a program <em>AND</em>
* has no remaining threads will be {@code shutdown} automatically. If
* you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange
@@ -273,7 +288,7 @@
* override one or more of the protected hook methods. For example,
* here is a subclass that adds a simple pause/resume feature:
*
- * <pre> {@code
+ * <pre> {@code
* class PausableThreadPoolExecutor extends ThreadPoolExecutor {
* private boolean isPaused;
* private ReentrantLock pauseLock = new ReentrantLock();
@@ -462,10 +477,10 @@
* Set containing all worker threads in pool. Accessed only when
* holding mainLock.
*/
- private final HashSet<Worker> workers = new HashSet<Worker>();
+ private final HashSet<Worker> workers = new HashSet<>();
/**
- * Wait condition to support awaitTermination
+ * Wait condition to support awaitTermination.
*/
private final Condition termination = mainLock.newCondition();
@@ -541,7 +556,7 @@
private volatile int maximumPoolSize;
/**
- * The default rejected execution handler
+ * The default rejected execution handler.
*/
private static final RejectedExecutionHandler defaultHandler =
new AbortPolicy();
@@ -612,7 +627,7 @@
this.thread = getThreadFactory().newThread(this);
}
- /** Delegates main run loop to outer runWorker */
+ /** Delegates main run loop to outer runWorker. */
public void run() {
runWorker(this);
}
@@ -668,6 +683,7 @@
* (but not TIDYING or TERMINATED -- use tryTerminate for that)
*/
private void advanceRunState(int targetState) {
+ // assert targetState == SHUTDOWN || targetState == STOP;
for (;;) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) ||
@@ -850,7 +866,7 @@
*/
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
- ArrayList<Runnable> taskList = new ArrayList<Runnable>();
+ ArrayList<Runnable> taskList = new ArrayList<>();
q.drainTo(taskList);
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
@@ -1406,7 +1422,7 @@
*
* <p>There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. This implementation
- * cancels tasks via {@link Thread#interrupt}, so any task that
+ * interrupts tasks via {@link Thread#interrupt}; any task that
* fails to respond to interrupts may never terminate.
*
* @throws SecurityException {@inheritDoc}
@@ -1457,13 +1473,12 @@
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
- for (;;) {
- if (runStateAtLeast(ctl.get(), TERMINATED))
- return true;
- if (nanos <= 0)
+ while (!runStateAtLeast(ctl.get(), TERMINATED)) {
+ if (nanos <= 0L)
return false;
nanos = termination.awaitNanos(nanos);
}
+ return true;
} finally {
mainLock.unlock();
}
@@ -1680,11 +1695,13 @@
}
/**
- * Sets the time limit for which threads may remain idle before
- * being terminated. If there are more than the core number of
- * threads currently in the pool, after waiting this amount of
- * time without processing a task, excess threads will be
- * terminated. This overrides any value set in the constructor.
+ * Sets the thread keep-alive time, which is the amount of time
+ * that threads may remain idle before being terminated.
+ * Threads that wait this amount of time without processing a
+ * task will be terminated if there are more than the core
+ * number of threads currently in the pool, or if this pool
+ * {@linkplain #allowsCoreThreadTimeOut() allows core thread timeout}.
+ * This overrides any value set in the constructor.
*
* @param time the time to wait. A time value of zero will cause
* excess threads to terminate immediately after executing tasks.
@@ -1707,8 +1724,11 @@
/**
* Returns the thread keep-alive time, which is the amount of time
- * that threads in excess of the core pool size may remain
- * idle before being terminated.
+ * that threads may remain idle before being terminated.
+ * Threads that wait this amount of time without processing a
+ * task will be terminated if there are more than the core
+ * number of threads currently in the pool, or if this pool
+ * {@linkplain #allowsCoreThreadTimeOut() allows core thread timeout}.
*
* @param unit the desired time unit of the result
* @return the time limit
@@ -1739,8 +1759,8 @@
*
* <p>This method may be useful as one part of a cancellation
* scheme. It may fail to remove tasks that have been converted
- * into other forms before being placed on the internal queue. For
- * example, a task entered using {@code submit} might be
+ * into other forms before being placed on the internal queue.
+ * For example, a task entered using {@code submit} might be
* converted into a form that maintains {@code Future} status.
* However, in such cases, method {@link #purge} may be used to
* remove those Futures that have been cancelled.
@@ -1912,11 +1932,12 @@
mainLock.unlock();
}
int c = ctl.get();
- String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
- (runStateAtLeast(c, TERMINATED) ? "Terminated" :
- "Shutting down"));
+ String runState =
+ runStateLessThan(c, SHUTDOWN) ? "Running" :
+ runStateAtLeast(c, TERMINATED) ? "Terminated" :
+ "Shutting down";
return super.toString() +
- "[" + rs +
+ "[" + runState +
", pool size = " + nworkers +
", active threads = " + nactive +
", queued tasks = " + workQueue.size() +
@@ -1963,20 +1984,23 @@
* as in this sample subclass that prints either the direct cause
* or the underlying exception if a task has been aborted:
*
- * <pre> {@code
+ * <pre> {@code
* class ExtendedExecutor extends ThreadPoolExecutor {
* // ...
* protected void afterExecute(Runnable r, Throwable t) {
* super.afterExecute(r, t);
- * if (t == null && r instanceof Future<?>) {
+ * if (t == null
+ * && r instanceof Future<?>
+ * && ((Future<?>)r).isDone()) {
* try {
* Object result = ((Future<?>) r).get();
* } catch (CancellationException ce) {
- * t = ce;
+ * t = ce;
* } catch (ExecutionException ee) {
- * t = ee.getCause();
+ * t = ee.getCause();
* } catch (InterruptedException ie) {
- * Thread.currentThread().interrupt(); // ignore/reset
+ * // ignore/reset
+ * Thread.currentThread().interrupt();
* }
* }
* if (t != null)
--- a/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java Tue Oct 20 08:24:37 2015 -0700
@@ -52,12 +52,12 @@
* the following code will timeout in 50 milliseconds if the {@link
* java.util.concurrent.locks.Lock lock} is not available:
*
- * <pre> {@code
+ * <pre> {@code
* Lock lock = ...;
* if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...}</pre>
*
* while this code will timeout in 50 seconds:
- * <pre> {@code
+ * <pre> {@code
* Lock lock = ...;
* if (lock.tryLock(50L, TimeUnit.SECONDS)) ...}</pre>
*
@@ -70,7 +70,7 @@
*/
public enum TimeUnit {
/**
- * Time unit representing one thousandth of a microsecond
+ * Time unit representing one thousandth of a microsecond.
*/
NANOSECONDS {
public long toNanos(long d) { return d; }
@@ -85,7 +85,7 @@
},
/**
- * Time unit representing one thousandth of a millisecond
+ * Time unit representing one thousandth of a millisecond.
*/
MICROSECONDS {
public long toNanos(long d) { return x(d, C1/C0, MAX/(C1/C0)); }
@@ -100,7 +100,7 @@
},
/**
- * Time unit representing one thousandth of a second
+ * Time unit representing one thousandth of a second.
*/
MILLISECONDS {
public long toNanos(long d) { return x(d, C2/C0, MAX/(C2/C0)); }
@@ -115,7 +115,7 @@
},
/**
- * Time unit representing one second
+ * Time unit representing one second.
*/
SECONDS {
public long toNanos(long d) { return x(d, C3/C0, MAX/(C3/C0)); }
@@ -130,7 +130,7 @@
},
/**
- * Time unit representing sixty seconds
+ * Time unit representing sixty seconds.
* @since 1.6
*/
MINUTES {
@@ -146,7 +146,7 @@
},
/**
- * Time unit representing sixty minutes
+ * Time unit representing sixty minutes.
* @since 1.6
*/
HOURS {
@@ -162,7 +162,7 @@
},
/**
- * Time unit representing twenty four hours
+ * Time unit representing twenty four hours.
* @since 1.6
*/
DAYS {
@@ -193,7 +193,7 @@
* This has a short name to make above code more readable.
*/
static long x(long d, long m, long over) {
- if (d > over) return Long.MAX_VALUE;
+ if (d > +over) return Long.MAX_VALUE;
if (d < -over) return Long.MIN_VALUE;
return d * m;
}
@@ -329,7 +329,7 @@
* method (see {@link BlockingQueue#poll BlockingQueue.poll})
* using:
*
- * <pre> {@code
+ * <pre> {@code
* public synchronized Object poll(long timeout, TimeUnit unit)
* throws InterruptedException {
* while (empty) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/TransferQueue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/TransferQueue.java Tue Oct 20 08:24:37 2015 -0700
@@ -63,7 +63,7 @@
*
* @since 1.7
* @author Doug Lea
- * @param <E> the type of elements held in this collection
+ * @param <E> the type of elements held in this queue
*/
public interface TransferQueue<E> extends BlockingQueue<E> {
/**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Tue Oct 20 08:24:37 2015 -0700
@@ -53,9 +53,9 @@
private static final long serialVersionUID = -6209656149925076980L;
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long ARRAY;
private static final int ABASE;
private static final int ASHIFT;
- private static final long ARRAY;
private final Object[] array; // must have exact type Object[]
static {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,11 +34,12 @@
*/
package java.util.concurrent.locks;
-import java.util.concurrent.TimeUnit;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
-import sun.misc.Unsafe;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer.Node;
/**
* A version of {@link AbstractQueuedSynchronizer} in
@@ -77,221 +78,6 @@
protected AbstractQueuedLongSynchronizer() { }
/**
- * Wait queue node class.
- *
- * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
- * Hagersten) lock queue. CLH locks are normally used for
- * spinlocks. We instead use them for blocking synchronizers, but
- * use the same basic tactic of holding some of the control
- * information about a thread in the predecessor of its node. A
- * "status" field in each node keeps track of whether a thread
- * should block. A node is signalled when its predecessor
- * releases. Each node of the queue otherwise serves as a
- * specific-notification-style monitor holding a single waiting
- * thread. The status field does NOT control whether threads are
- * granted locks etc though. A thread may try to acquire if it is
- * first in the queue. But being first does not guarantee success;
- * it only gives the right to contend. So the currently released
- * contender thread may need to rewait.
- *
- * <p>To enqueue into a CLH lock, you atomically splice it in as new
- * tail. To dequeue, you just set the head field.
- * <pre>
- * +------+ prev +-----+ +-----+
- * head | | <---- | | <---- | | tail
- * +------+ +-----+ +-----+
- * </pre>
- *
- * <p>Insertion into a CLH queue requires only a single atomic
- * operation on "tail", so there is a simple atomic point of
- * demarcation from unqueued to queued. Similarly, dequeuing
- * involves only updating the "head". However, it takes a bit
- * more work for nodes to determine who their successors are,
- * in part to deal with possible cancellation due to timeouts
- * and interrupts.
- *
- * <p>The "prev" links (not used in original CLH locks), are mainly
- * needed to handle cancellation. If a node is cancelled, its
- * successor is (normally) relinked to a non-cancelled
- * predecessor. For explanation of similar mechanics in the case
- * of spin locks, see the papers by Scott and Scherer at
- * http://www.cs.rochester.edu/u/scott/synchronization/
- *
- * <p>We also use "next" links to implement blocking mechanics.
- * The thread id for each node is kept in its own node, so a
- * predecessor signals the next node to wake up by traversing
- * next link to determine which thread it is. Determination of
- * successor must avoid races with newly queued nodes to set
- * the "next" fields of their predecessors. This is solved
- * when necessary by checking backwards from the atomically
- * updated "tail" when a node's successor appears to be null.
- * (Or, said differently, the next-links are an optimization
- * so that we don't usually need a backward scan.)
- *
- * <p>Cancellation introduces some conservatism to the basic
- * algorithms. Since we must poll for cancellation of other
- * nodes, we can miss noticing whether a cancelled node is
- * ahead or behind us. This is dealt with by always unparking
- * successors upon cancellation, allowing them to stabilize on
- * a new predecessor, unless we can identify an uncancelled
- * predecessor who will carry this responsibility.
- *
- * <p>CLH queues need a dummy header node to get started. But
- * we don't create them on construction, because it would be wasted
- * effort if there is never contention. Instead, the node
- * is constructed and head and tail pointers are set upon first
- * contention.
- *
- * <p>Threads waiting on Conditions use the same nodes, but
- * use an additional link. Conditions only need to link nodes
- * in simple (non-concurrent) linked queues because they are
- * only accessed when exclusively held. Upon await, a node is
- * inserted into a condition queue. Upon signal, the node is
- * transferred to the main queue. A special value of status
- * field is used to mark which queue a node is on.
- *
- * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
- * Scherer and Michael Scott, along with members of JSR-166
- * expert group, for helpful ideas, discussions, and critiques
- * on the design of this class.
- */
- static final class Node {
- /** Marker to indicate a node is waiting in shared mode */
- static final Node SHARED = new Node();
- /** Marker to indicate a node is waiting in exclusive mode */
- static final Node EXCLUSIVE = null;
-
- /** waitStatus value to indicate thread has cancelled */
- static final int CANCELLED = 1;
- /** waitStatus value to indicate successor's thread needs unparking */
- static final int SIGNAL = -1;
- /** waitStatus value to indicate thread is waiting on condition */
- static final int CONDITION = -2;
- /**
- * waitStatus value to indicate the next acquireShared should
- * unconditionally propagate
- */
- static final int PROPAGATE = -3;
-
- /**
- * Status field, taking on only the values:
- * SIGNAL: The successor of this node is (or will soon be)
- * blocked (via park), so the current node must
- * unpark its successor when it releases or
- * cancels. To avoid races, acquire methods must
- * first indicate they need a signal,
- * then retry the atomic acquire, and then,
- * on failure, block.
- * CANCELLED: This node is cancelled due to timeout or interrupt.
- * Nodes never leave this state. In particular,
- * a thread with cancelled node never again blocks.
- * CONDITION: This node is currently on a condition queue.
- * It will not be used as a sync queue node
- * until transferred, at which time the status
- * will be set to 0. (Use of this value here has
- * nothing to do with the other uses of the
- * field, but simplifies mechanics.)
- * PROPAGATE: A releaseShared should be propagated to other
- * nodes. This is set (for head node only) in
- * doReleaseShared to ensure propagation
- * continues, even if other operations have
- * since intervened.
- * 0: None of the above
- *
- * The values are arranged numerically to simplify use.
- * Non-negative values mean that a node doesn't need to
- * signal. So, most code doesn't need to check for particular
- * values, just for sign.
- *
- * The field is initialized to 0 for normal sync nodes, and
- * CONDITION for condition nodes. It is modified using CAS
- * (or when possible, unconditional volatile writes).
- */
- volatile int waitStatus;
-
- /**
- * Link to predecessor node that current node/thread relies on
- * for checking waitStatus. Assigned during enqueuing, and nulled
- * out (for sake of GC) only upon dequeuing. Also, upon
- * cancellation of a predecessor, we short-circuit while
- * finding a non-cancelled one, which will always exist
- * because the head node is never cancelled: A node becomes
- * head only as a result of successful acquire. A
- * cancelled thread never succeeds in acquiring, and a thread only
- * cancels itself, not any other node.
- */
- volatile Node prev;
-
- /**
- * Link to the successor node that the current node/thread
- * unparks upon release. Assigned during enqueuing, adjusted
- * when bypassing cancelled predecessors, and nulled out (for
- * sake of GC) when dequeued. The enq operation does not
- * assign next field of a predecessor until after attachment,
- * so seeing a null next field does not necessarily mean that
- * node is at end of queue. However, if a next field appears
- * to be null, we can scan prev's from the tail to
- * double-check. The next field of cancelled nodes is set to
- * point to the node itself instead of null, to make life
- * easier for isOnSyncQueue.
- */
- volatile Node next;
-
- /**
- * The thread that enqueued this node. Initialized on
- * construction and nulled out after use.
- */
- volatile Thread thread;
-
- /**
- * Link to next node waiting on condition, or the special
- * value SHARED. Because condition queues are accessed only
- * when holding in exclusive mode, we just need a simple
- * linked queue to hold nodes while they are waiting on
- * conditions. They are then transferred to the queue to
- * re-acquire. And because conditions can only be exclusive,
- * we save a field by using special value to indicate shared
- * mode.
- */
- Node nextWaiter;
-
- /**
- * Returns true if node is waiting in shared mode.
- */
- final boolean isShared() {
- return nextWaiter == SHARED;
- }
-
- /**
- * Returns previous node, or throws NullPointerException if null.
- * Use when predecessor cannot be null. The null check could
- * be elided, but is present to help the VM.
- *
- * @return the predecessor of this node
- */
- final Node predecessor() throws NullPointerException {
- Node p = prev;
- if (p == null)
- throw new NullPointerException();
- else
- return p;
- }
-
- Node() { // Used to establish initial head or SHARED marker
- }
-
- Node(Thread thread, Node mode) { // Used by addWaiter
- this.nextWaiter = mode;
- this.thread = thread;
- }
-
- Node(Thread thread, int waitStatus) { // Used by Condition
- this.waitStatus = waitStatus;
- this.thread = thread;
- }
- }
-
- /**
* Head of the wait queue, lazily initialized. Except for
* initialization, it is modified only via method setHead. Note:
* If head exists, its waitStatus is guaranteed not to be
@@ -325,7 +111,9 @@
* @param newState the new state value
*/
protected final void setState(long newState) {
- state = newState;
+ // Use putLongVolatile instead of ordinary volatile store when
+ // using compareAndSwapLong, for sake of some 32bit systems.
+ U.putLongVolatile(this, STATE, newState);
}
/**
@@ -340,8 +128,7 @@
* value was not equal to the expected value.
*/
protected final boolean compareAndSetState(long expect, long update) {
- // See below for intrinsics setup to support this
- return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
+ return U.compareAndSwapLong(this, STATE, expect, update);
}
// Queuing utilities
@@ -351,25 +138,24 @@
* rather than to use timed park. A rough estimate suffices
* to improve responsiveness with very short timeouts.
*/
- static final long spinForTimeoutThreshold = 1000L;
+ static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert
* @return node's predecessor
*/
- private Node enq(final Node node) {
+ private Node enq(Node node) {
for (;;) {
- Node t = tail;
- if (t == null) { // Must initialize
- if (compareAndSetHead(new Node()))
- tail = head;
+ Node oldTail = tail;
+ if (oldTail != null) {
+ U.putObject(node, Node.PREV, oldTail);
+ if (compareAndSetTail(oldTail, node)) {
+ oldTail.next = node;
+ return oldTail;
+ }
} else {
- node.prev = t;
- if (compareAndSetTail(t, node)) {
- t.next = node;
- return t;
- }
+ initializeSyncQueue();
}
}
}
@@ -381,18 +167,20 @@
* @return the new node
*/
private Node addWaiter(Node mode) {
- Node node = new Node(Thread.currentThread(), mode);
- // Try the fast path of enq; backup to full enq on failure
- Node pred = tail;
- if (pred != null) {
- node.prev = pred;
- if (compareAndSetTail(pred, node)) {
- pred.next = node;
- return node;
+ Node node = new Node(mode);
+
+ for (;;) {
+ Node oldTail = tail;
+ if (oldTail != null) {
+ U.putObject(node, Node.PREV, oldTail);
+ if (compareAndSetTail(oldTail, node)) {
+ oldTail.next = node;
+ return node;
+ }
+ } else {
+ initializeSyncQueue();
}
}
- enq(node);
- return node;
}
/**
@@ -421,7 +209,7 @@
*/
int ws = node.waitStatus;
if (ws < 0)
- compareAndSetWaitStatus(node, ws, 0);
+ node.compareAndSetWaitStatus(ws, 0);
/*
* Thread to unpark is held in successor, which is normally
@@ -432,9 +220,9 @@
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
- for (Node t = tail; t != null && t != node; t = t.prev)
- if (t.waitStatus <= 0)
- s = t;
+ for (Node p = tail; p != node && p != null; p = p.prev)
+ if (p.waitStatus <= 0)
+ s = p;
}
if (s != null)
LockSupport.unpark(s.thread);
@@ -462,12 +250,12 @@
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
- if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+ if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
- !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+ !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
@@ -541,18 +329,18 @@
// If we are the tail, remove ourselves.
if (node == tail && compareAndSetTail(node, pred)) {
- compareAndSetNext(pred, predNext, null);
+ pred.compareAndSetNext(predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
- (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+ (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
- compareAndSetNext(pred, predNext, next);
+ pred.compareAndSetNext(predNext, next);
} else {
unparkSuccessor(node);
}
@@ -593,7 +381,7 @@
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
- compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
+ pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
}
return false;
}
@@ -606,7 +394,7 @@
}
/**
- * Convenience method to park and then check if interrupted
+ * Convenience method to park and then check if interrupted.
*
* @return {@code true} if interrupted
*/
@@ -633,7 +421,6 @@
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, long arg) {
- boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
@@ -641,16 +428,15 @@
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
- failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -661,23 +447,21 @@
private void doAcquireInterruptibly(long arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
- failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -694,28 +478,28 @@
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
- failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
- if (nanosTimeout <= 0L)
+ if (nanosTimeout <= 0L) {
+ cancelAcquire(node);
return false;
+ }
if (shouldParkAfterFailedAcquire(p, node) &&
- nanosTimeout > spinForTimeoutThreshold)
+ nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -725,7 +509,6 @@
*/
private void doAcquireShared(long arg) {
final Node node = addWaiter(Node.SHARED);
- boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
@@ -737,7 +520,6 @@
p.next = null; // help GC
if (interrupted)
selfInterrupt();
- failed = false;
return;
}
}
@@ -745,9 +527,9 @@
parkAndCheckInterrupt())
interrupted = true;
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -758,7 +540,6 @@
private void doAcquireSharedInterruptibly(long arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
@@ -767,7 +548,6 @@
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
- failed = false;
return;
}
}
@@ -775,9 +555,9 @@
parkAndCheckInterrupt())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -794,7 +574,6 @@
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
@@ -803,22 +582,23 @@
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
- failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
- if (nanosTimeout <= 0L)
+ if (nanosTimeout <= 0L) {
+ cancelAcquire(node);
return false;
+ }
if (shouldParkAfterFailedAcquire(p, node) &&
- nanosTimeout > spinForTimeoutThreshold)
+ nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -1170,7 +950,7 @@
}
/**
- * Version of getFirstQueuedThread called when fastpath fails
+ * Version of getFirstQueuedThread called when fastpath fails.
*/
private Thread fullGetFirstQueuedThread() {
/*
@@ -1250,7 +1030,7 @@
*
* <p>An invocation of this method is equivalent to (but may be
* more efficient than):
- * <pre> {@code
+ * <pre> {@code
* getFirstQueuedThread() != Thread.currentThread() &&
* hasQueuedThreads()}</pre>
*
@@ -1270,7 +1050,7 @@
* tryAcquire} method for a fair, reentrant, exclusive mode
* synchronizer might look like this:
*
- * <pre> {@code
+ * <pre> {@code
* protected boolean tryAcquire(int arg) {
* if (isHeldExclusively()) {
* // A reentrant acquire; increment hold count
@@ -1306,8 +1086,7 @@
* acquire. The value is only an estimate because the number of
* threads may change dynamically while this method traverses
* internal data structures. This method is designed for use in
- * monitoring system state, not for synchronization
- * control.
+ * monitoring system state, not for synchronization control.
*
* @return the estimated number of threads waiting to acquire
*/
@@ -1332,7 +1111,7 @@
* @return the collection of threads
*/
public final Collection<Thread> getQueuedThreads() {
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
@@ -1350,7 +1129,7 @@
* @return the collection of threads
*/
public final Collection<Thread> getExclusiveQueuedThreads() {
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
@@ -1370,7 +1149,7 @@
* @return the collection of threads
*/
public final Collection<Thread> getSharedQueuedThreads() {
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
@@ -1391,10 +1170,9 @@
* @return a string identifying this synchronizer, as well as its state
*/
public String toString() {
- long s = getState();
- String q = hasQueuedThreads() ? "non" : "";
- return super.toString() +
- "[State = " + s + ", " + q + "empty queue]";
+ return super.toString()
+ + "[State = " + getState() + ", "
+ + (hasQueuedThreads() ? "non" : "") + "empty queue]";
}
@@ -1428,13 +1206,15 @@
* @return true if present
*/
private boolean findNodeFromTail(Node node) {
- Node t = tail;
- for (;;) {
- if (t == node)
+ // We check for node first, since it's likely to be at or near tail.
+ // tail is known to be non-null, so we could re-order to "save"
+ // one null check, but we leave it this way to help the VM.
+ for (Node p = tail;;) {
+ if (p == node)
return true;
- if (t == null)
+ if (p == null)
return false;
- t = t.prev;
+ p = p.prev;
}
}
@@ -1449,7 +1229,7 @@
/*
* If cannot change waitStatus, the node has been cancelled.
*/
- if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+ if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
return false;
/*
@@ -1460,7 +1240,7 @@
*/
Node p = enq(node);
int ws = p.waitStatus;
- if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
+ if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
@@ -1473,7 +1253,7 @@
* @return true if cancelled before the node was signalled
*/
final boolean transferAfterCancelledWait(Node node) {
- if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+ if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
enq(node);
return true;
}
@@ -1495,18 +1275,14 @@
* @return previous sync state
*/
final long fullyRelease(Node node) {
- boolean failed = true;
try {
long savedState = getState();
- if (release(savedState)) {
- failed = false;
+ if (release(savedState))
return savedState;
- } else {
- throw new IllegalMonitorStateException();
- }
- } finally {
- if (failed)
- node.waitStatus = Node.CANCELLED;
+ throw new IllegalMonitorStateException();
+ } catch (Throwable t) {
+ node.waitStatus = Node.CANCELLED;
+ throw t;
}
}
@@ -1551,8 +1327,8 @@
* given condition associated with this synchronizer. Note that
* because timeouts and interrupts may occur at any time, the
* estimate serves only as an upper bound on the actual number of
- * waiters. This method is designed for use in monitoring of the
- * system state, not for synchronization control.
+ * waiters. This method is designed for use in monitoring system
+ * state, not for synchronization control.
*
* @param condition the condition
* @return the estimated number of waiting threads
@@ -1632,7 +1408,9 @@
unlinkCancelledWaiters();
t = lastWaiter;
}
- Node node = new Node(Thread.currentThread(), Node.CONDITION);
+
+ Node node = new Node(Node.CONDITION);
+
if (t == null)
firstWaiter = node;
else
@@ -1740,12 +1518,12 @@
/**
* Implements uninterruptible condition wait.
* <ol>
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
* </ol>
*/
public final void awaitUninterruptibly() {
@@ -1799,14 +1577,14 @@
/**
* Implements interruptible condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled or interrupted.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled or interrupted.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final void await() throws InterruptedException {
@@ -1831,30 +1609,33 @@
/**
* Implements timed condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled, interrupted, or timed out.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled, interrupted, or timed out.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
+ // We don't check for nanosTimeout <= 0L here, to allow
+ // awaitNanos(0) as a way to "yield the lock".
+ final long deadline = System.nanoTime() + nanosTimeout;
+ long initialNanos = nanosTimeout;
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
- final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
- if (nanosTimeout >= spinForTimeoutThreshold)
+ if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
@@ -1866,21 +1647,22 @@
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
- return deadline - System.nanoTime();
+ long remaining = deadline - System.nanoTime(); // avoid overflow
+ return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
}
/**
* Implements absolute timed condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled, interrupted, or timed out.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
- * <li> If timed out while blocked in step 4, return false, else true.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled, interrupted, or timed out.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If timed out while blocked in step 4, return false, else true.
* </ol>
*/
public final boolean awaitUntil(Date deadline)
@@ -1893,7 +1675,7 @@
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
- if (System.currentTimeMillis() > abstime) {
+ if (System.currentTimeMillis() >= abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
@@ -1913,15 +1695,15 @@
/**
* Implements timed condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled, interrupted, or timed out.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
- * <li> If timed out while blocked in step 4, return false, else true.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled, interrupted, or timed out.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If timed out while blocked in step 4, return false, else true.
* </ol>
*/
public final boolean await(long time, TimeUnit unit)
@@ -1929,9 +1711,11 @@
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
+ // We don't check for nanosTimeout <= 0L here, to allow
+ // await(0, unit) as a way to "yield the lock".
+ final long deadline = System.nanoTime() + nanosTimeout;
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
- final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
@@ -1939,7 +1723,7 @@
timedout = transferAfterCancelledWait(node);
break;
}
- if (nanosTimeout >= spinForTimeoutThreshold)
+ if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
@@ -2016,7 +1800,7 @@
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
@@ -2037,59 +1821,40 @@
* are at it, we do the same for other CASable fields (which could
* otherwise be done with atomic field updaters).
*/
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long stateOffset;
- private static final long headOffset;
- private static final long tailOffset;
- private static final long waitStatusOffset;
- private static final long nextOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long STATE;
+ private static final long HEAD;
+ private static final long TAIL;
static {
try {
- stateOffset = unsafe.objectFieldOffset
+ STATE = U.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
- headOffset = unsafe.objectFieldOffset
+ HEAD = U.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
- tailOffset = unsafe.objectFieldOffset
+ TAIL = U.objectFieldOffset
(AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
- waitStatusOffset = unsafe.objectFieldOffset
- (Node.class.getDeclaredField("waitStatus"));
- nextOffset = unsafe.objectFieldOffset
- (Node.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
- } catch (Exception ex) { throw new Error(ex); }
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
/**
- * CAS head field. Used only by enq.
+ * Initializes head and tail fields on first contention.
*/
- private final boolean compareAndSetHead(Node update) {
- return unsafe.compareAndSwapObject(this, headOffset, null, update);
- }
-
- /**
- * CAS tail field. Used only by enq.
- */
- private final boolean compareAndSetTail(Node expect, Node update) {
- return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+ private final void initializeSyncQueue() {
+ if (U.compareAndSwapObject(this, HEAD, null, new Node()))
+ tail = head;
}
/**
- * CAS waitStatus field of a node.
+ * CASes tail field.
*/
- private static final boolean compareAndSetWaitStatus(Node node,
- int expect,
- int update) {
- return unsafe.compareAndSwapInt(node, waitStatusOffset,
- expect, update);
- }
-
- /**
- * CAS next field of a node.
- */
- private static final boolean compareAndSetNext(Node node,
- Node expect,
- Node update) {
- return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
+ private final boolean compareAndSetTail(Node expect, Node update) {
+ return U.compareAndSwapObject(this, TAIL, expect, update);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,11 +34,11 @@
*/
package java.util.concurrent.locks;
-import java.util.concurrent.TimeUnit;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
-import sun.misc.Unsafe;
+import java.util.concurrent.TimeUnit;
/**
* Provides a framework for implementing blocking locks and related
@@ -110,11 +110,11 @@
* #setState} and/or {@link #compareAndSetState}:
*
* <ul>
- * <li> {@link #tryAcquire}
- * <li> {@link #tryRelease}
- * <li> {@link #tryAcquireShared}
- * <li> {@link #tryReleaseShared}
- * <li> {@link #isHeldExclusively}
+ * <li>{@link #tryAcquire}
+ * <li>{@link #tryRelease}
+ * <li>{@link #tryAcquireShared}
+ * <li>{@link #tryReleaseShared}
+ * <li>{@link #isHeldExclusively}
* </ul>
*
* Each of these methods by default throws {@link
@@ -195,7 +195,7 @@
* It also supports conditions and exposes
* one of the instrumentation methods:
*
- * <pre> {@code
+ * <pre> {@code
* class Mutex implements Lock, java.io.Serializable {
*
* // Our internal helper class
@@ -259,7 +259,7 @@
* fire. Because a latch is non-exclusive, it uses the {@code shared}
* acquire and release methods.
*
- * <pre> {@code
+ * <pre> {@code
* class BooleanLatch {
*
* private static class Sync extends AbstractQueuedSynchronizer {
@@ -383,15 +383,15 @@
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
- /** waitStatus value to indicate thread has cancelled */
+ /** waitStatus value to indicate thread has cancelled. */
static final int CANCELLED = 1;
- /** waitStatus value to indicate successor's thread needs unparking */
+ /** waitStatus value to indicate successor's thread needs unparking. */
static final int SIGNAL = -1;
- /** waitStatus value to indicate thread is waiting on condition */
+ /** waitStatus value to indicate thread is waiting on condition. */
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
- * unconditionally propagate
+ * unconditionally propagate.
*/
static final int PROPAGATE = -3;
@@ -499,17 +499,49 @@
return p;
}
- Node() { // Used to establish initial head or SHARED marker
+ /** Establishes initial head or SHARED marker. */
+ Node() {}
+
+ /** Constructor used by addWaiter. */
+ Node(Node nextWaiter) {
+ this.nextWaiter = nextWaiter;
+ U.putObject(this, THREAD, Thread.currentThread());
+ }
+
+ /** Constructor used by addConditionWaiter. */
+ Node(int waitStatus) {
+ U.putInt(this, WAITSTATUS, waitStatus);
+ U.putObject(this, THREAD, Thread.currentThread());
+ }
+
+ /** CASes waitStatus field. */
+ final boolean compareAndSetWaitStatus(int expect, int update) {
+ return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
}
- Node(Thread thread, Node mode) { // Used by addWaiter
- this.nextWaiter = mode;
- this.thread = thread;
+ /** CASes next field. */
+ final boolean compareAndSetNext(Node expect, Node update) {
+ return U.compareAndSwapObject(this, NEXT, expect, update);
}
- Node(Thread thread, int waitStatus) { // Used by Condition
- this.waitStatus = waitStatus;
- this.thread = thread;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long NEXT;
+ static final long PREV;
+ private static final long THREAD;
+ private static final long WAITSTATUS;
+ static {
+ try {
+ NEXT = U.objectFieldOffset
+ (Node.class.getDeclaredField("next"));
+ PREV = U.objectFieldOffset
+ (Node.class.getDeclaredField("prev"));
+ THREAD = U.objectFieldOffset
+ (Node.class.getDeclaredField("thread"));
+ WAITSTATUS = U.objectFieldOffset
+ (Node.class.getDeclaredField("waitStatus"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
}
@@ -562,8 +594,7 @@
* value was not equal to the expected value.
*/
protected final boolean compareAndSetState(int expect, int update) {
- // See below for intrinsics setup to support this
- return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
+ return U.compareAndSwapInt(this, STATE, expect, update);
}
// Queuing utilities
@@ -573,25 +604,24 @@
* rather than to use timed park. A rough estimate suffices
* to improve responsiveness with very short timeouts.
*/
- static final long spinForTimeoutThreshold = 1000L;
+ static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert
* @return node's predecessor
*/
- private Node enq(final Node node) {
+ private Node enq(Node node) {
for (;;) {
- Node t = tail;
- if (t == null) { // Must initialize
- if (compareAndSetHead(new Node()))
- tail = head;
+ Node oldTail = tail;
+ if (oldTail != null) {
+ U.putObject(node, Node.PREV, oldTail);
+ if (compareAndSetTail(oldTail, node)) {
+ oldTail.next = node;
+ return oldTail;
+ }
} else {
- node.prev = t;
- if (compareAndSetTail(t, node)) {
- t.next = node;
- return t;
- }
+ initializeSyncQueue();
}
}
}
@@ -603,18 +633,20 @@
* @return the new node
*/
private Node addWaiter(Node mode) {
- Node node = new Node(Thread.currentThread(), mode);
- // Try the fast path of enq; backup to full enq on failure
- Node pred = tail;
- if (pred != null) {
- node.prev = pred;
- if (compareAndSetTail(pred, node)) {
- pred.next = node;
- return node;
+ Node node = new Node(mode);
+
+ for (;;) {
+ Node oldTail = tail;
+ if (oldTail != null) {
+ U.putObject(node, Node.PREV, oldTail);
+ if (compareAndSetTail(oldTail, node)) {
+ oldTail.next = node;
+ return node;
+ }
+ } else {
+ initializeSyncQueue();
}
}
- enq(node);
- return node;
}
/**
@@ -643,7 +675,7 @@
*/
int ws = node.waitStatus;
if (ws < 0)
- compareAndSetWaitStatus(node, ws, 0);
+ node.compareAndSetWaitStatus(ws, 0);
/*
* Thread to unpark is held in successor, which is normally
@@ -654,9 +686,9 @@
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
- for (Node t = tail; t != null && t != node; t = t.prev)
- if (t.waitStatus <= 0)
- s = t;
+ for (Node p = tail; p != node && p != null; p = p.prev)
+ if (p.waitStatus <= 0)
+ s = p;
}
if (s != null)
LockSupport.unpark(s.thread);
@@ -684,12 +716,12 @@
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
- if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+ if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
- !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+ !h.compareAndSetWaitStatus(0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
@@ -763,18 +795,18 @@
// If we are the tail, remove ourselves.
if (node == tail && compareAndSetTail(node, pred)) {
- compareAndSetNext(pred, predNext, null);
+ pred.compareAndSetNext(predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
- (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+ (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
- compareAndSetNext(pred, predNext, next);
+ pred.compareAndSetNext(predNext, next);
} else {
unparkSuccessor(node);
}
@@ -815,7 +847,7 @@
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
- compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
+ pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
}
return false;
}
@@ -828,7 +860,7 @@
}
/**
- * Convenience method to park and then check if interrupted
+ * Convenience method to park and then check if interrupted.
*
* @return {@code true} if interrupted
*/
@@ -855,7 +887,6 @@
* @return {@code true} if interrupted while waiting
*/
final boolean acquireQueued(final Node node, int arg) {
- boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
@@ -863,16 +894,15 @@
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
- failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -883,23 +913,21 @@
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
- failed = false;
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -916,28 +944,28 @@
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
- failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
- if (nanosTimeout <= 0L)
+ if (nanosTimeout <= 0L) {
+ cancelAcquire(node);
return false;
+ }
if (shouldParkAfterFailedAcquire(p, node) &&
- nanosTimeout > spinForTimeoutThreshold)
+ nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -947,7 +975,6 @@
*/
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
- boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
@@ -959,7 +986,6 @@
p.next = null; // help GC
if (interrupted)
selfInterrupt();
- failed = false;
return;
}
}
@@ -967,9 +993,9 @@
parkAndCheckInterrupt())
interrupted = true;
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -980,7 +1006,6 @@
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
@@ -989,7 +1014,6 @@
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
- failed = false;
return;
}
}
@@ -997,9 +1021,9 @@
parkAndCheckInterrupt())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -1016,7 +1040,6 @@
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
- boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
@@ -1025,22 +1048,23 @@
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
- failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
- if (nanosTimeout <= 0L)
+ if (nanosTimeout <= 0L) {
+ cancelAcquire(node);
return false;
+ }
if (shouldParkAfterFailedAcquire(p, node) &&
- nanosTimeout > spinForTimeoutThreshold)
+ nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
- } finally {
- if (failed)
- cancelAcquire(node);
+ } catch (Throwable t) {
+ cancelAcquire(node);
+ throw t;
}
}
@@ -1392,7 +1416,7 @@
}
/**
- * Version of getFirstQueuedThread called when fastpath fails
+ * Version of getFirstQueuedThread called when fastpath fails.
*/
private Thread fullGetFirstQueuedThread() {
/*
@@ -1472,7 +1496,7 @@
*
* <p>An invocation of this method is equivalent to (but may be
* more efficient than):
- * <pre> {@code
+ * <pre> {@code
* getFirstQueuedThread() != Thread.currentThread() &&
* hasQueuedThreads()}</pre>
*
@@ -1492,7 +1516,7 @@
* tryAcquire} method for a fair, reentrant, exclusive mode
* synchronizer might look like this:
*
- * <pre> {@code
+ * <pre> {@code
* protected boolean tryAcquire(int arg) {
* if (isHeldExclusively()) {
* // A reentrant acquire; increment hold count
@@ -1528,8 +1552,7 @@
* acquire. The value is only an estimate because the number of
* threads may change dynamically while this method traverses
* internal data structures. This method is designed for use in
- * monitoring system state, not for synchronization
- * control.
+ * monitoring system state, not for synchronization control.
*
* @return the estimated number of threads waiting to acquire
*/
@@ -1554,7 +1577,7 @@
* @return the collection of threads
*/
public final Collection<Thread> getQueuedThreads() {
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
@@ -1572,7 +1595,7 @@
* @return the collection of threads
*/
public final Collection<Thread> getExclusiveQueuedThreads() {
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
@@ -1592,7 +1615,7 @@
* @return the collection of threads
*/
public final Collection<Thread> getSharedQueuedThreads() {
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
@@ -1613,10 +1636,9 @@
* @return a string identifying this synchronizer, as well as its state
*/
public String toString() {
- int s = getState();
- String q = hasQueuedThreads() ? "non" : "";
- return super.toString() +
- "[State = " + s + ", " + q + "empty queue]";
+ return super.toString()
+ + "[State = " + getState() + ", "
+ + (hasQueuedThreads() ? "non" : "") + "empty queue]";
}
@@ -1650,13 +1672,15 @@
* @return true if present
*/
private boolean findNodeFromTail(Node node) {
- Node t = tail;
- for (;;) {
- if (t == node)
+ // We check for node first, since it's likely to be at or near tail.
+ // tail is known to be non-null, so we could re-order to "save"
+ // one null check, but we leave it this way to help the VM.
+ for (Node p = tail;;) {
+ if (p == node)
return true;
- if (t == null)
+ if (p == null)
return false;
- t = t.prev;
+ p = p.prev;
}
}
@@ -1671,7 +1695,7 @@
/*
* If cannot change waitStatus, the node has been cancelled.
*/
- if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
+ if (!node.compareAndSetWaitStatus(Node.CONDITION, 0))
return false;
/*
@@ -1682,7 +1706,7 @@
*/
Node p = enq(node);
int ws = p.waitStatus;
- if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
+ if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}
@@ -1695,7 +1719,7 @@
* @return true if cancelled before the node was signalled
*/
final boolean transferAfterCancelledWait(Node node) {
- if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
+ if (node.compareAndSetWaitStatus(Node.CONDITION, 0)) {
enq(node);
return true;
}
@@ -1717,18 +1741,14 @@
* @return previous sync state
*/
final int fullyRelease(Node node) {
- boolean failed = true;
try {
int savedState = getState();
- if (release(savedState)) {
- failed = false;
+ if (release(savedState))
return savedState;
- } else {
- throw new IllegalMonitorStateException();
- }
- } finally {
- if (failed)
- node.waitStatus = Node.CANCELLED;
+ throw new IllegalMonitorStateException();
+ } catch (Throwable t) {
+ node.waitStatus = Node.CANCELLED;
+ throw t;
}
}
@@ -1773,8 +1793,8 @@
* given condition associated with this synchronizer. Note that
* because timeouts and interrupts may occur at any time, the
* estimate serves only as an upper bound on the actual number of
- * waiters. This method is designed for use in monitoring of the
- * system state, not for synchronization control.
+ * waiters. This method is designed for use in monitoring system
+ * state, not for synchronization control.
*
* @param condition the condition
* @return the estimated number of waiting threads
@@ -1852,7 +1872,9 @@
unlinkCancelledWaiters();
t = lastWaiter;
}
- Node node = new Node(Thread.currentThread(), Node.CONDITION);
+
+ Node node = new Node(Node.CONDITION);
+
if (t == null)
firstWaiter = node;
else
@@ -1960,12 +1982,12 @@
/**
* Implements uninterruptible condition wait.
* <ol>
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
* </ol>
*/
public final void awaitUninterruptibly() {
@@ -2019,14 +2041,14 @@
/**
* Implements interruptible condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled or interrupted.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled or interrupted.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final void await() throws InterruptedException {
@@ -2051,30 +2073,33 @@
/**
* Implements timed condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled, interrupted, or timed out.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled, interrupted, or timed out.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
+ // We don't check for nanosTimeout <= 0L here, to allow
+ // awaitNanos(0) as a way to "yield the lock".
+ final long deadline = System.nanoTime() + nanosTimeout;
+ long initialNanos = nanosTimeout;
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
- final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
- if (nanosTimeout >= spinForTimeoutThreshold)
+ if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
@@ -2086,21 +2111,22 @@
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
- return deadline - System.nanoTime();
+ long remaining = deadline - System.nanoTime(); // avoid overflow
+ return (remaining <= initialNanos) ? remaining : Long.MIN_VALUE;
}
/**
* Implements absolute timed condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled, interrupted, or timed out.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
- * <li> If timed out while blocked in step 4, return false, else true.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled, interrupted, or timed out.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If timed out while blocked in step 4, return false, else true.
* </ol>
*/
public final boolean awaitUntil(Date deadline)
@@ -2113,7 +2139,7 @@
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
- if (System.currentTimeMillis() > abstime) {
+ if (System.currentTimeMillis() >= abstime) {
timedout = transferAfterCancelledWait(node);
break;
}
@@ -2133,15 +2159,15 @@
/**
* Implements timed condition wait.
* <ol>
- * <li> If current thread is interrupted, throw InterruptedException.
- * <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with saved state as argument,
- * throwing IllegalMonitorStateException if it fails.
- * <li> Block until signalled, interrupted, or timed out.
- * <li> Reacquire by invoking specialized version of
- * {@link #acquire} with saved state as argument.
- * <li> If interrupted while blocked in step 4, throw InterruptedException.
- * <li> If timed out while blocked in step 4, return false, else true.
+ * <li>If current thread is interrupted, throw InterruptedException.
+ * <li>Save lock state returned by {@link #getState}.
+ * <li>Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
+ * <li>Block until signalled, interrupted, or timed out.
+ * <li>Reacquire by invoking specialized version of
+ * {@link #acquire} with saved state as argument.
+ * <li>If interrupted while blocked in step 4, throw InterruptedException.
+ * <li>If timed out while blocked in step 4, return false, else true.
* </ol>
*/
public final boolean await(long time, TimeUnit unit)
@@ -2149,9 +2175,11 @@
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
+ // We don't check for nanosTimeout <= 0L here, to allow
+ // await(0, unit) as a way to "yield the lock".
+ final long deadline = System.nanoTime() + nanosTimeout;
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
- final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
@@ -2159,7 +2187,7 @@
timedout = transferAfterCancelledWait(node);
break;
}
- if (nanosTimeout >= spinForTimeoutThreshold)
+ if (nanosTimeout >= SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
@@ -2236,7 +2264,7 @@
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
- ArrayList<Thread> list = new ArrayList<Thread>();
+ ArrayList<Thread> list = new ArrayList<>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
@@ -2257,59 +2285,40 @@
* are at it, we do the same for other CASable fields (which could
* otherwise be done with atomic field updaters).
*/
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long stateOffset;
- private static final long headOffset;
- private static final long tailOffset;
- private static final long waitStatusOffset;
- private static final long nextOffset;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long STATE;
+ private static final long HEAD;
+ private static final long TAIL;
static {
try {
- stateOffset = unsafe.objectFieldOffset
+ STATE = U.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state"));
- headOffset = unsafe.objectFieldOffset
+ HEAD = U.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
- tailOffset = unsafe.objectFieldOffset
+ TAIL = U.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
- waitStatusOffset = unsafe.objectFieldOffset
- (Node.class.getDeclaredField("waitStatus"));
- nextOffset = unsafe.objectFieldOffset
- (Node.class.getDeclaredField("next"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
- } catch (Exception ex) { throw new Error(ex); }
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
}
/**
- * CAS head field. Used only by enq.
+ * Initializes head and tail fields on first contention.
*/
- private final boolean compareAndSetHead(Node update) {
- return unsafe.compareAndSwapObject(this, headOffset, null, update);
- }
-
- /**
- * CAS tail field. Used only by enq.
- */
- private final boolean compareAndSetTail(Node expect, Node update) {
- return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
+ private final void initializeSyncQueue() {
+ if (U.compareAndSwapObject(this, HEAD, null, new Node()))
+ tail = head;
}
/**
- * CAS waitStatus field of a node.
+ * CASes tail field.
*/
- private static final boolean compareAndSetWaitStatus(Node node,
- int expect,
- int update) {
- return unsafe.compareAndSwapInt(node, waitStatusOffset,
- expect, update);
- }
-
- /**
- * CAS next field of a node.
- */
- private static final boolean compareAndSetNext(Node node,
- Node expect,
- Node update) {
- return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
+ private final boolean compareAndSetTail(Node expect, Node update) {
+ return U.compareAndSwapObject(this, TAIL, expect, update);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,8 +34,9 @@
*/
package java.util.concurrent.locks;
+
+import java.util.Date;
import java.util.concurrent.TimeUnit;
-import java.util.Date;
/**
* {@code Condition} factors out the {@code Object} monitor
@@ -126,7 +127,7 @@
* <p>Note that {@code Condition} instances are just normal objects and can
* themselves be used as the target in a {@code synchronized} statement,
* and can have their own monitor {@link Object#wait wait} and
- * {@link Object#notify notification} methods invoked.
+ * {@link Object#notify notify} methods invoked.
* Acquiring the monitor lock of a {@code Condition} instance, or using its
* monitor methods, has no specified relationship with acquiring the
* {@link Lock} associated with that {@code Condition} or the use of its
@@ -308,7 +309,7 @@
* condition still does not hold. Typical uses of this method take
* the following form:
*
- * <pre> {@code
+ * <pre> {@code
* boolean aMethod(long timeout, TimeUnit unit) {
* long nanos = unit.toNanos(timeout);
* lock.lock();
@@ -361,7 +362,7 @@
* Causes the current thread to wait until it is signalled or interrupted,
* or the specified waiting time elapses. This method is behaviorally
* equivalent to:
- * <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre>
+ * <pre> {@code awaitNanos(unit.toNanos(time)) > 0}</pre>
*
* @param time the maximum time to wait
* @param unit the time unit of the {@code time} argument
@@ -410,7 +411,7 @@
*
* <p>The return value indicates whether the deadline has elapsed,
* which can be used as follows:
- * <pre> {@code
+ * <pre> {@code
* boolean aMethod(Date deadline) {
* boolean stillWaiting = true;
* lock.lock();
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/Lock.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/Lock.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,6 +34,7 @@
*/
package java.util.concurrent.locks;
+
import java.util.concurrent.TimeUnit;
/**
@@ -77,7 +78,7 @@
* methods and statements. In most cases, the following idiom
* should be used:
*
- * <pre> {@code
+ * <pre> {@code
* Lock l = ...;
* l.lock();
* try {
@@ -121,8 +122,9 @@
* <p>All {@code Lock} implementations <em>must</em> enforce the same
* memory synchronization semantics as provided by the built-in monitor
* lock, as described in
- * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
- * The Java Language Specification (17.4 Memory Model)</a>:
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
+ * Chapter 17 of
+ * <cite>The Java™ Language Specification</cite></a>:
* <ul>
* <li>A successful {@code lock} operation has the same memory
* synchronization effects as a successful <em>Lock</em> action.
@@ -240,7 +242,7 @@
* immediately with the value {@code false}.
*
* <p>A typical usage idiom for this method would be:
- * <pre> {@code
+ * <pre> {@code
* Lock lock = ...;
* if (lock.tryLock()) {
* try {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,7 +34,6 @@
*/
package java.util.concurrent.locks;
-import sun.misc.Unsafe;
/**
* Basic thread blocking primitives for creating locks and other
@@ -47,6 +46,10 @@
* it <em>may</em> block. A call to {@code unpark} makes the permit
* available, if it was not already available. (Unlike with Semaphores
* though, permits do not accumulate. There is at most one.)
+ * Reliable usage requires the use of volatile (or atomic) variables
+ * to control when to park or unpark. Orderings of calls to these
+ * methods are maintained with respect to volatile variable accesses,
+ * but not necessarily non-volatile variable accesses.
*
* <p>Methods {@code park} and {@code unpark} provide efficient
* means of blocking and unblocking threads that do not encounter the
@@ -77,7 +80,7 @@
* useful for most concurrency control applications. The {@code park}
* method is designed for use only in constructions of the form:
*
- * <pre> {@code
+ * <pre> {@code
* while (!canProceed()) { ... LockSupport.park(this); }}</pre>
*
* where neither {@code canProceed} nor any other actions prior to the
@@ -87,11 +90,11 @@
*
* <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
* non-reentrant lock class:
- * <pre> {@code
+ * <pre> {@code
* class FIFOMutex {
* private final AtomicBoolean locked = new AtomicBoolean(false);
* private final Queue<Thread> waiters
- * = new ConcurrentLinkedQueue<Thread>();
+ * = new ConcurrentLinkedQueue<>();
*
* public void lock() {
* boolean wasInterrupted = false;
@@ -122,7 +125,7 @@
private static void setBlocker(Thread t, Object arg) {
// Even though volatile, hotspot doesn't need a write barrier here.
- UNSAFE.putObject(t, parkBlockerOffset, arg);
+ U.putObject(t, PARKBLOCKER, arg);
}
/**
@@ -138,7 +141,7 @@
*/
public static void unpark(Thread thread) {
if (thread != null)
- UNSAFE.unpark(thread);
+ U.unpark(thread);
}
/**
@@ -172,7 +175,7 @@
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
- UNSAFE.park(false, 0L);
+ U.park(false, 0L);
setBlocker(t, null);
}
@@ -212,7 +215,7 @@
if (nanos > 0) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
- UNSAFE.park(false, nanos);
+ U.park(false, nanos);
setBlocker(t, null);
}
}
@@ -253,7 +256,7 @@
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
- UNSAFE.park(true, deadline);
+ U.park(true, deadline);
setBlocker(t, null);
}
@@ -272,7 +275,7 @@
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
- return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
+ return U.getObjectVolatile(t, PARKBLOCKER);
}
/**
@@ -301,7 +304,7 @@
* for example, the interrupt status of the thread upon return.
*/
public static void park() {
- UNSAFE.park(false, 0L);
+ U.park(false, 0L);
}
/**
@@ -335,7 +338,7 @@
*/
public static void parkNanos(long nanos) {
if (nanos > 0)
- UNSAFE.park(false, nanos);
+ U.park(false, nanos);
}
/**
@@ -369,7 +372,7 @@
* to wait until
*/
public static void parkUntil(long deadline) {
- UNSAFE.park(true, deadline);
+ U.park(true, deadline);
}
/**
@@ -379,36 +382,30 @@
static final int nextSecondarySeed() {
int r;
Thread t = Thread.currentThread();
- if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
+ if ((r = U.getInt(t, SECONDARY)) != 0) {
r ^= r << 13; // xorshift
r ^= r >>> 17;
r ^= r << 5;
}
else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
r = 1; // avoid zero
- UNSAFE.putInt(t, SECONDARY, r);
+ U.putInt(t, SECONDARY, r);
return r;
}
// Hotspot implementation via intrinsics API
- private static final sun.misc.Unsafe UNSAFE;
- private static final long parkBlockerOffset;
- private static final long SEED;
- private static final long PROBE;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long PARKBLOCKER;
private static final long SECONDARY;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> tk = Thread.class;
- parkBlockerOffset = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("parkBlocker"));
- SEED = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomSeed"));
- PROBE = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomProbe"));
- SECONDARY = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
- } catch (Exception ex) { throw new Error(ex); }
+ PARKBLOCKER = U.objectFieldOffset
+ (Thread.class.getDeclaredField("parkBlocker"));
+ SECONDARY = U.objectFieldOffset
+ (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java Tue Oct 20 08:24:37 2015 -0700
@@ -38,9 +38,9 @@
/**
* A {@code ReadWriteLock} maintains a pair of associated {@link
* Lock locks}, one for read-only operations and one for writing.
- * The {@link #readLock read lock} may be held simultaneously by
- * multiple reader threads, so long as there are no writers. The
- * {@link #writeLock write lock} is exclusive.
+ * The {@linkplain #readLock read lock} may be held simultaneously
+ * by multiple reader threads, so long as there are no writers.
+ * The {@linkplain #writeLock write lock} is exclusive.
*
* <p>All {@code ReadWriteLock} implementations must guarantee that
* the memory synchronization effects of {@code writeLock} operations
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,8 +34,9 @@
*/
package java.util.concurrent.locks;
+
+import java.util.Collection;
import java.util.concurrent.TimeUnit;
-import java.util.Collection;
/**
* A reentrant mutual exclusion {@link Lock} with the same basic
@@ -72,7 +73,7 @@
* follow a call to {@code lock} with a {@code try} block, most
* typically in a before/after construction such as:
*
- * <pre> {@code
+ * <pre> {@code
* class X {
* private final ReentrantLock lock = new ReentrantLock();
* // ...
@@ -378,7 +379,7 @@
* method. If you want a timed {@code tryLock} that does permit barging on
* a fair lock then combine the timed and un-timed forms together:
*
- * <pre> {@code
+ * <pre> {@code
* if (lock.tryLock() ||
* lock.tryLock(timeout, unit)) {
* ...
@@ -484,7 +485,7 @@
* InterruptedException} will be thrown, and the thread's
* interrupted status will be cleared.
*
- * <li> Waiting threads are signalled in FIFO order.
+ * <li>Waiting threads are signalled in FIFO order.
*
* <li>The ordering of lock reacquisition for threads returning
* from waiting methods is the same as for threads initially
@@ -511,7 +512,7 @@
* not be entered with the lock already held then we can assert that
* fact:
*
- * <pre> {@code
+ * <pre> {@code
* class X {
* ReentrantLock lock = new ReentrantLock();
* // ...
@@ -541,7 +542,7 @@
* debugging and testing. For example, a method that should only be
* called while a lock is held can assert that this is the case:
*
- * <pre> {@code
+ * <pre> {@code
* class X {
* ReentrantLock lock = new ReentrantLock();
* // ...
@@ -555,7 +556,7 @@
* <p>It can also be used to ensure that a reentrant lock is used
* in a non-reentrant manner, for example:
*
- * <pre> {@code
+ * <pre> {@code
* class X {
* ReentrantLock lock = new ReentrantLock();
* // ...
@@ -646,12 +647,11 @@
}
/**
- * Returns an estimate of the number of threads waiting to
- * acquire this lock. The value is only an estimate because the number of
+ * Returns an estimate of the number of threads waiting to acquire
+ * this lock. The value is only an estimate because the number of
* threads may change dynamically while this method traverses
* internal data structures. This method is designed for use in
- * monitoring of the system state, not for synchronization
- * control.
+ * monitoring system state, not for synchronization control.
*
* @return the estimated number of threads waiting for this lock
*/
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,8 +34,9 @@
*/
package java.util.concurrent.locks;
+
+import java.util.Collection;
import java.util.concurrent.TimeUnit;
-import java.util.Collection;
/**
* An implementation of {@link ReadWriteLock} supporting similar
@@ -51,14 +52,16 @@
*
* <dl>
* <dt><b><i>Non-fair mode (default)</i></b>
- * <dd>When constructed as non-fair (the default), the order of entry
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * When constructed as non-fair (the default), the order of entry
* to the read and write lock is unspecified, subject to reentrancy
* constraints. A nonfair lock that is continuously contended may
* indefinitely postpone one or more reader or writer threads, but
* will normally have higher throughput than a fair lock.
*
* <dt><b><i>Fair mode</i></b>
- * <dd>When constructed as fair, threads contend for entry using an
+ * <dd style="font-family:'DejaVu Sans', Arial, Helvetica, sans-serif">
+ * When constructed as fair, threads contend for entry using an
* approximately arrival-order policy. When the currently held lock
* is released, either the longest-waiting single writer thread will
* be assigned the write lock, or if there is a group of reader threads
@@ -173,9 +176,9 @@
* is a class using a TreeMap that is expected to be large and
* concurrently accessed.
*
- * <pre> {@code
+ * <pre> {@code
* class RWDictionary {
- * private final Map<String, Data> m = new TreeMap<String, Data>();
+ * private final Map<String, Data> m = new TreeMap<>();
* private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
* private final Lock r = rwl.readLock();
* private final Lock w = rwl.writeLock();
@@ -263,17 +266,17 @@
static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
- /** Returns the number of shared holds represented in count */
+ /** Returns the number of shared holds represented in count. */
static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
- /** Returns the number of exclusive holds represented in count */
+ /** Returns the number of exclusive holds represented in count. */
static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
/**
* A counter for per-thread read hold counts.
- * Maintained as a ThreadLocal; cached in cachedHoldCounter
+ * Maintained as a ThreadLocal; cached in cachedHoldCounter.
*/
static final class HoldCounter {
- int count = 0;
+ int count; // initially 0
// Use id, not reference, to avoid garbage retention
final long tid = getThreadId(Thread.currentThread());
}
@@ -330,7 +333,7 @@
* <p>This allows tracking of read holds for uncontended read
* locks to be very cheap.
*/
- private transient Thread firstReader = null;
+ private transient Thread firstReader;
private transient int firstReaderHoldCount;
Sync() {
@@ -703,7 +706,7 @@
private final Sync sync;
/**
- * Constructor for use by subclasses
+ * Constructor for use by subclasses.
*
* @param lock the outer lock object
* @throws NullPointerException if the lock is null
@@ -814,7 +817,7 @@
* permit barging on a fair lock then combine the timed and
* un-timed forms together:
*
- * <pre> {@code
+ * <pre> {@code
* if (lock.tryLock() ||
* lock.tryLock(timeout, unit)) {
* ...
@@ -874,7 +877,12 @@
* Attempts to release this lock.
*
* <p>If the number of readers is now zero then the lock
- * is made available for write lock attempts.
+ * is made available for write lock attempts. If the current
+ * thread does not hold this lock then {@link
+ * IllegalMonitorStateException} is thrown.
+ *
+ * @throws IllegalMonitorStateException if the current thread
+ * does not hold this lock
*/
public void unlock() {
sync.releaseShared(1);
@@ -912,7 +920,7 @@
private final Sync sync;
/**
- * Constructor for use by subclasses
+ * Constructor for use by subclasses.
*
* @param lock the outer lock object
* @throws NullPointerException if the lock is null
@@ -1026,7 +1034,7 @@
* by the current thread, or the write lock was already held
* by the current thread; and {@code false} otherwise.
*/
- public boolean tryLock( ) {
+ public boolean tryLock() {
return sync.tryWriteLock();
}
@@ -1046,7 +1054,7 @@
* that does permit barging on a fair lock then combine the
* timed and un-timed forms together:
*
- * <pre> {@code
+ * <pre> {@code
* if (lock.tryLock() ||
* lock.tryLock(timeout, unit)) {
* ...
@@ -1161,7 +1169,7 @@
* InterruptedException} will be thrown, and the thread's
* interrupted status will be cleared.
*
- * <li> Waiting threads are signalled in FIFO order.
+ * <li>Waiting threads are signalled in FIFO order.
*
* <li>The ordering of lock reacquisition for threads returning
* from waiting methods is the same as for threads initially
@@ -1369,7 +1377,7 @@
* either the read or write lock. The value is only an estimate
* because the number of threads may change dynamically while this
* method traverses internal data structures. This method is
- * designed for use in monitoring of the system state, not for
+ * designed for use in monitoring system state, not for
* synchronization control.
*
* @return the estimated number of threads waiting for this lock
@@ -1489,19 +1497,17 @@
* ways that do not preserve unique mappings.
*/
static final long getThreadId(Thread thread) {
- return UNSAFE.getLongVolatile(thread, TID_OFFSET);
+ return U.getLongVolatile(thread, TID);
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long TID_OFFSET;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
+ private static final long TID;
static {
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> tk = Thread.class;
- TID_OFFSET = UNSAFE.objectFieldOffset
- (tk.getDeclaredField("tid"));
- } catch (Exception e) {
+ TID = U.objectFieldOffset
+ (Thread.class.getDeclaredField("tid"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,10 +36,6 @@
package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.LockSupport;
/**
* A capability-based lock with three modes for controlling read/write
@@ -58,12 +54,12 @@
* in method {@link #unlockWrite} to release the lock. Untimed and
* timed versions of {@code tryWriteLock} are also provided. When
* the lock is held in write mode, no read locks may be obtained,
- * and all optimistic read validations will fail. </li>
+ * and all optimistic read validations will fail.
*
* <li><b>Reading.</b> Method {@link #readLock} possibly blocks
* waiting for non-exclusive access, returning a stamp that can be
* used in method {@link #unlockRead} to release the lock. Untimed
- * and timed versions of {@code tryReadLock} are also provided. </li>
+ * and timed versions of {@code tryReadLock} are also provided.
*
* <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
* returns a non-zero stamp only if the lock is not currently held
@@ -81,7 +77,7 @@
* invoke method {@code validate()}. For example, such steps are
* typically required when first reading an object or array
* reference, and then accessing one of its fields, elements or
- * methods. </li>
+ * methods.
*
* </ul>
*
@@ -132,7 +128,7 @@
* not strictly needed here because no exceptions can occur in their
* bodies.<br>
*
- * <pre>{@code
+ * <pre> {@code
* class Point {
* private double x, y;
* private final StampedLock sl = new StampedLock();
@@ -542,7 +538,7 @@
WNode h;
if (state != stamp || (stamp & WBIT) == 0L)
throw new IllegalMonitorStateException();
- state = (stamp += WBIT) == 0L ? ORIGIN : stamp;
+ U.putLongVolatile(this, STATE, (stamp += WBIT) == 0L ? ORIGIN : stamp);
if ((h = whead) != null && h.status != 0)
release(h);
}
@@ -589,7 +585,7 @@
else if (m == WBIT) {
if (a != m)
break;
- state = (s += WBIT) == 0L ? ORIGIN : s;
+ U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
if ((h = whead) != null && h.status != 0)
release(h);
return;
@@ -610,7 +606,7 @@
}
/**
- * If the lock state matches the given stamp, performs one of
+ * If the lock state matches the given stamp, atomically performs one of
* the following actions. If the stamp represents holding a write
* lock, returns it. Or, if a read lock, if the write lock is
* available, releases the read lock and returns a write stamp.
@@ -647,7 +643,7 @@
}
/**
- * If the lock state matches the given stamp, performs one of
+ * If the lock state matches the given stamp, atomically performs one of
* the following actions. If the stamp represents holding a write
* lock, releases it and obtains a read lock. Or, if a read lock,
* returns it. Or, if an optimistic read, acquires a read lock and
@@ -673,7 +669,7 @@
else if (m == WBIT) {
if (a != m)
break;
- state = next = s + (WBIT + RUNIT);
+ U.putLongVolatile(this, STATE, next = s + (WBIT + RUNIT));
if ((h = whead) != null && h.status != 0)
release(h);
return next;
@@ -687,7 +683,7 @@
}
/**
- * If the lock state matches the given stamp then, if the stamp
+ * If the lock state matches the given stamp then, atomically, if the stamp
* represents holding a lock, releases it and returns an
* observation stamp. Or, if an optimistic read, returns it if
* validated. This method returns zero in all other cases, and so
@@ -710,7 +706,8 @@
else if (m == WBIT) {
if (a != m)
break;
- state = next = (s += WBIT) == 0L ? ORIGIN : s;
+ U.putLongVolatile(this, STATE,
+ next = (s += WBIT) == 0L ? ORIGIN : s);
if ((h = whead) != null && h.status != 0)
release(h);
return next;
@@ -740,7 +737,7 @@
public boolean tryUnlockWrite() {
long s; WNode h;
if (((s = state) & WBIT) != 0L) {
- state = (s += WBIT) == 0L ? ORIGIN : s;
+ U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
if ((h = whead) != null && h.status != 0)
release(h);
return true;
@@ -923,7 +920,7 @@
WNode h; long s;
if (((s = state) & WBIT) == 0L)
throw new IllegalMonitorStateException();
- state = (s += WBIT) == 0L ? ORIGIN : s;
+ U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
if ((h = whead) != null && h.status != 0)
release(h);
}
@@ -948,7 +945,7 @@
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
- state = ORIGIN; // reset to unlocked state
+ U.putLongVolatile(this, STATE, ORIGIN); // reset to unlocked state
}
// internals
@@ -966,7 +963,7 @@
if ((s & ABITS) == RFULL) {
if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
++readerOverflow;
- state = s;
+ U.putLongVolatile(this, STATE, s);
return s;
}
}
@@ -993,8 +990,8 @@
}
else
next = s - RUNIT;
- state = next;
- return next;
+ U.putLongVolatile(this, STATE, next);
+ return next;
}
}
else if ((LockSupport.nextSecondarySeed() &
@@ -1062,6 +1059,7 @@
}
}
+ boolean wasInterrupted = false;
for (int spins = -1;;) {
WNode h, np, pp; int ps;
if ((h = whead) == p) {
@@ -1076,6 +1074,8 @@
ns = s + WBIT)) {
whead = node;
node.prev = null;
+ if (wasInterrupted)
+ Thread.currentThread().interrupt();
return ns;
}
}
@@ -1119,8 +1119,11 @@
U.park(false, time); // emulate LockSupport.park
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
- if (interruptible && Thread.interrupted())
- return cancelWaiter(node, node, true);
+ if (Thread.interrupted()) {
+ if (interruptible)
+ return cancelWaiter(node, node, true);
+ wasInterrupted = true;
+ }
}
}
}
@@ -1136,6 +1139,7 @@
* @return next state, or INTERRUPTED
*/
private long acquireRead(boolean interruptible, long deadline) {
+ boolean wasInterrupted = false;
WNode node = null, p;
for (int spins = -1;;) {
WNode h;
@@ -1143,8 +1147,11 @@
for (long m, s, ns;;) {
if ((m = (s = state) & ABITS) < RFULL ?
U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
- (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
+ (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
+ if (wasInterrupted)
+ Thread.currentThread().interrupt();
return ns;
+ }
else if (m >= WBIT) {
if (spins > 0) {
if (LockSupport.nextSecondarySeed() >= 0)
@@ -1193,8 +1200,11 @@
U.compareAndSwapLong(this, STATE, s,
ns = s + RUNIT) :
(m < WBIT &&
- (ns = tryIncReaderOverflow(s)) != 0L))
+ (ns = tryIncReaderOverflow(s)) != 0L)) {
+ if (wasInterrupted)
+ Thread.currentThread().interrupt();
return ns;
+ }
} while (m < WBIT);
}
if (whead == h && p.prev == pp) {
@@ -1205,8 +1215,11 @@
}
if (deadline == 0L)
time = 0L;
- else if ((time = deadline - System.nanoTime()) <= 0L)
+ else if ((time = deadline - System.nanoTime()) <= 0L) {
+ if (wasInterrupted)
+ Thread.currentThread().interrupt();
return cancelWaiter(node, p, false);
+ }
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
@@ -1215,8 +1228,11 @@
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
- if (interruptible && Thread.interrupted())
- return cancelWaiter(node, p, true);
+ if (Thread.interrupted()) {
+ if (interruptible)
+ return cancelWaiter(node, p, true);
+ wasInterrupted = true;
+ }
}
}
}
@@ -1243,6 +1259,8 @@
(w = c.thread) != null)
U.unpark(w);
}
+ if (wasInterrupted)
+ Thread.currentThread().interrupt();
return ns;
}
else if (m >= WBIT &&
@@ -1286,8 +1304,11 @@
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
- if (interruptible && Thread.interrupted())
- return cancelWaiter(node, node, true);
+ if (Thread.interrupted()) {
+ if (interruptible)
+ return cancelWaiter(node, node, true);
+ wasInterrupted = true;
+ }
}
}
}
@@ -1377,7 +1398,7 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe U;
+ private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final long STATE;
private static final long WHEAD;
private static final long WTAIL;
@@ -1388,26 +1409,23 @@
static {
try {
- U = sun.misc.Unsafe.getUnsafe();
- Class<?> k = StampedLock.class;
- Class<?> wk = WNode.class;
STATE = U.objectFieldOffset
- (k.getDeclaredField("state"));
+ (StampedLock.class.getDeclaredField("state"));
WHEAD = U.objectFieldOffset
- (k.getDeclaredField("whead"));
+ (StampedLock.class.getDeclaredField("whead"));
WTAIL = U.objectFieldOffset
- (k.getDeclaredField("wtail"));
+ (StampedLock.class.getDeclaredField("wtail"));
+
WSTATUS = U.objectFieldOffset
- (wk.getDeclaredField("status"));
+ (WNode.class.getDeclaredField("status"));
WNEXT = U.objectFieldOffset
- (wk.getDeclaredField("next"));
+ (WNode.class.getDeclaredField("next"));
WCOWAIT = U.objectFieldOffset
- (wk.getDeclaredField("cowait"));
- Class<?> tk = Thread.class;
+ (WNode.class.getDeclaredField("cowait"));
+
PARKBLOCKER = U.objectFieldOffset
- (tk.getDeclaredField("parkBlocker"));
-
- } catch (Exception e) {
+ (Thread.class.getDeclaredField("parkBlocker"));
+ } catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
--- a/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java Tue Oct 20 08:24:37 2015 -0700
@@ -226,8 +226,9 @@
*
* <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
*
- * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5">
- * Chapter 17 of the Java Language Specification</a> defines the
+ * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.5">
+ * Chapter 17 of
+ * <cite>The Java™ Language Specification</cite></a> defines the
* <i>happens-before</i> relation on memory operations such as reads and
* writes of shared variables. The results of a write by one thread are
* guaranteed to be visible to a read by another thread only if the write
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Tue Oct 20 08:24:37 2015 -0700
@@ -438,10 +438,19 @@
private byte[] getBytes(ZipEntry ze) throws IOException {
try (InputStream is = super.getInputStream(ze)) {
int len = (int)ze.getSize();
- byte[] b = is.readAllBytes();
- if (len != -1 && b.length != len)
- throw new EOFException("Expected:" + len + ", read:" + b.length);
-
+ int bytesRead;
+ byte[] b;
+ // trust specified entry sizes when reasonably small
+ if (len != -1 && len <= 65535) {
+ b = new byte[len];
+ bytesRead = is.readNBytes(b, 0, len);
+ } else {
+ b = is.readAllBytes();
+ bytesRead = b.length;
+ }
+ if (len != -1 && len != bytesRead) {
+ throw new EOFException("Expected:" + len + ", read:" + bytesRead);
+ }
return b;
}
}
--- a/jdk/src/java.base/share/classes/java/util/zip/Deflater.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/zip/Deflater.java Tue Oct 20 08:24:37 2015 -0700
@@ -318,7 +318,9 @@
* should be called in order to provide more input
*/
public boolean needsInput() {
- return len <= 0;
+ synchronized (zsRef) {
+ return len <= 0;
+ }
}
/**
--- a/jdk/src/java.base/share/classes/java/util/zip/ZStreamRef.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZStreamRef.java Tue Oct 20 08:24:37 2015 -0700
@@ -31,7 +31,7 @@
class ZStreamRef {
- private long address;
+ private volatile long address;
ZStreamRef (long address) {
this.address = address;
}
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java Tue Oct 20 08:24:37 2015 -0700
@@ -60,7 +60,7 @@
*/
public
class ZipFile implements ZipConstants, Closeable {
- private long jzfile; // address of jzfile data
+ private long jzfile; // address of jzfile data
private final String name; // zip file name
private final int total; // total number of entries
private final boolean locsig; // if zip file starts with LOCSIG (usually true)
@@ -691,7 +691,7 @@
* (possibly compressed) zip file entry.
*/
private class ZipFileInputStream extends InputStream {
- private volatile boolean closeRequested = false;
+ private volatile boolean zfisCloseRequested = false;
protected long jzentry; // address of jzentry data
private long pos; // current position within entry data
protected long rem; // number of remaining bytes within entry
@@ -718,6 +718,7 @@
len = (int) rem;
}
+ // Check if ZipFile open
ensureOpenOrZipException();
len = ZipFile.read(ZipFile.this.jzfile, jzentry, pos, b,
off, len);
@@ -761,9 +762,9 @@
}
public void close() {
- if (closeRequested)
+ if (zfisCloseRequested)
return;
- closeRequested = true;
+ zfisCloseRequested = true;
rem = 0;
synchronized (ZipFile.this) {
--- a/jdk/src/java.base/share/classes/javax/crypto/Cipher.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/Cipher.java Tue Oct 20 08:24:37 2015 -0700
@@ -478,6 +478,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param transformation the name of the transformation, e.g.,
* <i>DES/CBC/PKCS5Padding</i>.
* See the Cipher section in the <a href=
--- a/jdk/src/java.base/share/classes/javax/crypto/ExemptionMechanism.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/ExemptionMechanism.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested exemption
* mechanism.
* See the ExemptionMechanism section in the
--- a/jdk/src/java.base/share/classes/javax/crypto/KeyAgreement.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/KeyAgreement.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -150,6 +150,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested key agreement
* algorithm.
* See the KeyAgreement section in the <a href=
--- a/jdk/src/java.base/share/classes/javax/crypto/KeyGenerator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/KeyGenerator.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -202,6 +202,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested key algorithm.
* See the KeyGenerator section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#KeyGenerator">
--- a/jdk/src/java.base/share/classes/javax/crypto/Mac.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/Mac.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -152,6 +152,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested MAC algorithm.
* See the Mac section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Mac">
--- a/jdk/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -137,6 +137,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested secret-key
* algorithm.
* See the SecretKeyFactory section in the <a href=
--- a/jdk/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -116,6 +116,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested algorithm.
* See the <a href=
* "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java Tue Oct 20 08:24:37 2015 -0700
@@ -136,6 +136,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param protocol the standard name of the requested protocol.
* See the SSLContext section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#SSLContext">
--- a/jdk/src/java.base/share/classes/javax/net/ssl/TrustManagerFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/TrustManagerFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -130,6 +130,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the standard name of the requested trust management
* algorithm. See the <a href=
* "{@docRoot}/../technotes/guides/security/jsse/JSSERefGuide.html">
--- a/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java Tue Oct 20 08:24:37 2015 -0700
@@ -311,6 +311,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param type the specified Configuration type. See the Configuration
* section in the <a href=
* "{@docRoot}/../technotes/guides/security/StandardNames.html#Configuration">
--- a/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,14 +37,20 @@
private BytecodeDescriptor() { } // cannot instantiate
+ /**
+ * @param loader the class loader in which to look up the types (null means
+ * bootstrap class loader)
+ */
public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
}
+ /**
+ * @param loader the class loader in which to look up the types (null means
+ * bootstrap class loader)
+ */
static List<Class<?>> parseMethod(String bytecodeSignature,
int start, int end, ClassLoader loader) {
- if (loader == null)
- loader = ClassLoader.getSystemClassLoader();
String str = bytecodeSignature;
int[] i = {start};
ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
@@ -71,6 +77,10 @@
throw new IllegalArgumentException("bad signature: "+str+": "+msg);
}
+ /**
+ * @param loader the class loader in which to look up the types (null means
+ * bootstrap class loader)
+ */
private static Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
if (i[0] == end) return null;
char c = str.charAt(i[0]++);
@@ -80,7 +90,9 @@
i[0] = endc+1;
String name = str.substring(begc, endc).replace('/', '.');
try {
- return loader.loadClass(name);
+ return (loader == null)
+ ? Class.forName(name, false, null)
+ : loader.loadClass(name);
} catch (ClassNotFoundException ex) {
throw new TypeNotPresentException(name, ex);
}
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderList.java Tue Oct 20 08:24:37 2015 -0700
@@ -27,8 +27,11 @@
import java.util.*;
-import java.security.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Provider;
import java.security.Provider.Service;
+import java.security.Security;
/**
* List of Providers. Used to represent the provider preferences.
@@ -65,6 +68,9 @@
// constant for an ProviderList with no elements
static final ProviderList EMPTY = new ProviderList(PC0, true);
+ // list of all jdk.security.provider.preferred entries
+ static private PreferredList preferredPropList = null;
+
// dummy provider object to use during initialization
// used to avoid explicit null checks in various places
private static final Provider EMPTY_PROVIDER =
@@ -162,11 +168,10 @@
*/
private ProviderList() {
List<ProviderConfig> configList = new ArrayList<>();
- for (int i = 1; true; i++) {
- String entry = Security.getProperty("security.provider." + i);
- if (entry == null) {
- break;
- }
+ String entry;
+ int i = 1;
+
+ while ((entry = Security.getProperty("security.provider." + i)) != null) {
entry = entry.trim();
if (entry.length() == 0) {
System.err.println("invalid entry for " +
@@ -187,10 +192,36 @@
if (configList.contains(config) == false) {
configList.add(config);
}
+ i++;
}
configs = configList.toArray(PC0);
+
+ // Load config entries for use when getInstance is called
+ entry = Security.getProperty("jdk.security.provider.preferred");
+ if (entry != null && (entry = entry.trim()).length() > 0) {
+ String[] entries = entry.split(",");
+ if (ProviderList.preferredPropList == null) {
+ ProviderList.preferredPropList = new PreferredList();
+ }
+
+ for (String e : entries) {
+ i = e.indexOf(':');
+ if (i < 0) {
+ if (debug != null) {
+ debug.println("invalid preferred entry skipped. " +
+ "Missing colon delimiter \"" + e + "\"");
+ }
+ continue;
+ }
+ ProviderList.preferredPropList.add(new PreferredEntry(
+ e.substring(0, i).trim(), e.substring(i + 1).trim()));
+ }
+ }
+
if (debug != null) {
debug.println("provider configuration: " + configList);
+ debug.println("config configuration: " +
+ ProviderList.preferredPropList);
}
}
@@ -327,7 +358,22 @@
* algorithm.
*/
public Service getService(String type, String name) {
- for (int i = 0; i < configs.length; i++) {
+ ArrayList<PreferredEntry> pList = null;
+ int i;
+
+ // Preferred provider list
+ if (preferredPropList != null &&
+ (pList = preferredPropList.getAll(type, name)) != null) {
+ for (i = 0; i < pList.size(); i++) {
+ Provider p = getProvider(pList.get(i).provider);
+ Service s = p.getService(type, name);
+ if (s != null) {
+ return s;
+ }
+ }
+ }
+
+ for (i = 0; i < configs.length; i++) {
Provider p = getProvider(i);
Service s = p.getService(type, name);
if (s != null) {
@@ -394,7 +440,11 @@
private List<Service> services;
// index into config[] of the next provider we need to query
- private int providerIndex;
+ private int providerIndex = 0;
+
+ // Matching preferred provider list for this ServiceList
+ ArrayList<PreferredEntry> preferredList = null;
+ private int preferredIndex = 0;
ServiceList(String type, String algorithm) {
this.type = type;
@@ -421,6 +471,14 @@
}
private Service tryGet(int index) {
+ Provider p;
+
+ // If preferred providers are configured, check for matches with
+ // the requested service.
+ if (preferredPropList != null && preferredList == null) {
+ preferredList = preferredPropList.getAll(this);
+ }
+
while (true) {
if ((index == 0) && (firstService != null)) {
return firstService;
@@ -430,8 +488,27 @@
if (providerIndex >= configs.length) {
return null;
}
- // check all algorithms in this provider before moving on
- Provider p = getProvider(providerIndex++);
+
+ // If there were matches with a preferred provider, iterate
+ // through the list first before going through the
+ // ordered list (java.security.provider.#)
+ if (preferredList != null &&
+ preferredIndex < preferredList.size()) {
+ PreferredEntry entry = preferredList.get(preferredIndex++);
+ // Look for the provider name in the PreferredEntry
+ p = getProvider(entry.provider);
+ if (p == null) {
+ if (debug != null) {
+ debug.println("No provider found with name: " +
+ entry.provider);
+ }
+ continue;
+ }
+ } else {
+ // check all algorithms in this provider before moving on
+ p = getProvider(providerIndex++);
+ }
+
if (type != null) {
// simple lookup
Service s = p.getService(type, algorithm);
@@ -502,4 +579,119 @@
}
}
+ // Provider list defined by jdk.security.provider.preferred entry
+ static final class PreferredList {
+ ArrayList<PreferredEntry> list = new ArrayList<PreferredEntry>();
+
+ /*
+ * Return a list of all preferred entries that match the passed
+ * ServiceList.
+ */
+ ArrayList<PreferredEntry> getAll(ServiceList s) {
+ if (s.ids == null) {
+ return getAll(s.type, s.algorithm);
+
+ }
+
+ ArrayList<PreferredEntry> l = new ArrayList<PreferredEntry>();
+ for (ServiceId id : s.ids) {
+ implGetAll(l, id.type, id.algorithm);
+ }
+
+ return l;
+ }
+
+ /*
+ * Return a list of all preferred entries that match the passed
+ * type and algorithm.
+ */
+ ArrayList<PreferredEntry> getAll(String type, String algorithm) {
+ ArrayList<PreferredEntry> l = new ArrayList<PreferredEntry>();
+ implGetAll(l, type, algorithm);
+ return l;
+ }
+
+ /*
+ * Compare each preferred entry against the passed type and
+ * algorithm, putting any matches in the passed ArrayList.
+ */
+ private void implGetAll(ArrayList<PreferredEntry> l, String type,
+ String algorithm) {
+ PreferredEntry e;
+
+ for (int i = 0; i < size(); i++) {
+ e = list.get(i);
+ if (e.match(type, algorithm)) {
+ l.add(e);
+ }
+ }
+ }
+
+ public PreferredEntry get(int i) {
+ return list.get(i);
+ }
+
+ public int size() {
+ return list.size();
+ }
+
+ public boolean add(PreferredEntry e) {
+ return list.add(e);
+ }
+
+ public String toString() {
+ String s = "";
+ for (PreferredEntry e: list) {
+ s += e.toString();
+ }
+ return s;
+ }
+ }
+
+ // Individual preferred property entry from jdk.security.provider.preferred
+ private class PreferredEntry {
+ String type = null;
+ String algorithm;
+ String provider;
+
+ PreferredEntry(String t, String p) {
+ int i = t.indexOf('.');
+ if (i > 0) {
+ type = t.substring(0, i);
+ algorithm = t.substring(i + 1);
+ } else {
+ algorithm = t;
+ }
+
+ provider = p;
+ }
+
+ boolean match(String t, String a) {
+ if (debug != null) {
+ debug.println("Config match: " + toString() + " == [" + t +
+ ", " + a + "]");
+ }
+
+ // Compare service type if configured
+ if (type != null && type.compareToIgnoreCase(t) != 0) {
+ return false;
+ }
+
+ // Compare the algorithm string.
+ if (a.compareToIgnoreCase(algorithm) == 0) {
+ if (debug != null) {
+ debug.println("Config entry found: " + toString());
+ }
+ return true;
+ }
+
+ // No match
+ return false;
+ }
+
+ public String toString() {
+ return "[" + type + ", " + algorithm + " : " + provider + "] ";
+ }
+ }
+
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Tue Oct 20 08:24:37 2015 -0700
@@ -350,8 +350,6 @@
private static void add(String name, int id, int priority,
KeyExchange keyExchange, BulkCipher cipher, MacAlg mac,
boolean allowed, int obsoleted) {
- // If this is an obsoleted suite, then don't let the TLS 1.2
- // protocol have a valid PRF value.
PRF prf = obsoleted < ProtocolVersion.TLS12.v ? P_NONE : P_SHA256;
add(name, id, priority, keyExchange, cipher, mac, allowed, obsoleted,
Binary file jdk/src/java.base/share/classes/sun/text/resources/nfc.icu has changed
Binary file jdk/src/java.base/share/classes/sun/text/resources/nfkc.icu has changed
Binary file jdk/src/java.base/share/classes/sun/text/resources/nfkc_cf.icu has changed
Binary file jdk/src/java.base/share/classes/sun/text/resources/ubidi.icu has changed
Binary file jdk/src/java.base/share/classes/sun/text/resources/uprops.icu has changed
--- a/jdk/src/java.base/share/conf/security/java.security Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/conf/security/java.security Tue Oct 20 08:24:37 2015 -0700
@@ -90,6 +90,31 @@
security.provider.tbd=sun.security.pkcs11.SunPKCS11
#endif
+#
+# A list of preferred providers for specific algorithms. These providers will
+# be searched for matching algorithms before the list of registered providers.
+# Entries containing errors (parsing, etc) will be ignored. Use the
+# -Djava.security.debug=jca property to debug these errors.
+#
+# The property is a comma-separated list of serviceType.algorithm:provider
+# entries. The serviceType (example: "MessageDigest") is optional, and if
+# not specified, the algorithm applies to all service types that support it.
+# The algorithm is the standard algorithm name or transformation.
+# Transformations can be specified in their full standard name
+# (ex: AES/CBC/PKCS5Padding), or as partial matches (ex: AES, AES/CBC).
+# The provider is the name of the provider. Any provider that does not
+# also appear in the registered list will be ignored.
+#
+# Example:
+# jdk.security.provider.preferred=AES/GCM/NoPadding:SunJCE, \
+# MessageDigest.SHA-256:SUN
+#ifdef solaris-sparc
+jdk.security.provider.preferred=AES:SunJCE, SHA-256:SUN, SHA-384:SUN, SHA-512:SUN
+#endif
+#ifdef solaris-x86
+jdk.security.provider.preferred=AES:SunJCE, RSA:SunRsaSign
+#endif
+
#
# Sun Provider SecureRandom seed source.
--- a/jdk/src/java.base/share/native/libfdlibm/s_cbrt.c Tue Oct 13 14:59:44 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-
-/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "fdlibm.h"
-
-/* cbrt(x)
- * Return cube root of x
- */
-#ifdef __STDC__
-static const unsigned
-#else
-static unsigned
-#endif
- B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */
- B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
-
-#ifdef __STDC__
-static const double
-#else
-static double
-#endif
-C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */
-D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */
-E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */
-F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */
-G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */
-
-#ifdef __STDC__
- double cbrt(double x)
-#else
- double cbrt(x)
- double x;
-#endif
-{
- int hx;
- double r,s,t=0.0,w;
- unsigned sign;
-
-
- hx = __HI(x); /* high word of x */
- sign=hx&0x80000000; /* sign= sign(x) */
- hx ^=sign;
- if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */
- if((hx|__LO(x))==0)
- return(x); /* cbrt(0) is itself */
-
- __HI(x) = hx; /* x <- |x| */
- /* rough cbrt to 5 bits */
- if(hx<0x00100000) /* subnormal number */
- {__HI(t)=0x43500000; /* set t= 2**54 */
- t*=x; __HI(t)=__HI(t)/3+B2;
- }
- else
- __HI(t)=hx/3+B1;
-
-
- /* new cbrt to 23 bits, may be implemented in single precision */
- r=t*t/x;
- s=C+r*t;
- t*=G+F/(s+E+D/s);
-
- /* chopped to 20 bits and make it larger than cbrt(x) */
- __LO(t)=0; __HI(t)+=0x00000001;
-
-
- /* 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-s is exact */
- t=t+t*r;
-
- /* retore the sign bit */
- __HI(t) |= sign;
- return(t);
-}
--- a/jdk/src/java.base/share/native/libjava/StrictMath.c Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/native/libjava/StrictMath.c Tue Oct 20 08:24:37 2015 -0700
@@ -89,12 +89,6 @@
}
JNIEXPORT jdouble JNICALL
-Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d)
-{
- return (jdouble) jcbrt((double)d);
-}
-
-JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
{
return (jdouble) jatan2((double)d1, (double)d2);
--- a/jdk/src/java.base/share/native/libzip/zip_util.c Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.base/share/native/libzip/zip_util.c Tue Oct 20 08:24:37 2015 -0700
@@ -1302,12 +1302,23 @@
jint
ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
{
- jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size;
+ jlong entry_size;
jlong start;
+ if (zip == 0) {
+ return -1;
+ }
+
/* Clear previous zip error */
zip->msg = NULL;
+ if (entry == 0) {
+ zip->msg = "ZIP_Read: jzentry is NULL";
+ return -1;
+ }
+
+ entry_size = (entry->csize != 0) ? entry->csize : entry->size;
+
/* Check specified position */
if (pos < 0 || pos > entry_size - 1) {
zip->msg = "ZIP_Read: specified offset out of range";
@@ -1440,6 +1451,11 @@
char *msg;
char tmpbuf[1024];
+ if (entry == 0) {
+ jio_fprintf(stderr, "jzentry was invalid");
+ return JNI_FALSE;
+ }
+
strcpy(entryname, entry->name);
if (entry->csize == 0) {
/* Entry is stored */
--- a/jdk/src/java.desktop/share/classes/java/awt/font/NumericShaper.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/java/awt/font/NumericShaper.java Tue Oct 20 08:24:37 2015 -0700
@@ -672,7 +672,7 @@
0x0825, 0x0828,
0x0829, 0x082e,
0x0859, 0x085c,
- 0x08e4, 0x0903,
+ 0x08e3, 0x0903,
0x093a, 0x093b,
0x093c, 0x093d,
0x0941, 0x0949,
@@ -721,7 +721,8 @@
0x0acd, 0x0ad0,
0x0ad1, 0x0ae0,
0x0ae2, 0x0ae6,
- 0x0af1, 0x0b02,
+ 0x0af1, 0x0af9,
+ 0x0afa, 0x0b02,
0x0b04, 0x0b05,
0x0b0d, 0x0b0f,
0x0b11, 0x0b13,
@@ -761,7 +762,7 @@
0x0c3a, 0x0c3d,
0x0c3e, 0x0c41,
0x0c45, 0x0c58,
- 0x0c5a, 0x0c60,
+ 0x0c5b, 0x0c60,
0x0c62, 0x0c66,
0x0c70, 0x0c7f,
0x0c80, 0x0c82,
@@ -787,7 +788,7 @@
0x0d49, 0x0d4a,
0x0d4d, 0x0d4e,
0x0d4f, 0x0d57,
- 0x0d58, 0x0d60,
+ 0x0d58, 0x0d5f,
0x0d62, 0x0d66,
0x0d76, 0x0d79,
0x0d80, 0x0d82,
@@ -867,7 +868,8 @@
0x135b, 0x1360,
0x137d, 0x1380,
0x1390, 0x13a0,
- 0x13f5, 0x1401,
+ 0x13f6, 0x13f8,
+ 0x13fe, 0x1401,
0x1680, 0x1681,
0x169b, 0x16a0,
0x16f9, 0x1700,
@@ -1019,7 +1021,7 @@
0x33de, 0x33e0,
0x33ff, 0x3400,
0x4db6, 0x4e00,
- 0x9fcd, 0xa000,
+ 0x9fd6, 0xa000,
0xa48d, 0xa4d0,
0xa60d, 0xa610,
0xa62c, 0xa640,
@@ -1028,9 +1030,8 @@
0xa6f0, 0xa6f2,
0xa6f8, 0xa722,
0xa788, 0xa789,
- 0xa78f, 0xa790,
0xa7ae, 0xa7b0,
- 0xa7b2, 0xa7f7,
+ 0xa7b8, 0xa7f7,
0xa802, 0xa803,
0xa806, 0xa807,
0xa80b, 0xa80c,
@@ -1040,7 +1041,7 @@
0xa874, 0xa880,
0xa8c4, 0xa8ce,
0xa8da, 0xa8f2,
- 0xa8fc, 0xa900,
+ 0xa8fe, 0xa900,
0xa926, 0xa92e,
0xa947, 0xa952,
0xa954, 0xa95f,
@@ -1073,8 +1074,7 @@
0xab17, 0xab20,
0xab27, 0xab28,
0xab2f, 0xab30,
- 0xab60, 0xab64,
- 0xab66, 0xabc0,
+ 0xab66, 0xab70,
0xabe5, 0xabe6,
0xabe8, 0xabe9,
0xabed, 0xabf0,
@@ -1152,15 +1152,20 @@
0x11173, 0x11174,
0x11177, 0x11182,
0x111b6, 0x111bf,
- 0x111c9, 0x111cd,
+ 0x111ca, 0x111cd,
0x111ce, 0x111d0,
- 0x111db, 0x111e1,
+ 0x111e0, 0x111e1,
0x111f5, 0x11200,
0x11212, 0x11213,
0x1122f, 0x11232,
0x11234, 0x11235,
0x11236, 0x11238,
- 0x1123e, 0x112b0,
+ 0x1123e, 0x11280,
+ 0x11287, 0x11288,
+ 0x11289, 0x1128a,
+ 0x1128e, 0x1128f,
+ 0x1129e, 0x1129f,
+ 0x112aa, 0x112b0,
0x112df, 0x112e0,
0x112e3, 0x112f0,
0x112fa, 0x11302,
@@ -1174,7 +1179,8 @@
0x11340, 0x11341,
0x11345, 0x11347,
0x11349, 0x1134b,
- 0x1134e, 0x11357,
+ 0x1134e, 0x11350,
+ 0x11351, 0x11357,
0x11358, 0x1135d,
0x11364, 0x11480,
0x114b3, 0x114b9,
@@ -1186,7 +1192,7 @@
0x115b2, 0x115b8,
0x115bc, 0x115be,
0x115bf, 0x115c1,
- 0x115ca, 0x11600,
+ 0x115dc, 0x11600,
0x11633, 0x1163b,
0x1163d, 0x1163e,
0x1163f, 0x11641,
@@ -1196,14 +1202,20 @@
0x116ad, 0x116ae,
0x116b0, 0x116b6,
0x116b7, 0x116c0,
- 0x116ca, 0x118a0,
+ 0x116ca, 0x11700,
+ 0x1171a, 0x11720,
+ 0x11722, 0x11726,
+ 0x11727, 0x11730,
+ 0x11740, 0x118a0,
0x118f3, 0x118ff,
0x11900, 0x11ac0,
0x11af9, 0x12000,
- 0x12399, 0x12400,
+ 0x1239a, 0x12400,
0x1246f, 0x12470,
- 0x12475, 0x13000,
- 0x1342f, 0x16800,
+ 0x12475, 0x12480,
+ 0x12544, 0x13000,
+ 0x1342f, 0x14400,
+ 0x14647, 0x16800,
0x16a39, 0x16a40,
0x16a5f, 0x16a60,
0x16a6a, 0x16a6e,
@@ -1232,7 +1244,7 @@
0x1d173, 0x1d183,
0x1d185, 0x1d18c,
0x1d1aa, 0x1d1ae,
- 0x1d1de, 0x1d360,
+ 0x1d1e9, 0x1d360,
0x1d372, 0x1d400,
0x1d455, 0x1d456,
0x1d49d, 0x1d49e,
@@ -1258,7 +1270,12 @@
0x1d74f, 0x1d750,
0x1d789, 0x1d78a,
0x1d7c3, 0x1d7c4,
- 0x1d7cc, 0x1e800,
+ 0x1d7cc, 0x1d800,
+ 0x1da00, 0x1da37,
+ 0x1da3b, 0x1da6d,
+ 0x1da75, 0x1da76,
+ 0x1da84, 0x1da85,
+ 0x1da8c, 0x1e800,
0x1e8d0, 0x1e8d7,
0x1eef0, 0x1eef2,
0x1f000, 0x1f110,
@@ -1271,7 +1288,8 @@
0x1f252, 0x20000,
0x2a6d7, 0x2a700,
0x2b735, 0x2b740,
- 0x2b81e, 0x2f800,
+ 0x2b81e, 0x2b820,
+ 0x2cea2, 0x2f800,
0x2fa1e, 0xf0000,
0xffffe, 0x100000,
0x10fffe, 0x10ffff // sentinel
--- a/jdk/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.security.sasl/share/classes/javax/security/sasl/Sasl.java Tue Oct 20 08:24:37 2015 -0700
@@ -310,6 +310,13 @@
* for information about how to install and configure security service
* providers.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param mechanisms The non-null list of mechanism names to try. Each is the
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param authorizationId The possibly null protocol-dependent
@@ -452,6 +459,13 @@
* for information about how to install and configure security
* service providers.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param mechanism The non-null mechanism name. It must be an
* IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
* @param protocol The non-null string name of the protocol for which
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/TerminalFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -229,6 +229,13 @@
* specified parameters Object. The type of parameters
* needed may vary between different types of <code>TerminalFactory</code>s.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param type the type of the requested TerminalFactory
* @param params the parameters to pass to the TerminalFactorySpi
* implementation, or null if no parameters are needed
--- a/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/TransformService.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/TransformService.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -136,6 +136,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param algorithm the URI of the algorithm
* @param mechanismType the type of the XML processing mechanism and
* representation
--- a/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLSignatureFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/XMLSignatureFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -173,6 +173,13 @@
* <p>Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param mechanismType the type of the XML processing mechanism and
* representation. See the <a
* href="../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider">
--- a/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyInfoFactory.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/keyinfo/KeyInfoFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -129,6 +129,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @param mechanismType the type of the XML processing mechanism and
* representation. See the <a
* href="../../../../../../technotes/guides/security/xmldsig/overview.html#Service%20Provider">
@@ -263,6 +270,13 @@
* <p> Note that the list of registered providers may be retrieved via
* the {@link Security#getProviders() Security.getProviders()} method.
*
+ * @implNote
+ * The JDK Reference Implementation additionally uses the
+ * {@code jdk.security.provider.preferred} property to determine
+ * the preferred provider order for the specified algorithm. This
+ * may be different than the order of providers returned by
+ * {@link Security#getProviders() Security.getProviders()}.
+ *
* @return a new <code>KeyInfoFactory</code>
* @throws NoSuchMechanismException if no <code>Provider</code> supports a
* <code>KeyInfoFactory</code> implementation for the DOM mechanism
--- a/jdk/test/ProblemList.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/ProblemList.txt Tue Oct 20 08:24:37 2015 -0700
@@ -133,6 +133,9 @@
# 8029891
java/lang/ClassLoader/deadlock/GetResource.java generic-all
+# 8131129
+java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java windows-all
+
############################################################################
# jdk_instrument
@@ -297,6 +300,9 @@
# 8074580
sun/security/pkcs11/rsa/TestKeyPairGenerator.java generic-all
+# 8139860
+com/oracle/security/ucrypto/TestRSA.java solaris-all
+
############################################################################
# jdk_sound
--- a/jdk/test/java/lang/Character/CheckProp.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Character/CheckProp.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,7 @@
/**
* @test
- * @bug 7037261 7070436 7198195 8032446
+ * @bug 7037261 7070436 7198195 8032446 8072600
* @summary Check j.l.Character.isLowerCase/isUppercase/isAlphabetic/isIdeographic
*/
--- a/jdk/test/java/lang/Character/CheckScript.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Character/CheckScript.java Tue Oct 20 08:24:37 2015 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6945564 6959267 7033561 7070436 7198195 8032446
+ * @bug 6945564 6959267 7033561 7070436 7198195 8032446 8072600
* @summary Check that the j.l.Character.UnicodeScript
*/
--- a/jdk/test/java/lang/Character/PropList.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Character/PropList.txt Tue Oct 20 08:24:37 2015 -0700
@@ -1,8 +1,8 @@
-# PropList-7.0.0.txt
-# Date: 2014-02-19, 15:51:26 GMT [MD]
+# PropList-8.0.0.txt
+# Date: 2015-05-16, 17:50:38 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2014 Unicode, Inc.
+# Copyright (c) 1991-2015 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
@@ -189,18 +189,22 @@
11141..11143 ; Terminal_Punctuation # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK
111C5..111C6 ; Terminal_Punctuation # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA
111CD ; Terminal_Punctuation # Po SHARADA SUTRA MARK
+111DE..111DF ; Terminal_Punctuation # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2
11238..1123C ; Terminal_Punctuation # Po [5] KHOJKI DANDA..KHOJKI DOUBLE SECTION MARK
+112A9 ; Terminal_Punctuation # Po MULTANI SECTION MARK
115C2..115C5 ; Terminal_Punctuation # Po [4] SIDDHAM DANDA..SIDDHAM SEPARATOR BAR
-115C9 ; Terminal_Punctuation # Po SIDDHAM END OF TEXT MARK
+115C9..115D7 ; Terminal_Punctuation # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; Terminal_Punctuation # Po [2] MODI DANDA..MODI DOUBLE DANDA
+1173C..1173E ; Terminal_Punctuation # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
12470..12474 ; Terminal_Punctuation # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
16A6E..16A6F ; Terminal_Punctuation # Po [2] MRO DANDA..MRO DOUBLE DANDA
16AF5 ; Terminal_Punctuation # Po BASSA VAH FULL STOP
16B37..16B39 ; Terminal_Punctuation # Po [3] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN CIM CHEEM
16B44 ; Terminal_Punctuation # Po PAHAWH HMONG SIGN XAUS
1BC9F ; Terminal_Punctuation # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+1DA87..1DA8A ; Terminal_Punctuation # Po [4] SIGNWRITING COMMA..SIGNWRITING COLON
-# Total code points: 214
+# Total code points: 238
# ================================================
@@ -425,7 +429,7 @@
081B..0823 ; Other_Alphabetic # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
0825..0827 ; Other_Alphabetic # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
0829..082C ; Other_Alphabetic # Mn [4] SAMARITAN VOWEL SIGN LONG I..SAMARITAN VOWEL SIGN SUKUN
-08E4..08E9 ; Other_Alphabetic # Mn [6] ARABIC CURLY FATHA..ARABIC CURLY KASRATAN
+08E3..08E9 ; Other_Alphabetic # Mn [7] ARABIC TURNED DAMMA BELOW..ARABIC CURLY KASRATAN
08F0..0902 ; Other_Alphabetic # Mn [19] ARABIC OPEN FATHATAN..DEVANAGARI SIGN ANUSVARA
0903 ; Other_Alphabetic # Mc DEVANAGARI SIGN VISARGA
093A ; Other_Alphabetic # Mn DEVANAGARI VOWEL SIGN OE
@@ -560,8 +564,6 @@
1930..1931 ; Other_Alphabetic # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
1932 ; Other_Alphabetic # Mn LIMBU SMALL LETTER ANUSVARA
1933..1938 ; Other_Alphabetic # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
-19B0..19C0 ; Other_Alphabetic # Mc [17] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE VOWEL SIGN IY
-19C8..19C9 ; Other_Alphabetic # Mc [2] NEW TAI LUE TONE MARK-1..NEW TAI LUE TONE MARK-2
1A17..1A18 ; Other_Alphabetic # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
1A19..1A1A ; Other_Alphabetic # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
1A1B ; Other_Alphabetic # Mn BUGINESE VOWEL SIGN AE
@@ -605,7 +607,7 @@
24B6..24E9 ; Other_Alphabetic # So [52] CIRCLED LATIN CAPITAL LETTER A..CIRCLED LATIN SMALL LETTER Z
2DE0..2DFF ; Other_Alphabetic # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
A674..A67B ; Other_Alphabetic # Mn [8] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC LETTER OMEGA
-A69F ; Other_Alphabetic # Mn COMBINING CYRILLIC LETTER IOTIFIED E
+A69E..A69F ; Other_Alphabetic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
A823..A824 ; Other_Alphabetic # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
A825..A826 ; Other_Alphabetic # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
A827 ; Other_Alphabetic # Mc SYLOTI NAGRI VOWEL SIGN OO
@@ -672,7 +674,7 @@
112DF ; Other_Alphabetic # Mn KHUDAWADI SIGN ANUSVARA
112E0..112E2 ; Other_Alphabetic # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
112E3..112E8 ; Other_Alphabetic # Mn [6] KHUDAWADI VOWEL SIGN U..KHUDAWADI VOWEL SIGN AU
-11301 ; Other_Alphabetic # Mn GRANTHA SIGN CANDRABINDU
+11300..11301 ; Other_Alphabetic # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
11302..11303 ; Other_Alphabetic # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
1133E..1133F ; Other_Alphabetic # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I
11340 ; Other_Alphabetic # Mn GRANTHA VOWEL SIGN II
@@ -693,6 +695,7 @@
115B8..115BB ; Other_Alphabetic # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
115BC..115BD ; Other_Alphabetic # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
115BE ; Other_Alphabetic # Mc SIDDHAM SIGN VISARGA
+115DC..115DD ; Other_Alphabetic # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
11630..11632 ; Other_Alphabetic # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
11633..1163A ; Other_Alphabetic # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
1163B..1163C ; Other_Alphabetic # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
@@ -704,6 +707,11 @@
116AD ; Other_Alphabetic # Mn TAKRI VOWEL SIGN AA
116AE..116AF ; Other_Alphabetic # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
116B0..116B5 ; Other_Alphabetic # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
+1171D..1171F ; Other_Alphabetic # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11720..11721 ; Other_Alphabetic # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
+11722..11725 ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11726 ; Other_Alphabetic # Mc AHOM VOWEL SIGN E
+11727..1172A ; Other_Alphabetic # Mn [4] AHOM VOWEL SIGN AW..AHOM VOWEL SIGN AM
16B30..16B36 ; Other_Alphabetic # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
16F51..16F7E ; Other_Alphabetic # Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG
1BC9E ; Other_Alphabetic # Mn DUPLOYAN DOUBLE MARK
@@ -720,15 +728,16 @@
3021..3029 ; Ideographic # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
3038..303A ; Ideographic # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
3400..4DB5 ; Ideographic # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FCC ; Ideographic # Lo [20941] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FCC
+4E00..9FD5 ; Ideographic # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
F900..FA6D ; Ideographic # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
20000..2A6D6 ; Ideographic # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Ideographic # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-# Total code points: 75633
+# Total code points: 81404
# ================================================
@@ -773,7 +782,7 @@
07EB..07F3 ; Diacritic # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
07F4..07F5 ; Diacritic # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
0818..0819 ; Diacritic # Mn [2] SAMARITAN MARK OCCLUSION..SAMARITAN MARK DAGESH
-08E4..08FE ; Diacritic # Mn [27] ARABIC CURLY FATHA..ARABIC DAMMA WITH DOT
+08E3..08FE ; Diacritic # Mn [28] ARABIC TURNED DAMMA BELOW..ARABIC DAMMA WITH DOT
093C ; Diacritic # Mn DEVANAGARI SIGN NUKTA
094D ; Diacritic # Mn DEVANAGARI SIGN VIRAMA
0951..0954 ; Diacritic # Mn [4] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI ACUTE ACCENT
@@ -877,7 +886,7 @@
ABEC ; Diacritic # Mc MEETEI MAYEK LUM IYEK
ABED ; Diacritic # Mn MEETEI MAYEK APUN IYEK
FB1E ; Diacritic # Mn HEBREW POINT JUDEO-SPANISH VARIKA
-FE20..FE2D ; Diacritic # Mn [14] COMBINING LIGATURE LEFT HALF..COMBINING CONJOINING MACRON BELOW
+FE20..FE2F ; Diacritic # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
FF3E ; Diacritic # Sk FULLWIDTH CIRCUMFLEX ACCENT
FF40 ; Diacritic # Sk FULLWIDTH GRAVE ACCENT
FF70 ; Diacritic # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
@@ -889,6 +898,7 @@
11133..11134 ; Diacritic # Mn [2] CHAKMA VIRAMA..CHAKMA MAAYYAA
11173 ; Diacritic # Mn MAHAJANI SIGN NUKTA
111C0 ; Diacritic # Mc SHARADA SIGN VIRAMA
+111CA..111CC ; Diacritic # Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK
11235 ; Diacritic # Mc KHOJKI SIGN VIRAMA
11236 ; Diacritic # Mn KHOJKI SIGN NUKTA
112E9..112EA ; Diacritic # Mn [2] KHUDAWADI SIGN NUKTA..KHUDAWADI SIGN VIRAMA
@@ -901,6 +911,7 @@
1163F ; Diacritic # Mn MODI SIGN VIRAMA
116B6 ; Diacritic # Mc TAKRI SIGN VIRAMA
116B7 ; Diacritic # Mn TAKRI SIGN NUKTA
+1172B ; Diacritic # Mn AHOM SIGN KILLER
16AF0..16AF4 ; Diacritic # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
16F8F..16F92 ; Diacritic # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
16F93..16F9F ; Diacritic # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
@@ -911,7 +922,7 @@
1D1AA..1D1AD ; Diacritic # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
1E8D0..1E8D6 ; Diacritic # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
-# Total code points: 766
+# Total code points: 773
# ================================================
@@ -1053,7 +1064,7 @@
# ================================================
3400..4DB5 ; Unified_Ideograph # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FCC ; Unified_Ideograph # Lo [20941] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FCC
+4E00..9FD5 ; Unified_Ideograph # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
FA0E..FA0F ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA0E..CJK COMPATIBILITY IDEOGRAPH-FA0F
FA11 ; Unified_Ideograph # Lo CJK COMPATIBILITY IDEOGRAPH-FA11
FA13..FA14 ; Unified_Ideograph # Lo [2] CJK COMPATIBILITY IDEOGRAPH-FA13..CJK COMPATIBILITY IDEOGRAPH-FA14
@@ -1064,8 +1075,9 @@
20000..2A6D6 ; Unified_Ideograph # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Unified_Ideograph # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Unified_Ideograph # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Unified_Ideograph # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
-# Total code points: 74617
+# Total code points: 80388
# ================================================
@@ -1094,9 +1106,9 @@
2329 ; Deprecated # Ps LEFT-POINTING ANGLE BRACKET
232A ; Deprecated # Pe RIGHT-POINTING ANGLE BRACKET
E0001 ; Deprecated # Cf LANGUAGE TAG
-E0020..E007F ; Deprecated # Cf [96] TAG SPACE..CANCEL TAG
+E007F ; Deprecated # Cf CANCEL TAG
-# Total code points: 111
+# Total code points: 16
# ================================================
@@ -1138,11 +1150,13 @@
0E40..0E44 ; Logical_Order_Exception # Lo [5] THAI CHARACTER SARA E..THAI CHARACTER SARA AI MAIMALAI
0EC0..0EC4 ; Logical_Order_Exception # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI
+19B5..19B7 ; Logical_Order_Exception # Lo [3] NEW TAI LUE VOWEL SIGN E..NEW TAI LUE VOWEL SIGN O
+19BA ; Logical_Order_Exception # Lo NEW TAI LUE VOWEL SIGN AY
AAB5..AAB6 ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O
AAB9 ; Logical_Order_Exception # Lo TAI VIET VOWEL UEA
AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET VOWEL AY
-# Total code points: 15
+# Total code points: 19
# ================================================
@@ -1213,18 +1227,22 @@
11141..11143 ; STerm # Po [3] CHAKMA DANDA..CHAKMA QUESTION MARK
111C5..111C6 ; STerm # Po [2] SHARADA DANDA..SHARADA DOUBLE DANDA
111CD ; STerm # Po SHARADA SUTRA MARK
+111DE..111DF ; STerm # Po [2] SHARADA SECTION MARK-1..SHARADA SECTION MARK-2
11238..11239 ; STerm # Po [2] KHOJKI DANDA..KHOJKI DOUBLE DANDA
1123B..1123C ; STerm # Po [2] KHOJKI SECTION MARK..KHOJKI DOUBLE SECTION MARK
+112A9 ; STerm # Po MULTANI SECTION MARK
115C2..115C3 ; STerm # Po [2] SIDDHAM DANDA..SIDDHAM DOUBLE DANDA
-115C9 ; STerm # Po SIDDHAM END OF TEXT MARK
+115C9..115D7 ; STerm # Po [15] SIDDHAM END OF TEXT MARK..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
11641..11642 ; STerm # Po [2] MODI DANDA..MODI DOUBLE DANDA
+1173C..1173E ; STerm # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
16A6E..16A6F ; STerm # Po [2] MRO DANDA..MRO DOUBLE DANDA
16AF5 ; STerm # Po BASSA VAH FULL STOP
16B37..16B38 ; STerm # Po [2] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS TSHAB CEEB
16B44 ; STerm # Po PAHAWH HMONG SIGN XAUS
1BC9F ; STerm # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+1DA88 ; STerm # Po SIGNWRITING FULL STOP
-# Total code points: 99
+# Total code points: 120
# ================================================
@@ -1432,7 +1450,9 @@
2BBD..2BC8 ; Pattern_Syntax # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
2BC9 ; Pattern_Syntax # Cn <reserved-2BC9>
2BCA..2BD1 ; Pattern_Syntax # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN
-2BD2..2BFF ; Pattern_Syntax # Cn [46] <reserved-2BD2>..<reserved-2BFF>
+2BD2..2BEB ; Pattern_Syntax # Cn [26] <reserved-2BD2>..<reserved-2BEB>
+2BEC..2BEF ; Pattern_Syntax # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS
+2BF0..2BFF ; Pattern_Syntax # Cn [16] <reserved-2BF0>..<reserved-2BFF>
2E00..2E01 ; Pattern_Syntax # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
2E02 ; Pattern_Syntax # Pi LEFT SUBSTITUTION BRACKET
2E03 ; Pattern_Syntax # Pf RIGHT SUBSTITUTION BRACKET
--- a/jdk/test/java/lang/Character/PropertyValueAliases.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Character/PropertyValueAliases.txt Tue Oct 20 08:24:37 2015 -0700
@@ -1,8 +1,8 @@
-# PropertyValueAliases-7.0.0.txt
-# Date: 2014-05-14, 23:55:16 GMT [MD]
+# PropertyValueAliases-8.0.0.txt
+# Date: 2015-03-11, 22:29:33 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2014 Unicode, Inc.
+# Copyright (c) 1991-2015 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
#
@@ -77,6 +77,7 @@
age; 6.2 ; V6_2
age; 6.3 ; V6_3
age; 7.0 ; V7_0
+age; 8.0 ; V8_0
age; NA ; Unassigned
# Alphabetic (Alpha)
@@ -138,8 +139,10 @@
# Block (blk)
blk; Aegean_Numbers ; Aegean_Numbers
+blk; Ahom ; Ahom
blk; Alchemical ; Alchemical_Symbols
blk; Alphabetic_PF ; Alphabetic_Presentation_Forms
+blk; Anatolian_Hieroglyphs ; Anatolian_Hieroglyphs
blk; Ancient_Greek_Music ; Ancient_Greek_Musical_Notation
blk; Ancient_Greek_Numbers ; Ancient_Greek_Numbers
blk; Ancient_Symbols ; Ancient_Symbols
@@ -173,6 +176,7 @@
blk; Chakma ; Chakma
blk; Cham ; Cham
blk; Cherokee ; Cherokee
+blk; Cherokee_Sup ; Cherokee_Supplement
blk; CJK ; CJK_Unified_Ideographs
blk; CJK_Compat ; CJK_Compatibility
blk; CJK_Compat_Forms ; CJK_Compatibility_Forms
@@ -182,6 +186,7 @@
blk; CJK_Ext_B ; CJK_Unified_Ideographs_Extension_B
blk; CJK_Ext_C ; CJK_Unified_Ideographs_Extension_C
blk; CJK_Ext_D ; CJK_Unified_Ideographs_Extension_D
+blk; CJK_Ext_E ; CJK_Unified_Ideographs_Extension_E
blk; CJK_Radicals_Sup ; CJK_Radicals_Supplement
blk; CJK_Strokes ; CJK_Strokes
blk; CJK_Symbols ; CJK_Symbols_And_Punctuation
@@ -208,6 +213,7 @@
blk; Dingbats ; Dingbats
blk; Domino ; Domino_Tiles
blk; Duployan ; Duployan
+blk; Early_Dynastic_Cuneiform ; Early_Dynastic_Cuneiform
blk; Egyptian_Hieroglyphs ; Egyptian_Hieroglyphs
blk; Elbasan ; Elbasan
blk; Emoticons ; Emoticons
@@ -234,6 +240,7 @@
blk; Half_Marks ; Combining_Half_Marks
blk; Hangul ; Hangul_Syllables
blk; Hanunoo ; Hanunoo
+blk; Hatran ; Hatran
blk; Hebrew ; Hebrew
blk; High_PU_Surrogates ; High_Private_Use_Surrogates
blk; High_Surrogates ; High_Surrogates
@@ -303,6 +310,7 @@
blk; Modifier_Tone_Letters ; Modifier_Tone_Letters
blk; Mongolian ; Mongolian
blk; Mro ; Mro
+blk; Multani ; Multani
blk; Music ; Musical_Symbols
blk; Myanmar ; Myanmar
blk; Myanmar_Ext_A ; Myanmar_Extended_A
@@ -315,6 +323,7 @@
blk; OCR ; Optical_Character_Recognition
blk; Ogham ; Ogham
blk; Ol_Chiki ; Ol_Chiki
+blk; Old_Hungarian ; Old_Hungarian
blk; Old_Italic ; Old_Italic
blk; Old_North_Arabian ; Old_North_Arabian
blk; Old_Permic ; Old_Permic
@@ -359,7 +368,9 @@
blk; Sup_PUA_A ; Supplementary_Private_Use_Area_A
blk; Sup_PUA_B ; Supplementary_Private_Use_Area_B
blk; Sup_Punctuation ; Supplemental_Punctuation
+blk; Sup_Symbols_And_Pictographs ; Supplemental_Symbols_And_Pictographs
blk; Super_And_Sub ; Superscripts_And_Subscripts
+blk; Sutton_SignWriting ; Sutton_SignWriting
blk; Syloti_Nagri ; Syloti_Nagri
blk; Syriac ; Syriac
blk; Tagalog ; Tagalog
@@ -709,22 +720,22 @@
Ideo; N ; No ; F ; False
Ideo; Y ; Yes ; T ; True
-# Indic_Matra_Category (InMC)
+# Indic_Positional_Category (InPC)
-InMC; Bottom ; Bottom
-InMC; Bottom_And_Right ; Bottom_And_Right
-InMC; Left ; Left
-InMC; Left_And_Right ; Left_And_Right
-InMC; NA ; NA
-InMC; Overstruck ; Overstruck
-InMC; Right ; Right
-InMC; Top ; Top
-InMC; Top_And_Bottom ; Top_And_Bottom
-InMC; Top_And_Bottom_And_Right ; Top_And_Bottom_And_Right
-InMC; Top_And_Left ; Top_And_Left
-InMC; Top_And_Left_And_Right ; Top_And_Left_And_Right
-InMC; Top_And_Right ; Top_And_Right
-InMC; Visual_Order_Left ; Visual_Order_Left
+InPC; Bottom ; Bottom
+InPC; Bottom_And_Right ; Bottom_And_Right
+InPC; Left ; Left
+InPC; Left_And_Right ; Left_And_Right
+InPC; NA ; NA
+InPC; Overstruck ; Overstruck
+InPC; Right ; Right
+InPC; Top ; Top
+InPC; Top_And_Bottom ; Top_And_Bottom
+InPC; Top_And_Bottom_And_Right ; Top_And_Bottom_And_Right
+InPC; Top_And_Left ; Top_And_Left
+InPC; Top_And_Left_And_Right ; Top_And_Left_And_Right
+InPC; Top_And_Right ; Top_And_Right
+InPC; Visual_Order_Left ; Visual_Order_Left
# Indic_Syllabic_Category (InSC)
@@ -736,11 +747,14 @@
InSC; Consonant_Dead ; Consonant_Dead
InSC; Consonant_Final ; Consonant_Final
InSC; Consonant_Head_Letter ; Consonant_Head_Letter
+InSC; Consonant_Killer ; Consonant_Killer
InSC; Consonant_Medial ; Consonant_Medial
InSC; Consonant_Placeholder ; Consonant_Placeholder
InSC; Consonant_Preceding_Repha ; Consonant_Preceding_Repha
+InSC; Consonant_Prefixed ; Consonant_Prefixed
InSC; Consonant_Subjoined ; Consonant_Subjoined
InSC; Consonant_Succeeding_Repha ; Consonant_Succeeding_Repha
+InSC; Consonant_With_Stacker ; Consonant_With_Stacker
InSC; Gemination_Mark ; Gemination_Mark
InSC; Invisible_Stacker ; Invisible_Stacker
InSC; Joiner ; Joiner
@@ -752,6 +766,7 @@
InSC; Other ; Other
InSC; Pure_Killer ; Pure_Killer
InSC; Register_Shifter ; Register_Shifter
+InSC; Syllable_Modifier ; Syllable_Modifier
InSC; Tone_Letter ; Tone_Letter
InSC; Tone_Mark ; Tone_Mark
InSC; Virama ; Virama
@@ -1099,6 +1114,7 @@
# Script (sc)
sc ; Aghb ; Caucasian_Albanian
+sc ; Ahom ; Ahom
sc ; Arab ; Arabic
sc ; Armi ; Imperial_Aramaic
sc ; Armn ; Armenian
@@ -1137,10 +1153,13 @@
sc ; Hang ; Hangul
sc ; Hani ; Han
sc ; Hano ; Hanunoo
+sc ; Hatr ; Hatran
sc ; Hebr ; Hebrew
sc ; Hira ; Hiragana
+sc ; Hluw ; Anatolian_Hieroglyphs
sc ; Hmng ; Pahawh_Hmong
sc ; Hrkt ; Katakana_Or_Hiragana
+sc ; Hung ; Old_Hungarian
sc ; Ital ; Old_Italic
sc ; Java ; Javanese
sc ; Kali ; Kayah_Li
@@ -1171,6 +1190,7 @@
sc ; Mong ; Mongolian
sc ; Mroo ; Mro
sc ; Mtei ; Meetei_Mayek
+sc ; Mult ; Multani
sc ; Mymr ; Myanmar
sc ; Narb ; Old_North_Arabian
sc ; Nbat ; Nabataean
@@ -1194,6 +1214,7 @@
sc ; Samr ; Samaritan
sc ; Sarb ; Old_South_Arabian
sc ; Saur ; Saurashtra
+sc ; Sgnw ; SignWriting
sc ; Shaw ; Shavian
sc ; Shrd ; Sharada
sc ; Sidd ; Siddham
--- a/jdk/test/java/lang/Character/Scripts.txt Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Character/Scripts.txt Tue Oct 20 08:24:37 2015 -0700
@@ -1,10 +1,16 @@
-# Scripts-7.0.0.txt
-# Date: 2014-05-15, 00:11:35 GMT [MD]
+# Scripts-8.0.0.txt
+# Date: 2015-03-11, 22:29:42 GMT [MD]
#
# Unicode Character Database
-# Copyright (c) 1991-2014 Unicode, Inc.
+# Copyright (c) 1991-2015 Unicode, Inc.
# For terms of use, see http://www.unicode.org/terms_of_use.html
# For documentation, see http://www.unicode.org/reports/tr44/
+# For more information, see:
+# UAX #24, Unicode Script Property: http://www.unicode.org/reports/tr24/
+# Especially the sections:
+# http://www.unicode.org/reports/tr24/#Assignment_Script_Values
+# http://www.unicode.org/reports/tr24/#Assignment_ScriptX_Values
+#
# ================================================
@@ -89,7 +95,6 @@
061C ; Common # Cf ARABIC LETTER MARK
061F ; Common # Po ARABIC QUESTION MARK
0640 ; Common # Lm ARABIC TATWEEL
-0660..0669 ; Common # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
06DD ; Common # Cf ARABIC END OF AYAH
0964..0965 ; Common # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
0E3F ; Common # Sc THAI CURRENCY SYMBOL BAHT
@@ -148,7 +153,7 @@
208A..208C ; Common # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
208D ; Common # Ps SUBSCRIPT LEFT PARENTHESIS
208E ; Common # Pe SUBSCRIPT RIGHT PARENTHESIS
-20A0..20BD ; Common # Sc [30] EURO-CURRENCY SIGN..RUBLE SIGN
+20A0..20BE ; Common # Sc [31] EURO-CURRENCY SIGN..LARI SIGN
2100..2101 ; Common # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
2102 ; Common # L& DOUBLE-STRUCK CAPITAL C
2103..2106 ; Common # So [4] DEGREE CELSIUS..CADA UNA
@@ -182,6 +187,7 @@
214F ; Common # So SYMBOL FOR SAMARITAN SOURCE
2150..215F ; Common # No [16] VULGAR FRACTION ONE SEVENTH..FRACTION NUMERATOR ONE
2189 ; Common # No VULGAR FRACTION ZERO THIRDS
+218A..218B ; Common # So [2] TURNED DIGIT TWO..TURNED DIGIT THREE
2190..2194 ; Common # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW
2195..2199 ; Common # So [5] UP DOWN ARROW..SOUTH WEST ARROW
219A..219B ; Common # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE
@@ -304,6 +310,7 @@
2B98..2BB9 ; Common # So [34] THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD..UP ARROWHEAD IN A RECTANGLE BOX
2BBD..2BC8 ; Common # So [12] BALLOT BOX WITH LIGHT X..BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED
2BCA..2BD1 ; Common # So [8] TOP HALF BLACK CIRCLE..UNCERTAINTY SIGN
+2BEC..2BEF ; Common # So [4] LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS..DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS
2E00..2E01 ; Common # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
2E02 ; Common # Pi LEFT SUBSTITUTION BRACKET
2E03 ; Common # Pf RIGHT SUBSTITUTION BRACKET
@@ -512,7 +519,7 @@
1D173..1D17A ; Common # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
1D183..1D184 ; Common # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN
1D18C..1D1A9 ; Common # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH
-1D1AE..1D1DD ; Common # So [48] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL PES SUBPUNCTIS
+1D1AE..1D1E8 ; Common # So [59] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KIEVAN FLAT SIGN
1D300..1D356 ; Common # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
1D360..1D371 ; Common # No [18] COUNTING ROD UNIT DIGIT ONE..COUNTING ROD TENS DIGIT NINE
1D400..1D454 ; Common # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
@@ -571,16 +578,11 @@
1F210..1F23A ; Common # So [43] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-55B6
1F240..1F248 ; Common # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
1F250..1F251 ; Common # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
-1F300..1F32C ; Common # So [45] CYCLONE..WIND BLOWING FACE
-1F330..1F37D ; Common # So [78] CHESTNUT..FORK AND KNIFE WITH PLATE
-1F380..1F3CE ; Common # So [79] RIBBON..RACING CAR
-1F3D4..1F3F7 ; Common # So [36] SNOW CAPPED MOUNTAIN..LABEL
-1F400..1F4FE ; Common # So [255] RAT..PORTABLE STEREO
-1F500..1F54A ; Common # So [75] TWISTED RIGHTWARDS ARROWS..DOVE OF PEACE
-1F550..1F579 ; Common # So [42] CLOCK FACE ONE OCLOCK..JOYSTICK
+1F300..1F3FA ; Common # So [251] CYCLONE..AMPHORA
+1F3FB..1F3FF ; Common # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
+1F400..1F579 ; Common # So [378] RAT..JOYSTICK
1F57B..1F5A3 ; Common # So [41] LEFT HAND TELEPHONE RECEIVER..BLACK DOWN POINTING BACKHAND INDEX
-1F5A5..1F642 ; Common # So [158] DESKTOP COMPUTER..SLIGHTLY SMILING FACE
-1F645..1F6CF ; Common # So [139] FACE WITH NO GOOD GESTURE..BED
+1F5A5..1F6D0 ; Common # So [300] DESKTOP COMPUTER..PLACE OF WORSHIP
1F6E0..1F6EC ; Common # So [13] HAMMER AND WRENCH..AIRPLANE ARRIVING
1F6F0..1F6F3 ; Common # So [4] SATELLITE..PASSENGER SHIP
1F700..1F773 ; Common # So [116] ALCHEMICAL SYMBOL FOR QUINTESSENCE..ALCHEMICAL SYMBOL FOR HALF OUNCE
@@ -590,10 +592,13 @@
1F850..1F859 ; Common # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
1F860..1F887 ; Common # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
1F890..1F8AD ; Common # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
+1F910..1F918 ; Common # So [9] ZIPPER-MOUTH FACE..SIGN OF THE HORNS
+1F980..1F984 ; Common # So [5] CRAB..UNICORN FACE
+1F9C0 ; Common # So CHEESE WEDGE
E0001 ; Common # Cf LANGUAGE TAG
E0020..E007F ; Common # Cf [96] TAG SPACE..CANCEL TAG
-# Total code points: 7129
+# Total code points: 7179
# ================================================
@@ -635,20 +640,21 @@
A770 ; Latin # Lm MODIFIER LETTER US
A771..A787 ; Latin # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T
A78B..A78E ; Latin # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
+A78F ; Latin # Lo LATIN LETTER SINOLOGICAL DOT
A790..A7AD ; Latin # L& [30] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN CAPITAL LETTER L WITH BELT
-A7B0..A7B1 ; Latin # L& [2] LATIN CAPITAL LETTER TURNED K..LATIN CAPITAL LETTER TURNED T
+A7B0..A7B7 ; Latin # L& [8] LATIN CAPITAL LETTER TURNED K..LATIN SMALL LETTER OMEGA
A7F7 ; Latin # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I
A7F8..A7F9 ; Latin # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
A7FA ; Latin # L& LATIN LETTER SMALL CAPITAL TURNED M
A7FB..A7FF ; Latin # Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
AB30..AB5A ; Latin # L& [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
AB5C..AB5F ; Latin # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
-AB64 ; Latin # L& LATIN SMALL LETTER INVERTED ALPHA
+AB60..AB64 ; Latin # L& [5] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER INVERTED ALPHA
FB00..FB06 ; Latin # L& [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
FF21..FF3A ; Latin # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
FF41..FF5A ; Latin # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
-# Total code points: 1338
+# Total code points: 1349
# ================================================
@@ -731,9 +737,10 @@
A67F ; Cyrillic # Lm CYRILLIC PAYEROK
A680..A69B ; Cyrillic # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O
A69C..A69D ; Cyrillic # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
-A69F ; Cyrillic # Mn COMBINING CYRILLIC LETTER IOTIFIED E
-
-# Total code points: 431
+A69E..A69F ; Cyrillic # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
+FE2E..FE2F ; Cyrillic # Mn [2] COMBINING CYRILLIC TITLO LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
+
+# Total code points: 434
# ================================================
@@ -788,6 +795,7 @@
0620..063F ; Arabic # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
0641..064A ; Arabic # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
0656..065F ; Arabic # Mn [10] ARABIC SUBSCRIPT ALEF..ARABIC WAVY HAMZA BELOW
+0660..0669 ; Arabic # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
066A..066D ; Arabic # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
066E..066F ; Arabic # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
0671..06D3 ; Arabic # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
@@ -806,8 +814,8 @@
06FD..06FE ; Arabic # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN
06FF ; Arabic # Lo ARABIC LETTER HEH WITH INVERTED V
0750..077F ; Arabic # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
-08A0..08B2 ; Arabic # Lo [19] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER ZAIN WITH INVERTED V ABOVE
-08E4..08FF ; Arabic # Mn [28] ARABIC CURLY FATHA..ARABIC MARK SIDEWAYS NOON GHUNNA
+08A0..08B4 ; Arabic # Lo [21] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER KAF WITH DOT BELOW
+08E3..08FF ; Arabic # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
FB50..FBB1 ; Arabic # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
FBB2..FBC1 ; Arabic # Sk [16] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL SMALL TAH BELOW
FBD3..FD3D ; Arabic # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
@@ -854,7 +862,7 @@
1EEAB..1EEBB ; Arabic # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
1EEF0..1EEF1 ; Arabic # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
-# Total code points: 1244
+# Total code points: 1257
# ================================================
@@ -902,8 +910,10 @@
A8F2..A8F7 ; Devanagari # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
A8F8..A8FA ; Devanagari # Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
A8FB ; Devanagari # Lo DEVANAGARI HEADSTROKE
-
-# Total code points: 152
+A8FC ; Devanagari # Po DEVANAGARI SIGN SIDDHAM
+A8FD ; Devanagari # Lo DEVANAGARI JAIN OM
+
+# Total code points: 154
# ================================================
@@ -987,8 +997,9 @@
0AE6..0AEF ; Gujarati # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
0AF0 ; Gujarati # Po GUJARATI ABBREVIATION SIGN
0AF1 ; Gujarati # Sc GUJARATI RUPEE SIGN
-
-# Total code points: 84
+0AF9 ; Gujarati # Lo GUJARATI LETTER ZHA
+
+# Total code points: 85
# ================================================
@@ -1064,14 +1075,14 @@
0C46..0C48 ; Telugu # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
0C4A..0C4D ; Telugu # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
0C55..0C56 ; Telugu # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
-0C58..0C59 ; Telugu # Lo [2] TELUGU LETTER TSA..TELUGU LETTER DZA
+0C58..0C5A ; Telugu # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
0C60..0C61 ; Telugu # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
0C62..0C63 ; Telugu # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
0C66..0C6F ; Telugu # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
0C78..0C7E ; Telugu # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR
0C7F ; Telugu # So TELUGU SIGN TUUMU
-# Total code points: 95
+# Total code points: 96
# ================================================
@@ -1115,14 +1126,14 @@
0D4D ; Malayalam # Mn MALAYALAM SIGN VIRAMA
0D4E ; Malayalam # Lo MALAYALAM LETTER DOT REPH
0D57 ; Malayalam # Mc MALAYALAM AU LENGTH MARK
-0D60..0D61 ; Malayalam # Lo [2] MALAYALAM LETTER VOCALIC RR..MALAYALAM LETTER VOCALIC LL
+0D5F..0D61 ; Malayalam # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL
0D62..0D63 ; Malayalam # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
0D66..0D6F ; Malayalam # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
0D70..0D75 ; Malayalam # No [6] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE QUARTERS
0D79 ; Malayalam # So MALAYALAM DATE MARK
0D7A..0D7F ; Malayalam # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
-# Total code points: 99
+# Total code points: 100
# ================================================
@@ -1358,9 +1369,11 @@
# ================================================
-13A0..13F4 ; Cherokee # Lo [85] CHEROKEE LETTER A..CHEROKEE LETTER YV
-
-# Total code points: 85
+13A0..13F5 ; Cherokee # L& [86] CHEROKEE LETTER A..CHEROKEE LETTER MV
+13F8..13FD ; Cherokee # L& [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
+AB70..ABBF ; Cherokee # L& [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
+
+# Total code points: 172
# ================================================
@@ -1472,15 +1485,16 @@
3038..303A ; Han # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
303B ; Han # Lm VERTICAL IDEOGRAPHIC ITERATION MARK
3400..4DB5 ; Han # Lo [6582] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DB5
-4E00..9FCC ; Han # Lo [20941] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FCC
+4E00..9FD5 ; Han # Lo [20950] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FD5
F900..FA6D ; Han # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
FA70..FAD9 ; Han # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
20000..2A6D6 ; Han # Lo [42711] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6D6
2A700..2B734 ; Han # Lo [4149] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B734
2B740..2B81D ; Han # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B820..2CEA1 ; Han # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
2F800..2FA1D ; Han # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-# Total code points: 75963
+# Total code points: 81734
# ================================================
@@ -1680,9 +1694,7 @@
# ================================================
1980..19AB ; New_Tai_Lue # Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
-19B0..19C0 ; New_Tai_Lue # Mc [17] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE VOWEL SIGN IY
-19C1..19C7 ; New_Tai_Lue # Lo [7] NEW TAI LUE LETTER FINAL V..NEW TAI LUE LETTER FINAL B
-19C8..19C9 ; New_Tai_Lue # Mc [2] NEW TAI LUE TONE MARK-1..NEW TAI LUE TONE MARK-2
+19B0..19C9 ; New_Tai_Lue # Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
19D0..19D9 ; New_Tai_Lue # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
19DA ; New_Tai_Lue # No NEW TAI LUE THAM DIGIT ONE
19DE..19DF ; New_Tai_Lue # So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
@@ -1770,11 +1782,12 @@
# ================================================
-12000..12398 ; Cuneiform # Lo [921] CUNEIFORM SIGN A..CUNEIFORM SIGN UM TIMES ME
+12000..12399 ; Cuneiform # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U
12400..1246E ; Cuneiform # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
12470..12474 ; Cuneiform # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
-
-# Total code points: 1037
+12480..12543 ; Cuneiform # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
+
+# Total code points: 1234
# ================================================
@@ -2151,9 +2164,12 @@
# ================================================
109A0..109B7 ; Meroitic_Cursive # Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA
+109BC..109BD ; Meroitic_Cursive # No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
109BE..109BF ; Meroitic_Cursive # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
-
-# Total code points: 26
+109C0..109CF ; Meroitic_Cursive # No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
+109D2..109FF ; Meroitic_Cursive # No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
+
+# Total code points: 90
# ================================================
@@ -2180,12 +2196,16 @@
111B6..111BE ; Sharada # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
111BF..111C0 ; Sharada # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
111C1..111C4 ; Sharada # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM
-111C5..111C8 ; Sharada # Po [4] SHARADA DANDA..SHARADA SEPARATOR
+111C5..111C9 ; Sharada # Po [5] SHARADA DANDA..SHARADA SANDHI MARK
+111CA..111CC ; Sharada # Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK
111CD ; Sharada # Po SHARADA SUTRA MARK
111D0..111D9 ; Sharada # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE
111DA ; Sharada # Lo SHARADA EKAM
-
-# Total code points: 85
+111DB ; Sharada # Po SHARADA SIGN SIDDHAM
+111DC ; Sharada # Lo SHARADA HEADSTROKE
+111DD..111DF ; Sharada # Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
+
+# Total code points: 94
# ================================================
@@ -2243,7 +2263,7 @@
# ================================================
-11301 ; Grantha # Mn GRANTHA SIGN CANDRABINDU
+11300..11301 ; Grantha # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
11302..11303 ; Grantha # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
11305..1130C ; Grantha # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
1130F..11310 ; Grantha # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI
@@ -2258,13 +2278,14 @@
11341..11344 ; Grantha # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
11347..11348 ; Grantha # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
1134B..1134D ; Grantha # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
+11350 ; Grantha # Lo GRANTHA OM
11357 ; Grantha # Mc GRANTHA AU LENGTH MARK
1135D..11361 ; Grantha # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL
11362..11363 ; Grantha # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
11366..1136C ; Grantha # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
11370..11374 ; Grantha # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
-# Total code points: 83
+# Total code points: 85
# ================================================
@@ -2407,9 +2428,11 @@
115BC..115BD ; Siddham # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
115BE ; Siddham # Mc SIDDHAM SIGN VISARGA
115BF..115C0 ; Siddham # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
-115C1..115C9 ; Siddham # Po [9] SIDDHAM SIGN SIDDHAM..SIDDHAM END OF TEXT MARK
-
-# Total code points: 72
+115C1..115D7 ; Siddham # Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
+115D8..115DB ; Siddham # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U
+115DC..115DD ; Siddham # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
+
+# Total code points: 92
# ================================================
@@ -2448,4 +2471,69 @@
# Total code points: 84
+# ================================================
+
+11700..11719 ; Ahom # Lo [26] AHOM LETTER KA..AHOM LETTER JHA
+1171D..1171F ; Ahom # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11720..11721 ; Ahom # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
+11722..11725 ; Ahom # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11726 ; Ahom # Mc AHOM VOWEL SIGN E
+11727..1172B ; Ahom # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
+11730..11739 ; Ahom # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE
+1173A..1173B ; Ahom # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY
+1173C..1173E ; Ahom # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
+1173F ; Ahom # So AHOM SYMBOL VI
+
+# Total code points: 57
+
+# ================================================
+
+14400..14646 ; Anatolian_Hieroglyphs # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
+
+# Total code points: 583
+
+# ================================================
+
+108E0..108F2 ; Hatran # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH
+108F4..108F5 ; Hatran # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
+108FB..108FF ; Hatran # No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
+
+# Total code points: 26
+
+# ================================================
+
+11280..11286 ; Multani # Lo [7] MULTANI LETTER A..MULTANI LETTER GA
+11288 ; Multani # Lo MULTANI LETTER GHA
+1128A..1128D ; Multani # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA
+1128F..1129D ; Multani # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA
+1129F..112A8 ; Multani # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA
+112A9 ; Multani # Po MULTANI SECTION MARK
+
+# Total code points: 38
+
+# ================================================
+
+10C80..10CB2 ; Old_Hungarian # L& [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
+10CC0..10CF2 ; Old_Hungarian # L& [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
+10CFA..10CFF ; Old_Hungarian # No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
+
+# Total code points: 108
+
+# ================================================
+
+1D800..1D9FF ; SignWriting # So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
+1DA00..1DA36 ; SignWriting # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA37..1DA3A ; SignWriting # So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
+1DA3B..1DA6C ; SignWriting # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA6D..1DA74 ; SignWriting # So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
+1DA75 ; SignWriting # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA76..1DA83 ; SignWriting # So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
+1DA84 ; SignWriting # Mn SIGNWRITING LOCATION HEAD NECK
+1DA85..1DA86 ; SignWriting # So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS
+1DA87..1DA8B ; SignWriting # Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS
+1DA9B..1DA9F ; SignWriting # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA1..1DAAF ; SignWriting # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+
+# Total code points: 672
+
# EOF
--- a/jdk/test/java/lang/Math/CubeRootTests.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Math/CubeRootTests.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,7 @@
/*
* @test
* @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
* @run main CubeRootTests
* @bug 4347132 4939441 8078672
* @summary Tests for {Math, StrictMath}.cbrt (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/HypotTests.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Math/HypotTests.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,7 @@
/*
* @test
* @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
* @run main HypotTests
* @bug 4851638 4939441 8078672
* @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/IeeeRecommendedTests.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Math/IeeeRecommendedTests.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,7 @@
/*
* @test
* @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
* @run main IeeeRecommendedTests
* @bug 4860891 4826732 4780454 4939441 4826652 8078672
* @summary Tests for IEEE 754[R] recommended functions and similar methods (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/Math/Log1pTests.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/Math/Log1pTests.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,7 @@
/*
* @test
* @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
* @run main Log1pTests
* @bug 4851638 4939441 8078672
* @summary Tests for {Math, StrictMath}.log1p (use -Dseed=X to set PRNG seed)
--- a/jdk/test/java/lang/StrictMath/CubeRootTests.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/StrictMath/CubeRootTests.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,11 +23,20 @@
/*
* @test
- * @bug 4347132
+ * @bug 4347132 8136799
+ * @key randomness
+ * @library /lib/testlibrary/
+ * @build jdk.testlibrary.RandomFactory
+ * @build Tests
+ * @build FdlibmTranslit
+ * @build CubeRootTests
+ * @run main CubeRootTests
* @summary Tests specifically for StrictMath.cbrt
* @author Joseph D. Darcy
*/
+import jdk.testlibrary.RandomFactory;
+
/**
* The tests in ../Math/CubeRootTests.java test properties that should
* hold for any cube root implementation, including the FDLIBM-based
@@ -42,6 +51,19 @@
public class CubeRootTests {
private CubeRootTests(){}
+ public static void main(String [] argv) {
+ int failures = 0;
+
+ failures += testCubeRoot();
+ failures += testAgainstTranslit();
+
+ if (failures > 0) {
+ System.err.println("Testing the cube root incurred "
+ + failures + " failures.");
+ throw new RuntimeException();
+ }
+ }
+
static int testCubeRootCase(double input, double expected) {
int failures=0;
@@ -458,16 +480,44 @@
return failures;
}
+ // Initialize shared random number generator
+ private static java.util.Random random = RandomFactory.getRandom();
- public static void main(String [] argv) {
+ /**
+ * Test StrictMath.cbrt against transliteration port of cbrt.
+ */
+ private static int testAgainstTranslit() {
int failures = 0;
+ double x;
- failures += testCubeRoot();
+ // Test just above subnormal threshold...
+ x = Double.MIN_NORMAL;
+ failures += testRange(x, Math.ulp(x), 1000);
+
+ // ... and just below subnormal threshold ...
+ x = Math.nextDown(Double.MIN_NORMAL);
+ failures += testRange(x, -Math.ulp(x), 1000);
- if (failures > 0) {
- System.err.println("Testing the cube root incurred "
- + failures + " failures.");
- throw new RuntimeException();
+ // ... and near zero.
+ failures += testRange(0.0, Double.MIN_VALUE, 1000);
+
+ x = Tests.createRandomDouble(random);
+
+ // Make the increment twice the ulp value in case the random
+ // value is near an exponent threshold. Don't worry about test
+ // elements overflowing to infinity if the starting value is
+ // near Double.MAX_VALUE.
+ failures += testRange(x, 2.0 * Math.ulp(x), 1000);
+
+ return failures;
+ }
+
+ private static int testRange(double start, double increment, int count) {
+ int failures = 0;
+ double x = start;
+ for (int i = 0; i < count; i++, x += increment) {
+ failures += testCubeRootCase(x, FdlibmTranslit.Cbrt.compute(x));
}
+ return failures;
}
}
--- a/jdk/test/java/lang/StrictMath/FdlibmTranslit.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/StrictMath/FdlibmTranslit.java Tue Oct 20 08:24:37 2015 -0700
@@ -73,6 +73,67 @@
}
/**
+ * cbrt(x)
+ * Return cube root of x
+ */
+ public static class Cbrt {
+ // unsigned
+ private static final int B1 = 715094163; /* B1 = (682-0.03306235651)*2**20 */
+ private static final int B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */
+
+ private static final double C = 5.42857142857142815906e-01; /* 19/35 = 0x3FE15F15, 0xF15F15F1 */
+ private static final double D = -7.05306122448979611050e-01; /* -864/1225 = 0xBFE691DE, 0x2532C834 */
+ private static final double E = 1.41428571428571436819e+00; /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */
+ private static final double F = 1.60714285714285720630e+00; /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */
+ private static final double G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */
+
+ public static strictfp double compute(double x) {
+ int hx;
+ double r, s, t=0.0, w;
+ int sign; // unsigned
+
+ hx = __HI(x); // high word of x
+ sign = hx & 0x80000000; // sign= sign(x)
+ hx ^= sign;
+ if (hx >= 0x7ff00000)
+ return (x+x); // cbrt(NaN,INF) is itself
+ if ((hx | __LO(x)) == 0)
+ return(x); // cbrt(0) is itself
+
+ x = __HI(x, hx); // x <- |x|
+ // rough cbrt to 5 bits
+ if (hx < 0x00100000) { // subnormal number
+ t = __HI(t, 0x43500000); // set t= 2**54
+ t *= x;
+ t = __HI(t, __HI(t)/3+B2);
+ } else {
+ t = __HI(t, hx/3+B1);
+ }
+
+ // new cbrt to 23 bits, may be implemented in single precision
+ r = t * t/x;
+ s = C + r*t;
+ t *= G + F/(s + E + D/s);
+
+ // chopped to 20 bits and make it larger than cbrt(x)
+ t = __LO(t, 0);
+ t = __HI(t, __HI(t)+0x00000001);
+
+
+ // 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-s is exact
+ t= t + t*r;
+
+ // retore the sign bit
+ t = __HI(t, __HI(t) | sign);
+ return(t);
+ }
+ }
+
+ /**
* hypot(x,y)
*
* Method :
--- a/jdk/test/java/lang/StrictMath/HypotTests.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/lang/StrictMath/HypotTests.java Tue Oct 20 08:24:37 2015 -0700
@@ -27,7 +27,7 @@
* @key randomness
* @summary Tests for StrictMath.hypot
* @library /lib/testlibrary/
- * @build jdk.testlibrary.*
+ * @build jdk.testlibrary.RandomFactory
* @build Tests
* @build FdlibmTranslit
* @build HypotTests
--- a/jdk/test/java/util/AbstractList/CheckForComodification.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/AbstractList/CheckForComodification.java Tue Oct 20 08:24:37 2015 -0700
@@ -42,7 +42,7 @@
for (int i : list)
if (i == LENGTH - 2)
list.remove(i);
- } catch(ConcurrentModificationException e) {
+ } catch (ConcurrentModificationException e) {
return;
}
throw new RuntimeException("No ConcurrentModificationException");
--- a/jdk/test/java/util/AbstractList/FailFastIterator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/AbstractList/FailFastIterator.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,7 @@
/**
* @test
* @bug 4189896
- * @summary AbstractList iterators previously checked for co-modificatin
+ * @summary AbstractList iterators previously checked for co-modification
* *after* the set/add/remove operations were performed.
*/
@@ -44,7 +44,7 @@
copy.add(new Integer(99));
i.remove();
throw new Exception("remove: iterator didn't fail fast");
- } catch(ConcurrentModificationException e) {
+ } catch (ConcurrentModificationException e) {
}
if (!copy.equals(orig))
throw new Exception("remove: iterator didn't fail fast enough");
@@ -56,7 +56,7 @@
copy.add(new Integer(99));
i.set(new Integer(666));
throw new Exception("set: iterator didn't fail fast");
- } catch(ConcurrentModificationException e) {
+ } catch (ConcurrentModificationException e) {
}
if (!copy.equals(orig))
throw new Exception("set: iterator didn't fail fast enough");
@@ -67,7 +67,7 @@
copy.add(new Integer(99));
i.add(new Integer(666));
throw new Exception("add: iterator didn't fail fast");
- } catch(ConcurrentModificationException e) {
+ } catch (ConcurrentModificationException e) {
}
if (!copy.equals(orig))
throw new Exception("add: iterator didn't fail fast enough");
--- a/jdk/test/java/util/Collection/BiggernYours.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collection/BiggernYours.java Tue Oct 20 08:24:37 2015 -0700
@@ -41,16 +41,16 @@
Object[] c2Array = c2.toArray();
check(c1Array.length == c2Array.length);
- for(Object aC1 : c1Array) {
+ for (Object aC1 : c1Array) {
boolean found = false;
- for(Object aC2 : c2Array) {
- if(Objects.equals(aC1, aC2)) {
+ for (Object aC2 : c2Array) {
+ if (Objects.equals(aC1, aC2)) {
found = true;
break;
}
}
- if(!found)
+ if (!found)
fail(aC1 + " not found in " + Arrays.toString(c2Array));
}
}
--- a/jdk/test/java/util/Collection/MOAT.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collection/MOAT.java Tue Oct 20 08:24:37 2015 -0700
@@ -101,7 +101,12 @@
testMap(new HashMap<Integer,Integer>());
testMap(new LinkedHashMap<Integer,Integer>());
- testMap(new WeakHashMap<Integer,Integer>());
+
+ // TODO: Add reliable support for WeakHashMap.
+ // This test is subject to very rare failures because the GC
+ // may remove unreferenced-keys from the map at any time.
+ // testMap(new WeakHashMap<Integer,Integer>());
+
testMap(new IdentityHashMap<Integer,Integer>());
testMap(new TreeMap<Integer,Integer>());
testMap(new Hashtable<Integer,Integer>());
@@ -343,6 +348,12 @@
return true;
}
+ // 6260652: (coll) Arrays.asList(x).toArray().getClass()
+ // should be Object[].class
+ // Fixed in jdk9, but not jdk8 ...
+ static final boolean needToWorkAround6260652 =
+ Arrays.asList("").toArray().getClass() != Object[].class;
+
private static void checkFunctionalInvariants(Collection<Integer> c) {
try {
checkContainsSelf(c);
@@ -356,7 +367,10 @@
}
check(c.toArray().length == c.size());
- check(c.toArray().getClass() == Object[].class);
+ check(c.toArray().getClass() == Object[].class
+ ||
+ (needToWorkAround6260652 &&
+ c.getClass().getName().equals("java.util.Arrays$ArrayList")));
for (int size : new int[]{0,1,c.size(), c.size()+1}) {
Integer[] a = c.toArray(new Integer[size]);
check((size > c.size()) || a.length == c.size());
@@ -408,7 +422,6 @@
catch (Throwable t) { unexpected(t); }
}
-
//----------------------------------------------------------------
// If add("x") succeeds, contains("x") & remove("x") should succeed
//----------------------------------------------------------------
@@ -1291,7 +1304,7 @@
equalNext(descItr, expected[idx--]);
descItr.remove();
- while(idx >= 0 && descItr.hasNext()) {
+ while (idx >= 0 && descItr.hasNext()) {
equalNext(descItr, expected[idx--]);
}
equal(descItr.hasNext(), false);
--- a/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java Tue Oct 20 08:24:37 2015 -0700
@@ -113,7 +113,7 @@
}
Set<T> uniq = new HashSet<>();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
T each = iter.next();
assertTrue(!uniq.contains(each));
uniq.add(each);
@@ -209,7 +209,7 @@
assertTrue(!pI.hasNext());
}
- while(mI.hasNext()) {
+ while (mI.hasNext()) {
pI = mI.next().iterator();
assertTrue(!pI.hasNext());
}
--- a/jdk/test/java/util/Collections/BigBinarySearch.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/BigBinarySearch.java Tue Oct 20 08:24:37 2015 -0700
@@ -61,13 +61,13 @@
}
}
- /** Check that binarySearch finds an element where we got it */
+ /** Checks that binarySearch finds an element where we got it. */
private static void checkBinarySearch(List<Integer> l, int i) {
try { equal(i, Collections.binarySearch(l, l.get(i))); }
catch (Throwable t) { unexpected(t); }
}
- /** Check that binarySearch finds an element where we got it */
+ /** Checks that binarySearch finds an element where we got it. */
private static void checkBinarySearch(List<Integer> l, int i,
Comparator<Integer> comparator) {
try { equal(i, Collections.binarySearch(l, l.get(i), comparator)); }
--- a/jdk/test/java/util/Collections/BinarySearchNullComparator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/BinarySearchNullComparator.java Tue Oct 20 08:24:37 2015 -0700
@@ -27,11 +27,10 @@
* @summary Test Collections.binarySearch() with a null comparator
*/
-
import java.util.*;
public class BinarySearchNullComparator {
- public static void main (String args[]) throws Exception {
+ public static void main(String args[]) throws Exception {
List list = Arrays.asList(new String[] {"I", "Love", "You"});
int result = Collections.binarySearch(list, "You", null);
--- a/jdk/test/java/util/Collections/CheckedListBash.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/CheckedListBash.java Tue Oct 20 08:24:37 2015 -0700
@@ -109,19 +109,19 @@
List even = clone(s);
Iterator it = even.iterator();
- while(it.hasNext())
- if(((Integer)it.next()).intValue() % 2 == 1)
+ while (it.hasNext())
+ if (((Integer)it.next()).intValue() % 2 == 1)
it.remove();
it = even.iterator();
- while(it.hasNext())
- if(((Integer)it.next()).intValue() % 2 == 1)
+ while (it.hasNext())
+ if (((Integer)it.next()).intValue() % 2 == 1)
fail("Failed to remove all odd nubmers.");
List odd = clone(s);
for (int i=0; i<(listSize/2); i++)
odd.remove(i);
for (int i=0; i<(listSize/2); i++)
- if(((Integer)odd.get(i)).intValue() % 2 != 1)
+ if (((Integer)odd.get(i)).intValue() % 2 != 1)
fail("Failed to remove all even nubmers.");
List all = clone(odd);
@@ -145,8 +145,8 @@
}
itAll = all.listIterator();
it = s.iterator();
- while(it.hasNext())
- if(it.next()==itAll.next())
+ while (it.hasNext())
+ if (it.next()==itAll.next())
fail("Iterator.set failed to change value.");
if (!all.equals(s))
fail("Failed to reconstruct ints with ListIterator.");
@@ -215,10 +215,10 @@
int preSize = s.size();
if (!s.add(e))
- fail ("Add failed.");
+ fail("Add failed.");
int postSize = s.size();
if (postSize-preSize != 1)
- fail ("Add didn't increase size by 1.");
+ fail("Add didn't increase size by 1.");
}
}
--- a/jdk/test/java/util/Collections/CheckedMapBash.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/CheckedMapBash.java Tue Oct 20 08:24:37 2015 -0700
@@ -134,7 +134,7 @@
fail("clear failed.");
Iterator i = m.entrySet().iterator();
- while(i.hasNext()) {
+ while (i.hasNext()) {
i.next();
i.remove();
}
@@ -142,12 +142,11 @@
fail("Iterator.remove() failed");
}
-
@DataProvider(name = "Bash.Supplier<Map<Integer,Integer>>", parallel = true)
public static Iterator<Object[]> bashNavigableMapProvider() {
ArrayList<Object[]> iters = new ArrayList<>(makeCheckedMaps());
iters.ensureCapacity(numItr * iters.size());
- for(int each=1; each < numItr; each++) {
+ for (int each=1; each < numItr; each++) {
iters.addAll( makeCheckedMaps());
}
return iters.iterator();
--- a/jdk/test/java/util/Collections/CheckedSetBash.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/CheckedSetBash.java Tue Oct 20 08:24:37 2015 -0700
@@ -130,14 +130,14 @@
boolean prePresent = s.contains(e);
boolean added = s.add(e);
if (!s.contains(e))
- fail ("Element not present after addition.");
+ fail("Element not present after addition.");
if (added == prePresent)
- fail ("added == alreadyPresent");
+ fail("added == alreadyPresent");
int postSize = s.size();
if (added && preSize == postSize)
- fail ("Add returned true, but size didn't change.");
+ fail("Add returned true, but size didn't change.");
if (!added && preSize != postSize)
- fail ("Add returned false, but size changed.");
+ fail("Add returned false, but size changed.");
}
}
@@ -145,7 +145,7 @@
public static Iterator<Object[]> navigableSetsProvider() {
ArrayList<Object[]> iters = new ArrayList<>(makeCheckedSets());
iters.ensureCapacity(numItr * iters.size());
- for(int each=1; each < numItr; each++) {
+ for (int each=1; each < numItr; each++) {
iters.addAll( makeCheckedSets());
}
return iters.iterator();
--- a/jdk/test/java/util/Collections/EmptyCollectionSerialization.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/EmptyCollectionSerialization.java Tue Oct 20 08:24:37 2015 -0700
@@ -62,7 +62,7 @@
copy.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(copy)) +
" is not the singleton " +
singleton.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(singleton)));
- } catch(Exception all) {
+ } catch (Exception all) {
fail(description + ": Unexpected Exception", all);
}
}
--- a/jdk/test/java/util/Collections/EmptyIterator.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/EmptyIterator.java Tue Oct 20 08:24:37 2015 -0700
@@ -29,13 +29,14 @@
import static java.util.Collections.*;
import java.util.*;
+import java.util.concurrent.SynchronousQueue;
public class EmptyIterator {
void test(String[] args) throws Throwable {
testEmptyCollection(emptyList());
testEmptyCollection(emptySet());
-
+ testEmptyCollection(new SynchronousQueue<Object>());
testEmptyMap(emptyMap());
Hashtable<?,?> emptyTable = new Hashtable<>();
--- a/jdk/test/java/util/Collections/EmptyNavigableMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/EmptyNavigableMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -282,7 +282,7 @@
// slightly smaller
NavigableMap ns = subMap.subMap(first, false, last, false);
- // slight exapansion
+ // slight expansion
assertThrows(() -> {
ns.subMap(first, true, last, true);
},
@@ -303,7 +303,7 @@
// slightly smaller
NavigableMap ns = subMap.headMap(BigInteger.ONE, false);
- // slight exapansion
+ // slight expansion
assertThrows(() -> {
ns.headMap(BigInteger.ONE, true);
},
@@ -324,7 +324,7 @@
// slightly smaller
NavigableMap ns = subMap.tailMap(BigInteger.ONE, false);
- // slight exapansion
+ // slight expansion
assertThrows(() -> {
ns.tailMap(BigInteger.ONE, true);
},
--- a/jdk/test/java/util/Collections/EmptyNavigableSet.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/EmptyNavigableSet.java Tue Oct 20 08:24:37 2015 -0700
@@ -301,7 +301,7 @@
// slightly smaller
NavigableSet ns = subSet.subSet(first, false, last, false);
- // slight exapansion
+ // slight expansion
assertThrows(() -> {
ns.subSet(first, true, last, true);
},
@@ -322,7 +322,7 @@
// slightly smaller
NavigableSet ns = subSet.headSet(BigInteger.ONE, false);
- // slight exapansion
+ // slight expansion
assertThrows(() -> {
ns.headSet(BigInteger.ONE, true);
},
@@ -343,7 +343,7 @@
// slightly smaller
NavigableSet ns = subSet.tailSet(BigInteger.ONE, false);
- // slight exapansion
+ // slight expansion
assertThrows(() -> {
ns.tailSet(BigInteger.ONE, true);
},
--- a/jdk/test/java/util/Collections/RacingCollections.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/RacingCollections.java Tue Oct 20 08:24:37 2015 -0700
@@ -62,14 +62,16 @@
this.start();
}
- @SuppressWarnings("unchecked") void clear(Object o) {
+ @SuppressWarnings("unchecked")
+ void clear(Object o) {
if (o instanceof Collection)
((Collection<?>)o).clear();
else
((Map<?,?>)o).clear();
}
- @SuppressWarnings("unchecked") void realRun() {
+ @SuppressWarnings("unchecked")
+ void realRun() {
// Mutate elLoco wildly forever, checking occasionally for "done"
clear(elLoco);
if (elLoco instanceof List) {
@@ -156,7 +158,7 @@
quittingTime = System.nanoTime() + workTimeMillis * 1024 * 1024;
}
boolean keepGoing() {
- return (i++ % 128 != 0) || (System.nanoTime() < quittingTime);
+ return (i++ % 128 != 0) || (System.nanoTime() - quittingTime < 0);
}
}
@@ -233,6 +235,7 @@
private static List<Queue<Integer>> newConcurrentQueues() {
List<Queue<Integer>> list =
new ArrayList<Queue<Integer>>(newConcurrentDeques());
+ list.add(new ArrayBlockingQueue<Integer>(10));
list.add(new LinkedBlockingQueue<Integer>(10));
list.add(new LinkedTransferQueue<Integer>());
list.add(new ConcurrentLinkedQueue<Integer>());
--- a/jdk/test/java/util/Collections/ReverseOrder.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/ReverseOrder.java Tue Oct 20 08:24:37 2015 -0700
@@ -25,7 +25,7 @@
* @test
* @bug 4593209 8001667
* @summary Reverse comparator was subtly broken
- * @author Josh bloch
+ * @author Josh Bloch
*/
import java.util.*;
--- a/jdk/test/java/util/Collections/RotateEmpty.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/RotateEmpty.java Tue Oct 20 08:24:37 2015 -0700
@@ -33,6 +33,6 @@
public static void main(String[] args) throws Exception {
List l = new ArrayList();
- Collections.rotate (l, 1);
+ Collections.rotate(l, 1);
}
}
--- a/jdk/test/java/util/Collections/T6433170.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/T6433170.java Tue Oct 20 08:24:37 2015 -0700
@@ -58,7 +58,6 @@
checkEmpty(checked);
}
-
//--------------------- Infrastructure ---------------------------
volatile int passed = 0, failed = 0;
void pass() {passed++;}
--- a/jdk/test/java/util/Collections/WrappedNull.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Collections/WrappedNull.java Tue Oct 20 08:24:37 2015 -0700
@@ -33,133 +33,133 @@
public class WrappedNull {
public static void main(String argv[]) throws Exception {
boolean testSucceeded = false;
- try{
+ try {
List l = Arrays.asList(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("Arrays.asList");
testSucceeded = false;
- try{
+ try {
Collection c = Collections.unmodifiableCollection(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("unmodifiableCollection");
testSucceeded = false;
- try{
+ try {
Set c = Collections.unmodifiableSet(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("unmodifiableSet");
testSucceeded = false;
- try{
+ try {
List c = Collections.unmodifiableList(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("unmodifiableList");
testSucceeded = false;
- try{
+ try {
Map c = Collections.unmodifiableMap(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("unmodifiableMap");
testSucceeded = false;
- try{
+ try {
SortedSet c = Collections.unmodifiableSortedSet(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("unmodifiableSortedSet");
testSucceeded = false;
- try{
+ try {
SortedMap c = Collections.unmodifiableSortedMap(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("unmodifiableSortedMap");
testSucceeded = false;
- try{
+ try {
Collection c = Collections.synchronizedCollection(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("synchronizedCollection");
testSucceeded = false;
- try{
+ try {
Set c = Collections.synchronizedSet(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("synchronizedSet");
testSucceeded = false;
- try{
+ try {
List c = Collections.synchronizedList(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("synchronizedList");
testSucceeded = false;
- try{
+ try {
Map c = Collections.synchronizedMap(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("synchronizedMap");
testSucceeded = false;
- try{
+ try {
SortedSet c = Collections.synchronizedSortedSet(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("synchronizedSortedSet");
testSucceeded = false;
- try{
+ try {
SortedMap c = Collections.synchronizedSortedMap(null);
}
catch (NullPointerException e) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("synchronizedSortedMap");
// Make sure that non-null arguments don't throw exc.
--- a/jdk/test/java/util/Hashtable/IllegalLoadFactor.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Hashtable/IllegalLoadFactor.java Tue Oct 20 08:24:37 2015 -0700
@@ -26,8 +26,6 @@
@summary Test for an illegalargumentexception on loadFactor
*/
-
-
import java.util.*;
/**
@@ -38,92 +36,92 @@
public static void main(String argv[]) throws Exception {
boolean testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
Hashtable bad1 = new Hashtable(100, -3);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("Hashtable, negative load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
Hashtable bad1 = new Hashtable(100, Float.NaN);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("Hashtable, NaN load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
HashMap bad1 = new HashMap(100, -3);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("HashMap, negative load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
HashMap bad1 = new HashMap(100, Float.NaN);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("HashMap, NaN load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
HashSet bad1 = new HashSet(100, -3);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("HashSet, negative load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
HashSet bad1 = new HashSet(100, Float.NaN);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("HashSet, NaN load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
WeakHashMap bad1 = new WeakHashMap(100, -3);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("WeakHashMap, negative load factor");
testSucceeded = false;
- try{
+ try {
// this should generate an IllegalArgumentException
WeakHashMap bad1 = new WeakHashMap(100, Float.NaN);
}
catch (IllegalArgumentException e1) {
testSucceeded = true;
}
- if(!testSucceeded)
+ if (!testSucceeded)
throw new Exception("WeakHashMap, NaN load factor");
// Make sure that legal creates don't throw exceptions
--- a/jdk/test/java/util/Hashtable/ReadObject.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Hashtable/ReadObject.java Tue Oct 20 08:24:37 2015 -0700
@@ -57,13 +57,13 @@
public Object get(Object key) {
ValueWrapper valueWrapper = (ValueWrapper)super.get(key);
Object value = valueWrapper.getValue();
- if(value instanceof ValueWrapper)
+ if (value instanceof ValueWrapper)
throw new RuntimeException("Hashtable.get bug");
return value;
}
public Object put(Object key, Object value) {
- if(value instanceof ValueWrapper)
+ if (value instanceof ValueWrapper)
throw new RuntimeException(
"Hashtable.put bug: value is already wrapped");
ValueWrapper valueWrapper = new ValueWrapper(value);
@@ -98,4 +98,4 @@
ReadObject myHashtableCopy = (ReadObject)copyObject(myHashtable);
String value = (String)myHashtableCopy.get("key");
}
-};
+}
--- a/jdk/test/java/util/IdentityHashMap/ToString.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/IdentityHashMap/ToString.java Tue Oct 20 08:24:37 2015 -0700
@@ -28,7 +28,6 @@
* @author Josh Bloch
*/
-
import java.util.*;
public class ToString {
--- a/jdk/test/java/util/LinkedHashMap/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/LinkedHashMap/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -83,12 +83,12 @@
Map<Integer,Integer> m = new LinkedHashMap();
for (int i=0; i<mapSize; i++)
if (m.put(new Integer(i), new Integer(2*i)) != null)
- throw new Exception("put returns non-null value erroenously.");
+ throw new Exception("put returns non-null value erroneously.");
for (int i=0; i<2*mapSize; i++)
if (m.containsValue(new Integer(i)) != (i%2==0))
throw new Exception("contains value "+i);
if (m.put(nil, nil) == null)
- throw new Exception("put returns a null value erroenously.");
+ throw new Exception("put returns a null value erroneously.");
Map<Integer,Integer> m2 = new LinkedHashMap(); m2.putAll(m);
if (!m.equals(m2))
throw new Exception("Clone not equal to original. (1)");
@@ -129,7 +129,7 @@
throw new Exception("clear failed.");
Iterator it = m.entrySet().iterator();
- while(it.hasNext()) {
+ while (it.hasNext()) {
it.next();
it.remove();
}
@@ -240,8 +240,8 @@
for (int i=0; i<mapSize; i++) {
Integer x = (Integer) l2.get(i);
- if(!x.equals(m.remove(x)))
- throw new Exception("Missing key: "+i+", "+x);
+ if (!x.equals(m.remove(x)))
+ throw new Exception("Missing key: "+i+", "+x);
if (!x.equals(m.computeIfAbsent(x, Integer::valueOf)))
throw new Exception("Wrong value: "+i+", "+m.get(x)+", "+x);
}
@@ -292,7 +292,7 @@
ObjectInputStream in = new ObjectInputStream(bis);
result = (Map)in.readObject();
in.close();
- } catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
return result;
--- a/jdk/test/java/util/LinkedHashMap/Cache.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/LinkedHashMap/Cache.java Tue Oct 20 08:24:37 2015 -0700
@@ -33,7 +33,7 @@
private static final int MAP_SIZE = 10;
private static final int NUM_KEYS = 100;
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) throws Exception {
Map m = new LinkedHashMap() {
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAP_SIZE;
--- a/jdk/test/java/util/LinkedHashSet/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/LinkedHashSet/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -99,7 +99,7 @@
static Set clone(Set s) throws Exception {
Set clone;
int method = rnd.nextInt(3);
- clone = (method==0 ? (Set) ((LinkedHashSet)s).clone() :
+ clone = (method==0 ? (Set) ((LinkedHashSet)s).clone() :
(method==1 ? new LinkedHashSet(Arrays.asList(s.toArray())) :
serClone(s)));
if (!s.equals(clone))
@@ -126,7 +126,7 @@
ObjectInputStream in = new ObjectInputStream(bis);
result = (Set)in.readObject();
in.close();
- } catch(Exception e) {
+ } catch (Exception e) {
e.printStackTrace();
}
return result;
--- a/jdk/test/java/util/LinkedList/Clone.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/LinkedList/Clone.java Tue Oct 20 08:24:37 2015 -0700
@@ -74,7 +74,7 @@
throw new RuntimeException("TreeMap.clone() is broken.");
}
- private static class LinkedList2 extends LinkedList {};
- private static class TreeSet2 extends TreeSet {};
- private static class TreeMap2 extends TreeMap {};
+ private static class LinkedList2 extends LinkedList {}
+ private static class TreeSet2 extends TreeSet {}
+ private static class TreeMap2 extends TreeMap {}
}
--- a/jdk/test/java/util/LinkedList/ComodifiedRemove.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/LinkedList/ComodifiedRemove.java Tue Oct 20 08:24:37 2015 -0700
@@ -41,10 +41,10 @@
list.add(o1);
ListIterator e = list.listIterator();
e.next();
- Object o2 = new Integer (2);
+ Object o2 = new Integer(2);
list.add(o2);
- try{
+ try {
e.remove();
} catch (ConcurrentModificationException cme) {
return;
--- a/jdk/test/java/util/List/ListDefaults.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/List/ListDefaults.java Tue Oct 20 08:24:37 2015 -0700
@@ -381,7 +381,7 @@
minBitCount = bitCount;
}
- // Resuse the supplier to store AtomicInteger instead of Integer
+ // Reuse the supplier to store AtomicInteger instead of Integer
// Hence the use of raw type and cast
List<AtomicInteger> incomparablesData = new ArrayList<>();
for (int i = 0; i < test.expected.size(); i++) {
--- a/jdk/test/java/util/Map/Defaults.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Map/Defaults.java Tue Oct 20 08:24:37 2015 -0700
@@ -464,7 +464,7 @@
@Test(dataProvider = "MergeCases")
private void testMerge(String description, Map<IntegerEnum, String> map, Merging.Value oldValue, Merging.Value newValue, Merging.Merger merger, Merging.Value put, Merging.Value result) {
// add and check initial conditions.
- switch(oldValue) {
+ switch (oldValue) {
case ABSENT :
map.remove(EXTRA_KEY);
assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
@@ -490,7 +490,7 @@
// check result
- switch(result) {
+ switch (result) {
case NULL :
assertNull(returned, "wrong value");
break;
@@ -505,7 +505,7 @@
}
// check map
- switch(put) {
+ switch (put) {
case ABSENT :
assertFalse(map.containsKey(EXTRA_KEY), "key not absent");
break;
@@ -610,7 +610,6 @@
return all;
}
-
private static Collection<Object[]> makeRWMapsNoNulls() {
Collection<Object[]> all = new ArrayList<>();
@@ -656,8 +655,8 @@
return all;
}
+
/**
- *
* @param nullKeys include null keys
* @param nullValues include null values
* @return
@@ -674,7 +673,6 @@
}
/**
- *
* @param nulls include null values
* @return
*/
@@ -702,7 +700,6 @@
}
/**
- *
* @param nulls include nulls
* @return
*/
@@ -712,8 +709,7 @@
});
}
- /**
- *
+ /**
* @param supplier a supplier of mutable map instances.
*
* @param nullKeys include null keys
@@ -774,15 +770,15 @@
static Collection<Object[]> makeMergeTestCases() {
Collection<Object[]> cases = new ArrayList<>();
- for( Object[] mapParams : makeAllRWMaps() ) {
+ for (Object[] mapParams : makeAllRWMaps() ) {
cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.ABSENT, Merging.Value.NEWVALUE, Merging.Merger.UNUSED, Merging.Value.NEWVALUE, Merging.Value.NEWVALUE });
}
- for( Object[] mapParams : makeAllRWMaps() ) {
+ for (Object[] mapParams : makeAllRWMaps() ) {
cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.NULL, Merging.Value.ABSENT, Merging.Value.NULL });
}
- for( Object[] mapParams : makeAllRWMaps() ) {
+ for (Object[] mapParams : makeAllRWMaps() ) {
cases.add(new Object[] { mapParams[0], mapParams[1], Merging.Value.OLDVALUE, Merging.Value.NEWVALUE, Merging.Merger.RESULT, Merging.Value.RESULT, Merging.Value.RESULT });
}
@@ -813,7 +809,7 @@
}
public static <T extends Throwable> void assertThrows(Class<T> throwable, String message, Thrower<T>... throwers) {
- for(Thrower<T> thrower : throwers) {
+ for (Thrower<T> thrower : throwers) {
assertThrows(thrower, throwable, message);
}
}
@@ -834,7 +830,7 @@
* @param <K> Type of keys
* @param <V> Type of values
*/
- public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K, V> {
+ public static class ExtendsAbstractMap<M extends Map<K,V>, K, V> extends AbstractMap<K,V> {
protected final M map;
@@ -842,8 +838,8 @@
protected ExtendsAbstractMap(M map) { this.map = map; }
- public Set<Map.Entry<K, V>> entrySet() {
- return new AbstractSet<Map.Entry<K, V>>() {
+ public Set<Map.Entry<K,V>> entrySet() {
+ return new AbstractSet<Map.Entry<K,V>>() {
public int size() {
return map.size();
}
@@ -876,7 +872,7 @@
* @param <K> Type of keys
* @param <V> Type of values
*/
- public static class ImplementsConcurrentMap<K, V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
+ public static class ImplementsConcurrentMap<K,V> extends ExtendsAbstractMap<ConcurrentMap<K,V>, K, V> implements ConcurrentMap<K,V> {
public ImplementsConcurrentMap() { super(new ConcurrentHashMap<K,V>()); }
// ConcurrentMap reabstracts these methods
--- a/jdk/test/java/util/Map/Get.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Map/Get.java Tue Oct 20 08:24:37 2015 -0700
@@ -119,7 +119,7 @@
static void check(boolean cond) { if (cond) pass(); else fail(); }
static void check(String desc, boolean cond) { if (cond) pass(); else fail(desc); }
static void equal(Object x, Object y) {
- if(Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);
+ if (Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);
}
public static void main(String[] args) throws Throwable {
--- a/jdk/test/java/util/NavigableMap/LockStep.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/NavigableMap/LockStep.java Tue Oct 20 08:24:37 2015 -0700
@@ -228,8 +228,8 @@
if (maybe(4) && s instanceof Serializable) {
try {
equal2(s, serialClone(s));
- } catch(RuntimeException uhoh) {
- if(!(uhoh.getCause() instanceof NotSerializableException)) {
+ } catch (RuntimeException uhoh) {
+ if (!(uhoh.getCause() instanceof NotSerializableException)) {
throw uhoh;
}
}
--- a/jdk/test/java/util/Optional/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Optional/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -294,6 +294,46 @@
}
@Test(groups = "unit")
+ public void testOr() {
+ Optional<String> empty = Optional.empty();
+ Optional<String> duke = Optional.of("Duke");
+
+ // Null supplier
+ try {
+ Optional<String> b = empty.or(null);
+ fail("Should throw NPE on null supplier");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+
+ // Supply null
+ try {
+ Optional<String> b = empty.or(() -> null);
+ fail("Should throw NPE when supplier returns null");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+
+ // Non-empty won't invoke supplier
+ try {
+ Optional<String> b = duke.or(() -> null);
+ assertTrue(b.isPresent());
+ } catch (NullPointerException npe) {
+ fail("Supplier should not be invoked");
+ }
+
+ // Supply for empty
+ Optional<String> suppliedDuke = empty.or(() -> duke);
+ assertTrue(suppliedDuke.isPresent());
+ assertSame(suppliedDuke, duke);
+
+ // Supply for non-empty
+ Optional<String> actualDuke = duke.or(() -> Optional.of("Other Duke"));
+ assertTrue(actualDuke.isPresent());
+ assertSame(actualDuke, duke);
+ }
+
+ @Test(groups = "unit")
public void testStream() {
{
Stream<String> s = Optional.<String>empty().stream();
--- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java Tue Oct 20 08:24:37 2015 -0700
@@ -126,19 +126,19 @@
}
{
- Spliterator<?> s = Spliterators.spliterator(l.iterator( ), 1, 0);
+ Spliterator<?> s = Spliterators.spliterator(l.iterator(), 1, 0);
assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
}
{
- Spliterator<?> s = Spliterators.spliterator(l.iterator( ), 1, Spliterator.CONCURRENT);
+ Spliterator<?> s = Spliterators.spliterator(l.iterator(), 1, Spliterator.CONCURRENT);
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
assertCharacteristics(s, Spliterator.CONCURRENT);
}
{
- Spliterator<?> s = Spliterators.spliteratorUnknownSize(l.iterator( ), 0);
+ Spliterator<?> s = Spliterators.spliteratorUnknownSize(l.iterator(), 0);
assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED);
}
--- a/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Spliterator/SpliteratorLateBindingFailFastTest.java Tue Oct 20 08:24:37 2015 -0700
@@ -214,7 +214,7 @@
db.addMap(LinkedHashMap::new);
- // This fails when run through jrteg but passes when run though
+ // This fails when run through jtreg but passes when run through
// ant
// db.addMap(IdentityHashMap::new);
--- a/jdk/test/java/util/TimSort/Sorter.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/TimSort/Sorter.java Tue Oct 20 08:24:37 2015 -0700
@@ -46,7 +46,7 @@
for (int i=0; i < 10000; i++) {
for (Sorter s : values()) {
- Integer[] test= gold.clone();
+ Integer[] test = gold.clone();
s.sort(test);
}
}
--- a/jdk/test/java/util/TreeMap/ContainsValue.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/TreeMap/ContainsValue.java Tue Oct 20 08:24:37 2015 -0700
@@ -30,7 +30,7 @@
import java.util.*;
public class ContainsValue {
- public static void main (String[] args) {
+ public static void main(String[] args) {
Map map = new TreeMap();
if (map.containsValue ("gemutlichkeit"))
--- a/jdk/test/java/util/TreeMap/HeadTailTypeError.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/TreeMap/HeadTailTypeError.java Tue Oct 20 08:24:37 2015 -0700
@@ -32,71 +32,70 @@
public class HeadTailTypeError {
public static void main(String argv[]) throws Exception {
- try{
+ try {
SortedMap m = new TreeMap();
m.headMap(new Object());
throw new Exception("headMap, natural ordering");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedMap m = new TreeMap();
m.tailMap(new Object());
throw new Exception("tailMap, natural ordering");
} catch (ClassCastException e) {
}
-
- try{
+ try {
SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
m.headMap(new Integer(0));
throw new Exception("headMap, explicit comparator");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
m.tailMap(new Integer(0));
throw new Exception("tailMap, explicit comparator");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedSet m = new TreeSet();
m.headSet(new Object());
throw new Exception("headSet, natural ordering");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedSet m = new TreeSet();
m.tailSet(new Object());
throw new Exception("tailSet, natural ordering");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
m.headSet(new Integer(0));
throw new Exception("headSet, explicit comparator");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
m.tailSet(new Integer(0));
throw new Exception("tailSet, explicit comparator");
} catch (ClassCastException e) {
}
- try{
+ try {
SortedMap m = new TreeMap();
m.headMap(null);
throw new Exception("(null endpoint)headMap, natural ordering");
} catch (NullPointerException e) {
}
- try{
+ try {
SortedMap m = new TreeMap();
m.tailMap(null);
throw new Exception("(null endpoint)tailMap, natural ordering");
@@ -104,42 +103,42 @@
}
- try{
+ try {
SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
m.headMap(null);
throw new Exception("(null endpoint)headMap, explicit comparator");
} catch (NullPointerException e) {
}
- try{
+ try {
SortedMap m = new TreeMap(String.CASE_INSENSITIVE_ORDER);
m.tailMap(null);
throw new Exception("(null endpoint)tailMap, explicit comparator");
} catch (NullPointerException e) {
}
- try{
+ try {
SortedSet m = new TreeSet();
m.headSet(null);
throw new Exception("(null endpoint)headSet, natural ordering");
} catch (NullPointerException e) {
}
- try{
+ try {
SortedSet m = new TreeSet();
m.tailSet(null);
throw new Exception("(null endpoint)tailSet, natural ordering");
} catch (NullPointerException e) {
}
- try{
+ try {
SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
m.headSet(null);
throw new Exception("(null endpoint)headSet, explicit comparator");
} catch (NullPointerException e) {
}
- try{
+ try {
SortedSet m = new TreeSet(String.CASE_INSENSITIVE_ORDER);
m.tailSet(null);
throw new Exception("(null endpoint)tailSet, explicit comparator");
--- a/jdk/test/java/util/TreeMap/SubMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/TreeMap/SubMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -40,7 +40,7 @@
boolean exc = false;
try {
m2.firstKey();
- } catch(NoSuchElementException e) {
+ } catch (NoSuchElementException e) {
exc = true;
}
if (!exc)
@@ -49,7 +49,7 @@
exc = false;
try {
m2.lastKey();
- } catch(NoSuchElementException e) {
+ } catch (NoSuchElementException e) {
exc = true;
}
if (!exc)
@@ -70,7 +70,7 @@
exc = false;
try {
s2.first();
- } catch(NoSuchElementException e) {
+ } catch (NoSuchElementException e) {
exc = true;
}
if (!exc)
@@ -79,7 +79,7 @@
exc = false;
try {
s2.last();
- } catch(NoSuchElementException e) {
+ } catch (NoSuchElementException e) {
exc = true;
}
if (!exc)
--- a/jdk/test/java/util/Vector/ComodifiedRemoveAllElements.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Vector/ComodifiedRemoveAllElements.java Tue Oct 20 08:24:37 2015 -0700
@@ -25,7 +25,7 @@
* @test
* @bug 4298133
* @summary Due to a bug in Vector's removeAllElements(),
- * the modification counter would not get incremented.
+ * the modification counter would not get incremented.
* @author Konstantin Kladko
*/
@@ -37,7 +37,7 @@
v.addElement(null);
Iterator it = v.iterator();
v.removeAllElements();
- try{
+ try {
it.next();
} catch (ConcurrentModificationException cme) {
return;
--- a/jdk/test/java/util/Vector/IllegalConstructorArgs.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Vector/IllegalConstructorArgs.java Tue Oct 20 08:24:37 2015 -0700
@@ -39,7 +39,7 @@
public static void main(String argv[]) {
int testSucceeded=0;
- try{
+ try {
// this should generate an IllegalArgumentException
Vector bad1 = new Vector(-100, 10);
}
@@ -50,8 +50,8 @@
testSucceeded =0;
}
- if(testSucceeded == 0)
- throw new RuntimeException("Wrong exception thrown.");
+ if (testSucceeded == 0)
+ throw new RuntimeException("Wrong exception thrown.");
}
--- a/jdk/test/java/util/Vector/LastIndexOf.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Vector/LastIndexOf.java Tue Oct 20 08:24:37 2015 -0700
@@ -34,7 +34,7 @@
public static void main(String argv[]) throws Exception {
Vector v = new Vector(10);
- try{
+ try {
int i = v.lastIndexOf(null, 5);
throw new Exception("lastIndexOf(5/10) " + i);
} catch (IndexOutOfBoundsException e) {
--- a/jdk/test/java/util/Vector/SyncLastIndexOf.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/Vector/SyncLastIndexOf.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,7 +36,7 @@
static class RemovingThread extends Thread {
public void run() {
- synchronized(v) {
+ synchronized (v) {
try {
sleep(200);
} catch (InterruptedException e) {
--- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,7 +24,6 @@
/*
* @test
* @bug 6499848
- * @ignore until 6842353 is resolved
* @summary Check that iterators work properly in the presence of
* concurrent finalization and removal of elements.
* @key randomness
@@ -116,7 +115,7 @@
it.next(); // protects first entry
System.out.println(map.values());
foos[first] = null;
- tryWaitForFinalizersToRun()
+ tryWaitForFinalizersToRun();
equal(map.size(), first+1);
System.out.println(map.values());
checkIterator(it, first-1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ArrayBlockingQueue/IteratorConsistency.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,755 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Random;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+
+/*
+ * @test
+ * @bug 7014263
+ * @summary White box testing of ArrayBlockingQueue iterators.
+ */
+
+/**
+ * Highly coupled to the implementation of ArrayBlockingQueue.
+ * Uses reflection to inspect queue and iterator state.
+ */
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class IteratorConsistency {
+ final Random rnd = new Random();
+ final int CAPACITY = 20;
+ Field itrsField;
+ Field itemsField;
+ Field takeIndexField;
+ Field headField;
+ Field nextField;
+ Field prevTakeIndexField;
+
+ void test(String[] args) throws Throwable {
+ itrsField = ArrayBlockingQueue.class.getDeclaredField("itrs");
+ itemsField = ArrayBlockingQueue.class.getDeclaredField("items");
+ takeIndexField = ArrayBlockingQueue.class.getDeclaredField("takeIndex");
+ headField = Class.forName("java.util.concurrent.ArrayBlockingQueue$Itrs").getDeclaredField("head");
+ nextField = Class.forName("java.util.concurrent.ArrayBlockingQueue$Itrs$Node").getDeclaredField("next");
+ prevTakeIndexField = Class.forName("java.util.concurrent.ArrayBlockingQueue$Itr").getDeclaredField("prevTakeIndex");
+ itrsField.setAccessible(true);
+ itemsField.setAccessible(true);
+ takeIndexField.setAccessible(true);
+ headField.setAccessible(true);
+ nextField.setAccessible(true);
+ prevTakeIndexField.setAccessible(true);
+ test(CAPACITY, true);
+ test(CAPACITY, false);
+ }
+
+ Object itrs(ArrayBlockingQueue q) {
+ try {
+ return itrsField.get(q);
+ } catch (Throwable t) { throw new Error(); }
+ }
+
+ int takeIndex(ArrayBlockingQueue q) {
+ try {
+ return takeIndexField.getInt(q);
+ } catch (Throwable t) { throw new Error(); }
+ }
+
+ List<Iterator> trackedIterators(Object itrs) {
+ try {
+ List<Iterator> its = new ArrayList<Iterator>();
+ if (itrs != null)
+ for (Object p = headField.get(itrs); p != null; p = nextField.get(p))
+ its.add(((WeakReference<Iterator>)(p)).get());
+ Collections.reverse(its);
+ return its;
+ } catch (Throwable t) { throw new Error(); }
+ }
+
+ List<Iterator> trackedIterators(ArrayBlockingQueue q) {
+ return trackedIterators(itrs(q));
+ }
+
+ List<Iterator> attachedIterators(Object itrs) {
+ try {
+ List<Iterator> its = new ArrayList<Iterator>();
+ if (itrs != null)
+ for (Object p = headField.get(itrs); p != null; p = nextField.get(p)) {
+ Iterator it = ((WeakReference<Iterator>)(p)).get();
+ if (it != null && !isDetached(it))
+ its.add(it);
+ }
+ Collections.reverse(its);
+ return its;
+ } catch (Throwable t) { unexpected(t); return null; }
+ }
+
+ List<Iterator> attachedIterators(ArrayBlockingQueue q) {
+ return attachedIterators(itrs(q));
+ }
+
+ Object[] internalArray(ArrayBlockingQueue q) {
+ try {
+ return (Object[]) itemsField.get(q);
+ } catch (Throwable t) { throw new Error(t); }
+ }
+
+ void printInternalArray(ArrayBlockingQueue q) {
+ System.err.println(Arrays.toString(internalArray(q)));
+ }
+
+ void checkExhausted(Iterator it) {
+ if (rnd.nextBoolean()) {
+ check(!it.hasNext());
+ check(isDetached(it));
+ }
+ if (rnd.nextBoolean())
+ try { it.next(); fail("should throw"); }
+ catch (NoSuchElementException success) {}
+ }
+
+ boolean isDetached(Iterator it) {
+ try {
+ return prevTakeIndexField.getInt(it) < 0;
+ } catch (IllegalAccessException t) { unexpected(t); return false; }
+ }
+
+ void checkDetached(Iterator it) {
+ check(isDetached(it));
+ }
+
+ void removeUsingIterator(ArrayBlockingQueue q, Object element) {
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ Object x = it.next();
+ if (element.equals(x))
+ it.remove();
+ checkRemoveThrowsISE(it);
+ }
+ }
+
+ void checkRemoveThrowsISE(Iterator it) {
+ if (rnd.nextBoolean())
+ return;
+ try { it.remove(); fail("should throw"); }
+ catch (IllegalStateException success) {}
+ }
+
+ void checkRemoveHasNoEffect(Iterator it, Collection c) {
+ if (rnd.nextBoolean())
+ return;
+ int size = c.size();
+ it.remove(); // no effect
+ equal(c.size(), size);
+ checkRemoveThrowsISE(it);
+ }
+
+ void checkIterationSanity(Queue q) {
+ if (rnd.nextBoolean())
+ return;
+ int size = q.size();
+ Object[] a = q.toArray();
+ Object[] b = new Object[size+2];
+ Arrays.fill(b, Boolean.TRUE);
+ Object[] c = q.toArray(b);
+ equal(a.length, size);
+ check(b == c);
+ check(b[size] == null);
+ check(b[size+1] == Boolean.TRUE);
+ equal(q.toString(), Arrays.toString(a));
+ Integer[] xx = null, yy = null;
+ if (size > 0) {
+ xx = new Integer[size - 1];
+ Arrays.fill(xx, 42);
+ yy = ((Queue<Integer>)q).toArray(xx);
+ for (Integer zz : xx)
+ equal(42, zz);
+ }
+ Iterator it = q.iterator();
+ for (int i = 0; i < size; i++) {
+ check(it.hasNext());
+ Object x = it.next();
+ check(x == a[i]);
+ check(x == b[i]);
+ if (xx != null) check(x == yy[i]);
+ }
+ check(!it.hasNext());
+ }
+
+ private static void waitForFinalizersToRun() {
+ for (int i = 0; i < 2; i++)
+ tryWaitForFinalizersToRun();
+ }
+
+ private static void tryWaitForFinalizersToRun() {
+ System.gc();
+ final CountDownLatch fin = new CountDownLatch(1);
+ new Object() { protected void finalize() { fin.countDown(); }};
+ System.gc();
+ try { fin.await(); }
+ catch (InterruptedException ie) { throw new Error(ie); }
+ }
+
+ void test(int capacity, boolean fair) {
+ //----------------------------------------------------------------
+ // q.clear will clear out itrs.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ check(q.add(i));
+ check(itrs(q) == null);
+ for (int i = 0; i < capacity; i++) {
+ its.add(q.iterator());
+ equal(trackedIterators(q), its);
+ q.poll();
+ q.add(capacity+i);
+ }
+ q.clear();
+ check(itrs(q) == null);
+ int j = 0;
+ for (Iterator it : its) {
+ if (rnd.nextBoolean())
+ check(it.hasNext());
+ equal(it.next(), j++);
+ checkExhausted(it);
+ }
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // q emptying will clear out itrs.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ check(itrs(q) == null);
+ for (int i = 0; i < capacity; i++) {
+ its.add(q.iterator());
+ equal(trackedIterators(q), its);
+ q.poll();
+ q.add(capacity+i);
+ }
+ for (int i = 0; i < capacity; i++)
+ q.poll();
+ check(itrs(q) == null);
+ int j = 0;
+ for (Iterator it : its) {
+ if (rnd.nextBoolean())
+ check(it.hasNext());
+ equal(it.next(), j++);
+ checkExhausted(it);
+ }
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Advancing 2 cycles will remove iterators.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ check(itrs(q) == null);
+ for (int i = capacity; i < 3 * capacity; i++) {
+ its.add(q.iterator());
+ equal(trackedIterators(q), its);
+ q.poll();
+ q.add(i);
+ }
+ for (int i = 3 * capacity; i < 4 * capacity; i++) {
+ equal(trackedIterators(q), its.subList(capacity,2*capacity));
+ q.poll();
+ q.add(i);
+ }
+ check(itrs(q) == null);
+ int j = 0;
+ for (Iterator it : its) {
+ if (rnd.nextBoolean())
+ check(it.hasNext());
+ equal(it.next(), j++);
+ checkExhausted(it);
+ }
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Interior removal of elements used by an iterator will cause
+ // it to be untracked.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ q.add(0);
+ for (int i = 1; i < 2 * capacity; i++) {
+ q.add(i);
+ Integer[] elts = { -1, -2, -3 };
+ for (Integer elt : elts) q.add(elt);
+ equal(q.remove(), i - 1);
+ Iterator it = q.iterator();
+ equal(it.next(), i);
+ equal(it.next(), elts[0]);
+ Collections.shuffle(Arrays.asList(elts));
+ check(q.remove(elts[0]));
+ check(q.remove(elts[1]));
+ equal(trackedIterators(q), Collections.singletonList(it));
+ check(q.remove(elts[2]));
+ check(itrs(q) == null);
+ equal(it.next(), -2);
+ if (rnd.nextBoolean()) checkExhausted(it);
+ if (rnd.nextBoolean()) checkDetached(it);
+ }
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check iterators on an empty q
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ for (int i = 0; i < 4; i++) {
+ Iterator it = q.iterator();
+ check(itrs(q) == null);
+ if (rnd.nextBoolean()) checkExhausted(it);
+ if (rnd.nextBoolean()) checkDetached(it);
+ checkRemoveThrowsISE(it);
+ }
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check "interior" removal of iterator's last element
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ for (int i = 0; i < capacity; i++) {
+ Iterator it = q.iterator();
+ its.add(it);
+ for (int j = 0; j < i; j++)
+ equal(j, it.next());
+ equal(attachedIterators(q), its);
+ }
+ q.remove(capacity - 1);
+ equal(attachedIterators(q), its);
+ for (int i = 1; i < capacity - 1; i++) {
+ q.remove(capacity - i - 1);
+ Iterator it = its.get(capacity - i);
+ checkDetached(it);
+ equal(attachedIterators(q), its.subList(0, capacity - i));
+ if (rnd.nextBoolean()) check(it.hasNext());
+ equal(it.next(), capacity - i);
+ checkExhausted(it);
+ }
+ equal(attachedIterators(q), its.subList(0, 2));
+ q.remove(0);
+ check(q.isEmpty());
+ check(itrs(q) == null);
+ Iterator it = its.get(0);
+ equal(it.next(), 0);
+ checkRemoveHasNoEffect(it, q);
+ checkExhausted(it);
+ checkDetached(it);
+ checkRemoveHasNoEffect(its.get(1), q);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check "interior" removal of alternating elements, straddling 2 cycles
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ // Move takeIndex to middle
+ for (int i = 0; i < capacity/2; i++) {
+ check(q.add(i));
+ equal(q.poll(), i);
+ }
+ check(takeIndex(q) == capacity/2);
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ for (int i = 0; i < capacity; i++) {
+ Iterator it = q.iterator();
+ its.add(it);
+ for (int j = 0; j < i; j++)
+ equal(j, it.next());
+ equal(attachedIterators(q), its);
+ }
+ // Remove all even elements, in either direction using
+ // q.remove(), or iterator.remove()
+ switch (rnd.nextInt(3)) {
+ case 0:
+ for (int i = 0; i < capacity; i+=2) {
+ check(q.remove(i));
+ equal(attachedIterators(q), its);
+ }
+ break;
+ case 1:
+ for (int i = capacity - 2; i >= 0; i-=2) {
+ check(q.remove(i));
+ equal(attachedIterators(q), its);
+ }
+ break;
+ case 2:
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ int i = (Integer) it.next();
+ if ((i & 1) == 0)
+ it.remove();
+ }
+ equal(attachedIterators(q), its);
+ break;
+ default: throw new Error();
+ }
+
+ for (int i = 0; i < capacity; i++) {
+ Iterator it = its.get(i);
+ boolean even = ((i & 1) == 0);
+ if (even) {
+ if (rnd.nextBoolean()) check(it.hasNext());
+ equal(i, it.next());
+ for (int j = i+1; j < capacity; j += 2)
+ equal(j, it.next());
+ check(!isDetached(it));
+ check(!it.hasNext());
+ check(isDetached(it));
+ } else { /* odd */
+ if (rnd.nextBoolean()) check(it.hasNext());
+ checkRemoveHasNoEffect(it, q);
+ equal(i, it.next());
+ for (int j = i+2; j < capacity; j += 2)
+ equal(j, it.next());
+ check(!isDetached(it));
+ check(!it.hasNext());
+ check(isDetached(it));
+ }
+ }
+ equal(trackedIterators(q), Collections.emptyList());
+ check(itrs(q) == null);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check garbage collection of discarded iterators
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ for (int i = 0; i < capacity; i++) {
+ its.add(q.iterator());
+ equal(attachedIterators(q), its);
+ }
+ its = null;
+ waitForFinalizersToRun();
+ List<Iterator> trackedIterators = trackedIterators(q);
+ equal(trackedIterators.size(), capacity);
+ for (Iterator x : trackedIterators)
+ check(x == null);
+ Iterator it = q.iterator();
+ equal(trackedIterators(q), Collections.singletonList(it));
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check garbage collection of discarded iterators,
+ // with a randomly retained subset.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ List<Iterator> retained = new ArrayList<Iterator>();
+ final int size = 1 + rnd.nextInt(capacity);
+ for (int i = 0; i < size; i++)
+ q.add(i);
+ for (int i = 0; i < size; i++) {
+ Iterator it = q.iterator();
+ its.add(it);
+ equal(attachedIterators(q), its);
+ }
+ // Leave sufficient gaps in retained
+ for (int i = 0; i < size; i+= 2+rnd.nextInt(3))
+ retained.add(its.get(i));
+ its = null;
+ waitForFinalizersToRun();
+ List<Iterator> trackedIterators = trackedIterators(q);
+ equal(trackedIterators.size(), size);
+ for (Iterator it : trackedIterators)
+ check((it == null) ^ retained.contains(it));
+ Iterator it = q.iterator(); // trigger another sweep
+ retained.add(it);
+ equal(trackedIterators(q), retained);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check incremental sweeping of discarded iterators.
+ // Excessively white box?!
+ //----------------------------------------------------------------
+ try {
+ final int SHORT_SWEEP_PROBES = 4;
+ final int LONG_SWEEP_PROBES = 16;
+ final int PROBE_HOP = LONG_SWEEP_PROBES + 6 * SHORT_SWEEP_PROBES;
+ final int PROBE_HOP_COUNT = 10;
+ // Expect around 8 sweeps per PROBE_HOP
+ final int SWEEPS_PER_PROBE_HOP = 8;
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ for (int i = 0; i < PROBE_HOP_COUNT * PROBE_HOP; i++) {
+ its.add(q.iterator());
+ equal(attachedIterators(q), its);
+ }
+ // make some garbage, separated by PROBE_HOP
+ for (int i = 0; i < its.size(); i += PROBE_HOP)
+ its.set(i, null);
+ waitForFinalizersToRun();
+ int retries;
+ for (retries = 0;
+ trackedIterators(q).contains(null) && retries < 1000;
+ retries++)
+ // one round of sweeping
+ its.add(q.iterator());
+ check(retries >= PROBE_HOP_COUNT * (SWEEPS_PER_PROBE_HOP - 2));
+ check(retries <= PROBE_HOP_COUNT * (SWEEPS_PER_PROBE_HOP + 2));
+ Iterator itsit = its.iterator();
+ while (itsit.hasNext())
+ if (itsit.next() == null)
+ itsit.remove();
+ equal(trackedIterators(q), its);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check safety of iterator.remove while in detached mode.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity/2; i++) {
+ q.add(i);
+ q.remove();
+ }
+ check(takeIndex(q) == capacity/2);
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ for (int i = 0; i < capacity; i++) {
+ Iterator it = q.iterator();
+ its.add(it);
+ for (int j = 0; j < i; j++)
+ equal(j, it.next());
+ equal(attachedIterators(q), its);
+ }
+ for (int i = capacity - 1; i >= 0; i--) {
+ Iterator it = its.get(i);
+ equal(i, it.next()); // last element
+ check(!isDetached(it));
+ check(!it.hasNext()); // first hasNext failure
+ check(isDetached(it));
+ int size = q.size();
+ check(q.contains(i));
+ switch (rnd.nextInt(3)) {
+ case 0:
+ it.remove();
+ check(!q.contains(i));
+ equal(q.size(), size - 1);
+ break;
+ case 1:
+ // replace i with impostor
+ if (q.remainingCapacity() == 0) {
+ check(q.remove(i));
+ check(q.add(-1));
+ } else {
+ check(q.add(-1));
+ check(q.remove(i));
+ }
+ it.remove(); // should have no effect
+ equal(size, q.size());
+ check(q.contains(-1));
+ check(q.remove(-1));
+ break;
+ case 2:
+ // replace i with true impostor
+ if (i != 0) {
+ check(q.remove(i));
+ check(q.add(i));
+ }
+ it.remove();
+ check(!q.contains(i));
+ equal(q.size(), size - 1);
+ break;
+ default: throw new Error();
+ }
+ checkRemoveThrowsISE(it);
+ check(isDetached(it));
+ check(!trackedIterators(q).contains(it));
+ }
+ check(q.isEmpty());
+ check(itrs(q) == null);
+ for (Iterator it : its)
+ checkExhausted(it);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check dequeues bypassing iterators' current positions.
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ Queue<Iterator> its0
+ = new ArrayDeque<Iterator>();
+ Queue<Iterator> itsMid
+ = new ArrayDeque<Iterator>();
+ List<Iterator> its = new ArrayList<Iterator>();
+ for (int i = 0; i < capacity; i++)
+ q.add(i);
+ for (int i = 0; i < 2 * capacity + 1; i++) {
+ Iterator it = q.iterator();
+ its.add(it);
+ its0.add(it);
+ }
+ for (int i = 0; i < 2 * capacity + 1; i++) {
+ Iterator it = q.iterator();
+ for (int j = 0; j < capacity/2; j++)
+ equal(j, it.next());
+ its.add(it);
+ itsMid.add(it);
+ }
+ for (int i = capacity; i < 3 * capacity; i++) {
+ Iterator it;
+
+ it = its0.remove();
+ checkRemoveThrowsISE(it);
+ if (rnd.nextBoolean()) check(it.hasNext());
+ equal(0, it.next());
+ int victim = i - capacity;
+ for (int j = victim + (victim == 0 ? 1 : 0); j < i; j++) {
+ if (rnd.nextBoolean()) check(it.hasNext());
+ equal(j, it.next());
+ }
+ checkExhausted(it);
+
+ it = itsMid.remove();
+ if (victim >= capacity/2)
+ checkRemoveHasNoEffect(it, q);
+ equal(capacity/2, it.next());
+ if (victim > capacity/2)
+ checkRemoveHasNoEffect(it, q);
+ for (int j = Math.max(victim, capacity/2 + 1); j < i; j++) {
+ if (rnd.nextBoolean()) check(it.hasNext());
+ equal(j, it.next());
+ }
+ checkExhausted(it);
+
+ if (rnd.nextBoolean()) {
+ equal(victim, q.remove());
+ } else {
+ ArrayList list = new ArrayList(1);
+ q.drainTo(list, 1);
+ equal(list.size(), 1);
+ equal(victim, list.get(0));
+ }
+ check(q.add(i));
+ }
+ // takeIndex has wrapped twice.
+ Iterator it0 = its0.remove();
+ Iterator itMid = itsMid.remove();
+ check(isDetached(it0));
+ check(isDetached(itMid));
+ if (rnd.nextBoolean()) check(it0.hasNext());
+ if (rnd.nextBoolean()) check(itMid.hasNext());
+ checkRemoveThrowsISE(it0);
+ checkRemoveHasNoEffect(itMid, q);
+ if (rnd.nextBoolean()) equal(0, it0.next());
+ if (rnd.nextBoolean()) equal(capacity/2, itMid.next());
+ check(isDetached(it0));
+ check(isDetached(itMid));
+ equal(capacity, q.size());
+ equal(0, q.remainingCapacity());
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check collective sanity of iteration, toArray() and toString()
+ //----------------------------------------------------------------
+ try {
+ ArrayBlockingQueue q = new ArrayBlockingQueue(capacity, fair);
+ for (int i = 0; i < capacity; i++) {
+ checkIterationSanity(q);
+ equal(capacity, q.size() + q.remainingCapacity());
+ q.add(i);
+ }
+ for (int i = 0; i < (capacity + (capacity >> 1)); i++) {
+ checkIterationSanity(q);
+ equal(capacity, q.size() + q.remainingCapacity());
+ equal(i, q.peek());
+ equal(i, q.poll());
+ checkIterationSanity(q);
+ equal(capacity, q.size() + q.remainingCapacity());
+ q.add(capacity + i);
+ }
+ for (int i = 0; i < capacity; i++) {
+ checkIterationSanity(q);
+ equal(capacity, q.size() + q.remainingCapacity());
+ int expected = i + capacity + (capacity >> 1);
+ equal(expected, q.peek());
+ equal(expected, q.poll());
+ }
+ checkIterationSanity(q);
+ } catch (Throwable t) { unexpected(t); }
+
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new IteratorConsistency().instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.err.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/BlockingQueue/DrainToFails.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,207 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Test drainTo failing due to c.add throwing
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class DrainToFails {
+ final int CAPACITY = 10;
+ final int SMALL = 2;
+
+ void test(String[] args) throws Throwable {
+ testDelayQueue(new DelayQueue());
+ testDelayQueue(new ScheduledThreadPoolExecutor(1).getQueue());
+
+ testUnbounded(new LinkedBlockingQueue());
+ testUnbounded(new LinkedBlockingDeque());
+ testUnbounded(new PriorityBlockingQueue());
+
+ testBounded(new LinkedBlockingQueue(CAPACITY));
+ testBounded(new LinkedBlockingDeque(CAPACITY));
+ testBounded(new ArrayBlockingQueue(CAPACITY));
+ }
+
+ static class PDelay
+ extends FutureTask<Void>
+ implements Delayed, RunnableScheduledFuture<Void> {
+ int pseudodelay;
+ PDelay(int i) {
+ super(new Runnable() { public void run() {}}, null);
+ pseudodelay = i;
+ }
+ public int compareTo(PDelay other) {
+ int a = this.pseudodelay;
+ int b = other.pseudodelay;
+ return (a < b) ? -1 : (a > b) ? 1 : 0;
+ }
+ public int compareTo(Delayed y) {
+ return compareTo((PDelay)y);
+ }
+ public boolean equals(Object other) {
+ return (other instanceof PDelay) &&
+ this.pseudodelay == ((PDelay)other).pseudodelay;
+ }
+ public long getDelay(TimeUnit ignore) {
+ return Integer.MIN_VALUE + pseudodelay;
+ }
+ public String toString() {
+ return String.valueOf(pseudodelay);
+ }
+ public boolean isPeriodic() { return false; }
+ }
+
+ void testDelayQueue(final BlockingQueue q) throws Throwable {
+ System.err.println(q.getClass().getSimpleName());
+ for (int i = 0; i < CAPACITY; i++)
+ q.add(new PDelay(i));
+ ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
+ try {
+ q.drainTo(q2, SMALL + 3);
+ fail("should throw");
+ } catch (IllegalStateException success) {
+ equal(SMALL, q2.size());
+ equal(new PDelay(0), q2.poll());
+ equal(new PDelay(1), q2.poll());
+ check(q2.isEmpty());
+ for (int i = SMALL; i < CAPACITY; i++)
+ equal(new PDelay(i), q.poll());
+ equal(0, q.size());
+ }
+ }
+
+ void testUnbounded(final BlockingQueue q) throws Throwable {
+ System.err.println(q.getClass().getSimpleName());
+ for (int i = 0; i < CAPACITY; i++)
+ q.add(i);
+ ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
+ try {
+ q.drainTo(q2, 7);
+ fail("should throw");
+ } catch (IllegalStateException success) {
+ assertContentsInOrder(q2, 0, 1);
+ q2.clear();
+ equal(q.size(), CAPACITY - SMALL);
+ equal(SMALL, q.peek());
+ }
+
+ try {
+ q.drainTo(q2);
+ fail("should throw");
+ } catch (IllegalStateException success) {
+ assertContentsInOrder(q2, 2, 3);
+ equal(q.size(), CAPACITY - 2 * SMALL);
+ for (int i = 2 * SMALL; i < CAPACITY; i++)
+ equal(i, q.poll());
+ equal(0, q.size());
+ }
+ }
+
+ void testBounded(final BlockingQueue q) throws Throwable {
+ System.err.println(q.getClass().getSimpleName());
+ for (int i = 0; i < CAPACITY; i++)
+ q.add(i);
+ List<Thread> putters = new ArrayList<Thread>();
+ for (int i = 0; i < 4; i++) {
+ Thread putter = new Thread(putter(q, 42 + i));
+ putters.add(putter);
+ putter.setDaemon(true);
+ putter.start();
+ }
+ ArrayBlockingQueue q2 = new ArrayBlockingQueue(SMALL);
+ try {
+ q.drainTo(q2, 7);
+ fail("should throw");
+ } catch (IllegalStateException success) {
+ while (q.size() < CAPACITY)
+ Thread.yield();
+ assertContentsInOrder(q2, 0, 1);
+ q2.clear();
+ }
+
+ try {
+ q.drainTo(q2);
+ fail("should throw");
+ } catch (IllegalStateException success) {
+ for (Thread putter : putters) {
+ putter.join(2000L);
+ check(! putter.isAlive());
+ }
+ assertContentsInOrder(q2, 2, 3);
+ for (int i = 2 * SMALL; i < CAPACITY; i++)
+ equal(i, q.poll());
+ equal(4, q.size());
+ check(q.contains(42));
+ check(q.contains(43));
+ check(q.contains(44));
+ check(q.contains(45));
+ }
+ }
+
+ Runnable putter(final BlockingQueue q, final int elt) {
+ return new Runnable() {
+ public void run() {
+ try { q.put(elt); }
+ catch (Throwable t) { unexpected(t); }}};
+ }
+
+ void assertContentsInOrder(Iterable it, Object... contents) {
+ int i = 0;
+ for (Object e : it)
+ equal(contents[i++], e);
+ equal(contents.length, i);
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new DrainToFails().instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java Tue Oct 20 08:24:37 2015 -0700
@@ -48,7 +48,8 @@
}
}
- static void checkInterrupted(Iterable<Fun> fs) {
+ static void checkInterrupted(Iterable<Fun> fs)
+ throws InterruptedException {
final Executor immediateExecutor = new Executor() {
public void execute(Runnable r) {
r.run(); }};
@@ -60,6 +61,7 @@
checkInterrupted0(fs, immediateExecutor);
checkInterrupted0(fs, delayedExecutor);
stpe.shutdown();
+ check(stpe.awaitTermination(10, SECONDS));
}
static void testQueue(final BlockingQueue<Object> q) {
@@ -96,8 +98,10 @@
}
checkInterrupted(fs);
} catch (Throwable t) {
- System.out.printf("Failed: %s%n", q.getClass().getSimpleName());
- unexpected(t);
+ System.out.printf("Failed: %s%n", q.getClass().getSimpleName());
+ unexpected(t);
+ } finally {
+ Thread.interrupted(); // clear interrupts, just in case
}
}
--- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -53,7 +53,6 @@
import static java.util.concurrent.ForkJoinPool.*;
import java.util.concurrent.atomic.AtomicInteger;
-
public class Basic {
static void checkCompletedNormally(CompletableFuture<?> cf, Object value) {
@@ -66,6 +65,7 @@
try { equalAnyOf(cf.get(), values); } catch (Throwable x) { unexpected(x); }
try { equalAnyOf(cf.get(0L, SECONDS), values); } catch (Throwable x) { unexpected(x); }
check(cf.isDone(), "Expected isDone to be true, got:" + cf);
+ check(!cf.isCompletedExceptionally(), "Expected isCompletedExceptionally to return false");
check(!cf.isCancelled(), "Expected isCancelled to be false");
check(!cf.cancel(true), "Expected cancel to return false");
check(cf.toString().contains("[Completed normally]"));
@@ -97,6 +97,7 @@
catch (CancellationException x) { if (cancelled) pass(); else fail(); }
catch (ExecutionException x) { if (cancelled) check(x.getCause() instanceof CancellationException); else pass(); }
check(cf.isDone(), "Expected isDone to be true, got:" + cf);
+ check(cf.isCompletedExceptionally(), "Expected isCompletedExceptionally");
check(cf.isCancelled() == cancelled, "Expected isCancelled: " + cancelled + ", got:" + cf.isCancelled());
check(cf.cancel(true) == cancelled, "Expected cancel: " + cancelled + ", got:" + cf.cancel(true));
check(cf.toString().contains("[Completed exceptionally]")); // ## TODO: 'E'xceptionally
@@ -805,6 +806,49 @@
cf2 = cf1.handle((x,t) -> { check(t.getCause() == ex); return 2;});
checkCompletedExceptionally(cf1);
checkCompletedNormally(cf2, 2);
+
+ cf1 = supplyAsync(() -> 1);
+ cf2 = cf1.handleAsync((x,t) -> x+1);
+ checkCompletedNormally(cf1, 1);
+ checkCompletedNormally(cf2, 2);
+
+ cf1 = supplyAsync(() -> { throw ex; });
+ cf2 = cf1.handleAsync((x,t) -> { check(t.getCause() == ex); return 2;});
+ checkCompletedExceptionally(cf1);
+ checkCompletedNormally(cf2, 2);
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // whenComplete tests
+ //----------------------------------------------------------------
+ try {
+ AtomicInteger count = new AtomicInteger();
+ CompletableFuture<Integer> cf2;
+ CompletableFuture<Integer> cf1 = supplyAsync(() -> 1);
+ cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement());
+ checkCompletedNormally(cf1, 1);
+ checkCompletedNormally(cf2, 1);
+ check(count.get() == 1, "action count should be incremented");
+
+ final RuntimeException ex = new RuntimeException();
+ cf1 = supplyAsync(() -> { throw ex; });
+ cf2 = cf1.whenComplete((x,t) -> count.getAndIncrement());
+ checkCompletedExceptionally(cf1);
+ checkCompletedExceptionally(cf2);
+ check(count.get() == 2, "action count should be incremented");
+
+ cf1 = supplyAsync(() -> 1);
+ cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement());
+ checkCompletedNormally(cf1, 1);
+ checkCompletedNormally(cf2, 1);
+ check(count.get() == 3, "action count should be incremented");
+
+ cf1 = supplyAsync(() -> { throw ex; });
+ cf2 = cf1.whenCompleteAsync((x,t) -> count.getAndIncrement());
+ checkCompletedExceptionally(cf1);
+ checkCompletedExceptionally(cf2);
+ check(count.get() == 4, "action count should be incremented");
+
} catch (Throwable t) { unexpected(t); }
}
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeAsyncTest.java Tue Oct 20 08:24:37 2015 -0700
@@ -27,7 +27,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
-
/**
* @test
* @bug 8029164
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Tue Oct 20 08:24:37 2015 -0700
@@ -33,7 +33,6 @@
import java.util.function.BiFunction;
import java.util.function.Consumer;
-
/**
* @test
* @bug 8068432 8072030
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentAssociateTest.java Tue Oct 20 08:24:37 2015 -0700
@@ -23,14 +23,18 @@
import org.testng.annotations.Test;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.stream.IntStream;
@@ -39,48 +43,52 @@
/**
* @test
* @bug 8028564
- * @run testng ConcurrentAssociateTest
+ * @run testng/timeout=1200 ConcurrentAssociateTest
* @summary Test that association operations, such as put and compute,
* place entries in the map
*/
@Test
public class ConcurrentAssociateTest {
- // The number of entries for each thread to place in a map
+ /** Maximum time (in seconds) to wait for a test method to complete. */
+ private static final int TIMEOUT = Integer.getInteger("timeout", 200);
+
+ /** The number of entries for each thread to place in a map. */
private static final int N = Integer.getInteger("n", 128);
- // The number of iterations of the test
- private static final int I = Integer.getInteger("i", 256);
- // Object to be placed in the concurrent map
+ /** The number of iterations of the test. */
+ private static final int I = Integer.getInteger("i", 64);
+
+ /** Objects to be placed in the concurrent map. */
static class X {
// Limit the hash code to trigger collisions
- int hc = ThreadLocalRandom.current().nextInt(1, 9);
+ final int hc = ThreadLocalRandom.current().nextInt(1, 9);
public int hashCode() { return hc; }
}
@Test
- public void testPut() {
+ public void testPut() throws Throwable {
test("CHM.put", (m, o) -> m.put(o, o));
}
@Test
- public void testCompute() {
+ public void testCompute() throws Throwable {
test("CHM.compute", (m, o) -> m.compute(o, (k, v) -> o));
}
@Test
- public void testComputeIfAbsent() {
+ public void testComputeIfAbsent() throws Throwable {
test("CHM.computeIfAbsent", (m, o) -> m.computeIfAbsent(o, (k) -> o));
}
@Test
- public void testMerge() {
+ public void testMerge() throws Throwable {
test("CHM.merge", (m, o) -> m.merge(o, o, (v1, v2) -> v1));
}
@Test
- public void testPutAll() {
+ public void testPutAll() throws Throwable {
test("CHM.putAll", (m, o) -> {
Map<Object, Object> hm = new HashMap<>();
hm.put(o, o);
@@ -88,7 +96,7 @@
});
}
- private static void test(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) {
+ private static void test(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) throws Throwable {
for (int i = 0; i < I; i++) {
testOnce(desc, associator);
}
@@ -100,13 +108,16 @@
}
}
- private static void testOnce(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) {
+ private static void testOnce(String desc, BiConsumer<ConcurrentMap<Object, Object>, Object> associator) throws Throwable {
ConcurrentHashMap<Object, Object> m = new ConcurrentHashMap<>();
CountDownLatch s = new CountDownLatch(1);
Supplier<Runnable> sr = () -> () -> {
try {
- s.await();
+ if (!s.await(TIMEOUT, TimeUnit.SECONDS)) {
+ dumpTestThreads();
+ throw new AssertionError("timed out");
+ }
}
catch (InterruptedException e) {
}
@@ -121,7 +132,7 @@
};
// Bound concurrency to avoid degenerate performance
- int ps = Math.min(Runtime.getRuntime().availableProcessors(), 32);
+ int ps = Math.min(Runtime.getRuntime().availableProcessors(), 8);
Stream<CompletableFuture> runners = IntStream.range(0, ps)
.mapToObj(i -> sr.get())
.map(CompletableFuture::runAsync);
@@ -131,16 +142,41 @@
// Trigger the runners to start associating
s.countDown();
+
try {
- all.join();
- } catch (CompletionException e) {
- Throwable t = e.getCause();
- if (t instanceof AssociationFailure) {
- throw (AssociationFailure) t;
+ all.get(TIMEOUT, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ dumpTestThreads();
+ throw e;
+ } catch (Throwable e) {
+ dumpTestThreads();
+ Throwable cause = e.getCause();
+ if (cause instanceof AssociationFailure) {
+ throw cause;
}
- else {
- throw e;
- }
+ throw e;
}
}
+
+ /**
+ * A debugging tool to print stack traces of most threads, as jstack does.
+ * Uninteresting threads are filtered out.
+ */
+ static void dumpTestThreads() {
+ ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+ System.err.println("------ stacktrace dump start ------");
+ for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
+ String name = info.getThreadName();
+ if ("Signal Dispatcher".equals(name))
+ continue;
+ if ("Reference Handler".equals(name)
+ && info.getLockName().startsWith("java.lang.ref.Reference$Lock"))
+ continue;
+ if ("Finalizer".equals(name)
+ && info.getLockName().startsWith("java.lang.ref.ReferenceQueue$Lock"))
+ continue;
+ System.err.print(info);
+ }
+ System.err.println("------ stacktrace dump end ------");
+ }
}
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentContainsKeyTest.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ConcurrentContainsKeyTest.java Tue Oct 20 08:24:37 2015 -0700
@@ -80,7 +80,6 @@
test(content, m);
}
-
private static void test(X[] content, ConcurrentHashMap<Object, Object> m) {
for (int i = 0; i < I; i++) {
testOnce(content, m);
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapCheck.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapCheck.java Tue Oct 20 08:24:37 2015 -0700
@@ -68,7 +68,6 @@
}
}
-
if (args.length > 1)
numTests = Integer.parseInt(args[1]);
@@ -92,7 +91,6 @@
TestTimer.printStats();
-
if (doSerializeTest)
stest(newMap(mapClass), size);
}
--- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -175,7 +175,7 @@
int position;
int total;
- Runner(Map<Integer,Integer> map, Integer[] key, CyclicBarrier barrier) {
+ Runner(Map<Integer,Integer> map, Integer[] key, CyclicBarrier barrier) {
this.map = map;
this.key = key;
this.barrier = barrier;
@@ -183,7 +183,7 @@
}
int step() {
- // random-walk around key positions, bunching accesses
+ // random-walk around key positions, bunching accesses
int r = rng.next();
position += (r & 7) - 3;
while (position >= key.length) position -= key.length;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/RemoveLeak.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,60 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8054446 8137184 8137185
+ * @summary Regression test for memory leak in remove(Object)
+ * @run main/othervm -Xmx2200k RemoveLeak
+ */
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class RemoveLeak {
+ public static void main(String[] args) {
+ int i = 0;
+ // Without bug fix, OutOfMemoryError was observed at iteration 65120
+ int iterations = 10 * 65120;
+ try {
+ ConcurrentLinkedQueue<Long> queue = new ConcurrentLinkedQueue<>();
+ queue.add(0L);
+ while (i++ < iterations) {
+ queue.add(1L);
+ queue.remove(1L);
+ }
+ } catch (Error t) {
+ System.err.printf("failed at iteration %d/%d%n", i, iterations);
+ throw t;
+ }
+ }
+}
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -47,10 +47,10 @@
AtomicInteger totalItems;
boolean print;
- // Suitable for benchmarking. Overriden by args[0] for testing.
+ // Suitable for benchmarking. Overridden by args[0] for testing.
int maxStages = 20;
- // Suitable for benchmarking. Overriden by args[1] for testing.
+ // Suitable for benchmarking. Overridden by args[1] for testing.
int items = 1024 * 1024;
Collection<Queue<Integer>> concurrentQueues() {
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java Tue Oct 20 08:24:37 2015 -0700
@@ -56,7 +56,7 @@
import java.util.Map;
public class GCRetention {
- // Suitable for benchmarking. Overriden by args[0] for testing.
+ // Suitable for benchmarking. Overridden by args[0] for testing.
int count = 1024 * 1024;
final Map<String,String> results = new ConcurrentHashMap<String,String>();
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Tue Oct 20 08:24:37 2015 -0700
@@ -42,6 +42,7 @@
@SuppressWarnings({"unchecked", "rawtypes"})
public class IteratorWeakConsistency {
+ final Random rnd = new Random();
void test(String[] args) throws Throwable {
test(new LinkedBlockingQueue());
@@ -51,14 +52,46 @@
test(new ConcurrentLinkedDeque());
test(new ConcurrentLinkedQueue());
test(new LinkedTransferQueue());
- // Other concurrent queues (e.g. ArrayBlockingQueue) do not
- // currently have weakly consistent iterators.
- // As of 2010-09, ArrayBlockingQueue passes this test, but
- // does not fully implement weak consistency.
test(new ArrayBlockingQueue(20));
}
+ void checkExhausted(Iterator it) {
+ if (rnd.nextBoolean()) {
+ check(!it.hasNext());
+ }
+ if (rnd.nextBoolean())
+ try { it.next(); fail("should throw"); }
+ catch (NoSuchElementException success) {}
+ }
+
+ void checkRemoveThrowsISE(Iterator it) {
+ if (rnd.nextBoolean()) {
+ try { it.remove(); fail("should throw"); }
+ catch (IllegalStateException success) {}
+ }
+ }
+
+ void checkRemoveHasNoEffect(Iterator it, Collection c) {
+ if (rnd.nextBoolean()) {
+ int size = c.size();
+ it.remove(); // no effect
+ equal(c.size(), size);
+ checkRemoveThrowsISE(it);
+ }
+ }
+
void test(Queue q) {
+ //----------------------------------------------------------------
+ // Check iterators on an empty q
+ //----------------------------------------------------------------
+ try {
+ for (int i = 0; i < 4; i++) {
+ Iterator it = q.iterator();
+ if (rnd.nextBoolean()) checkExhausted(it);
+ checkRemoveThrowsISE(it);
+ }
+ } catch (Throwable t) { unexpected(t); }
+
// TODO: make this more general
try {
for (int i = 0; i < 10; i++)
@@ -73,7 +106,7 @@
list.add(it.next());
equal(list, Arrays.asList(0, 3, 4, 5, 6, 8, 9));
check(! list.contains(null));
- System.out.printf("%s: %s%n",
+ System.err.printf("%s: %s%n",
q.getClass().getSimpleName(),
list);
} catch (Throwable t) { unexpected(t); }
@@ -96,6 +129,118 @@
check(found4);
} catch (Throwable t) { unexpected(t); }
+ try {
+ q.clear();
+ Object x = new Object();
+ for (int i = 0; i < 20; i++)
+ q.add(x);
+ equal(20, q.size());
+ Iterator it1 = q.iterator();
+ Iterator it2 = q.iterator();
+ try { it1.remove(); fail(); }
+ catch (IllegalStateException success) {}
+ try { it2.remove(); fail(); }
+ catch (IllegalStateException success) {}
+
+ check(it1.next() == x);
+ check(it2.hasNext());
+ check(it2.next() == x);
+ it1.remove();
+ it2.remove();
+ equal(19, q.size());
+ try { it1.remove(); fail(); }
+ catch (IllegalStateException success) {}
+ try { it2.remove(); fail(); }
+ catch (IllegalStateException success) {}
+ equal(19, q.size());
+
+ it1.next();
+ check(it2.hasNext());
+ it2.next();
+ it2.remove();
+ it1.remove();
+ equal(18, q.size());
+
+ it1.next();
+ it2.next();
+ check(q.remove() == x);
+ equal(17, q.size());
+ it1.remove();
+ it2.remove();
+ equal(17, q.size());
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check "interior" removal of alternating elements
+ //----------------------------------------------------------------
+ try {
+ q.clear();
+ final int remainingCapacity = (q instanceof BlockingQueue) ?
+ ((BlockingQueue)q).remainingCapacity() :
+ Integer.MAX_VALUE;
+ final int capacity = Math.min(20, remainingCapacity);
+ List<Iterator> its = new ArrayList<Iterator>();
+ // Move to "middle"
+ for (int i = 0; i < capacity/2; i++) {
+ check(q.add(i));
+ equal(q.poll(), i);
+ }
+ for (int i = 0; i < capacity; i++)
+ check(q.add(i));
+ for (int i = 0; i < capacity; i++) {
+ Iterator it = q.iterator();
+ its.add(it);
+ for (int j = 0; j < i; j++)
+ equal(j, it.next());
+ }
+
+ // Remove all even elements, in either direction using
+ // q.remove(), or iterator.remove()
+ switch (rnd.nextInt(3)) {
+ case 0:
+ for (int i = 0; i < capacity; i+=2)
+ check(q.remove(i));
+ break;
+ case 1:
+ for (int i = capacity - 2; i >= 0; i-=2)
+ check(q.remove(i));
+ break;
+ case 2:
+ Iterator it = q.iterator();
+ while (it.hasNext()) {
+ int i = (Integer) it.next();
+ if ((i & 1) == 0)
+ it.remove();
+ }
+ break;
+ default: throw new Error();
+ }
+
+ for (int i = 0; i < capacity; i++) {
+ Iterator it = its.get(i);
+ boolean even = ((i & 1) == 0);
+ if (even) {
+ if (rnd.nextBoolean()) check(it.hasNext());
+ equal(i, it.next());
+ for (int j = i+1; j < capacity; j += 2)
+ equal(j, it.next());
+ check(!it.hasNext());
+ } else { /* odd */
+ if (rnd.nextBoolean()) check(it.hasNext());
+ checkRemoveHasNoEffect(it, q);
+ equal(i, it.next());
+ for (int j = i+2; j < capacity; j += 2)
+ equal(j, it.next());
+ check(!it.hasNext());
+ }
+ }
+
+ // q only contains odd elements
+ for (int i = 0; i < capacity; i++)
+ check(q.contains(i) ^ ((i & 1) == 0));
+
+ } catch (Throwable t) { unexpected(t); }
+
}
//--------------------- Infrastructure ---------------------------
@@ -112,6 +257,6 @@
new IteratorWeakConsistency().instanceMain(args);}
public void instanceMain(String[] args) throws Throwable {
try {test(args);} catch (Throwable t) {unexpected(t);}
- System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ System.err.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new AssertionError("Some tests failed");}
}
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/OfferRemoveLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -32,6 +32,7 @@
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
+import static java.util.concurrent.TimeUnit.*;
@SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
public class OfferRemoveLoops {
@@ -65,15 +66,16 @@
}
void testQueue(final Queue q) throws Throwable {
- System.out.println(q.getClass().getSimpleName());
+ System.err.println(q.getClass().getSimpleName());
final long testDurationNanos = testDurationMillis * 1000L * 1000L;
final long quittingTimeNanos = System.nanoTime() + testDurationNanos;
final long timeoutMillis = 10L * 1000L;
final int maxChunkSize = 1042;
final int maxQueueSize = 10 * maxChunkSize;
+ final CountDownLatch done = new CountDownLatch(3);
- /** Poor man's bounded buffer. */
- final AtomicLong approximateCount = new AtomicLong(0L);
+ /** Poor man's bounded buffer; prevents unbounded queue expansion. */
+ final Semaphore offers = new Semaphore(maxQueueSize);
abstract class CheckedThread extends Thread {
CheckedThread(String name) {
@@ -89,42 +91,44 @@
protected boolean quittingTime(long i) {
return (i % 1024) == 0 && quittingTime();
}
- protected abstract void realRun();
+ protected abstract void realRun() throws Exception;
public void run() {
try { realRun(); } catch (Throwable t) { unexpected(t); }
}
}
Thread offerer = new CheckedThread("offerer") {
- protected void realRun() {
- final long chunkSize = getRandom().nextInt(maxChunkSize) + 2;
+ protected void realRun() throws InterruptedException {
+ final int chunkSize = getRandom().nextInt(maxChunkSize) + 20;
long c = 0;
- for (long i = 0; ! quittingTime(i); i++) {
+ while (! quittingTime()) {
if (q.offer(Long.valueOf(c))) {
if ((++c % chunkSize) == 0) {
- approximateCount.getAndAdd(chunkSize);
- while (approximateCount.get() > maxQueueSize)
- Thread.yield();
+ offers.acquire(chunkSize);
}
} else {
Thread.yield();
- }}}};
+ }
+ }
+ done.countDown();
+ }};
Thread remover = new CheckedThread("remover") {
protected void realRun() {
- final long chunkSize = getRandom().nextInt(maxChunkSize) + 2;
+ final int chunkSize = getRandom().nextInt(maxChunkSize) + 20;
long c = 0;
- for (long i = 0; ! quittingTime(i); i++) {
+ while (! quittingTime()) {
if (q.remove(Long.valueOf(c))) {
if ((++c % chunkSize) == 0) {
- approximateCount.getAndAdd(-chunkSize);
+ offers.release(chunkSize);
}
} else {
Thread.yield();
}
}
q.clear();
- approximateCount.set(0); // Releases waiting offerer thread
+ offers.release(1<<30); // Releases waiting offerer thread
+ done.countDown();
}};
Thread scanner = new CheckedThread("scanner") {
@@ -139,18 +143,19 @@
break;
}
Thread.yield();
- }}};
+ }
+ done.countDown();
+ }};
- for (Thread thread : new Thread[] { offerer, remover, scanner }) {
- thread.join(timeoutMillis + testDurationMillis);
- if (thread.isAlive()) {
- System.err.printf("Hung thread: %s%n", thread.getName());
- failed++;
- for (StackTraceElement e : thread.getStackTrace())
- System.err.println(e);
- // Kludge alert
- thread.stop();
- thread.join(timeoutMillis);
+ if (! done.await(timeoutMillis + testDurationMillis, MILLISECONDS)) {
+ for (Thread thread : new Thread[] { offerer, remover, scanner }) {
+ if (thread.isAlive()) {
+ System.err.printf("Hung thread: %s%n", thread.getName());
+ failed++;
+ for (StackTraceElement e : thread.getStackTrace())
+ System.err.println(e);
+ thread.interrupt();
+ }
}
}
}
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,7 +36,7 @@
* @bug 6785442
* @summary Checks race between poll and remove(Object), while
* occasionally moonlighting as a microbenchmark.
- * @run main RemovePollRace 12345
+ * @run main RemovePollRace 1234
*/
import java.util.concurrent.ArrayBlockingQueue;
@@ -56,7 +56,7 @@
import java.util.Map;
public class RemovePollRace {
- // Suitable for benchmarking. Overriden by args[0] for testing.
+ // Suitable for benchmarking. Overridden by args[0] for testing.
int count = 1024 * 1024;
final Map<String,String> results = new ConcurrentHashMap<String,String>();
@@ -100,6 +100,7 @@
void test(String[] args) throws Throwable {
if (args.length > 0)
count = Integer.valueOf(args[0]);
+
// Warmup
for (Queue<Boolean> queue : concurrentQueues())
test(queue);
--- a/jdk/test/java/util/concurrent/CopyOnWriteArrayList/COWSubList.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/CopyOnWriteArrayList/COWSubList.java Tue Oct 20 08:24:37 2015 -0700
@@ -51,8 +51,7 @@
r.run();
throw new RuntimeException("Failed: expected IOOBE to be thrown");
} catch (IndexOutOfBoundsException x) {
- // ok, excpeted
+ // ok, expected
}
}
}
-
--- a/jdk/test/java/util/concurrent/CountDownLatch/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/CountDownLatch/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -120,7 +120,7 @@
//----------------------------------------------------------------
// One thread interrupted
//----------------------------------------------------------------
- public static void threadInterrupted() throws Throwable{
+ public static void threadInterrupted() throws Throwable {
int count = 0;
Basic test = new Basic();
CountDownLatch latch = new CountDownLatch(3);
--- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -49,7 +49,6 @@
Int(int i) { value = i; }
}
-
public static void main(String[] args) throws Exception {
int maxStages = 5;
int iters = 10000;
--- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -111,8 +111,6 @@
if (r == 0) // avoid overoptimization
System.out.println("useless result: " + r);
-
-
}
}
--- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Tue Oct 20 08:24:37 2015 -0700
@@ -24,55 +24,71 @@
/*
* @test
* @bug 6399443
- * @run main/othervm AutoShutdown
+ * @run main/othervm/timeout=1000 AutoShutdown
* @summary Check for auto-shutdown and gc of singleThreadExecutors
* @author Martin Buchholz
*/
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.*;
-import static java.util.concurrent.Executors.*;
-import java.util.concurrent.Phaser;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import static java.util.concurrent.Executors.defaultThreadFactory;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
public class AutoShutdown {
- private static void waitForFinalizersToRun() {
- for (int i = 0; i < 2; i++)
- tryWaitForFinalizersToRun();
- }
- private static void tryWaitForFinalizersToRun() {
- System.gc();
- final CountDownLatch fin = new CountDownLatch(1);
- new Object() { protected void finalize() { fin.countDown(); }};
- System.gc();
- try { fin.await(); }
- catch (InterruptedException ie) { throw new Error(ie); }
+ static void await(CountDownLatch latch) throws InterruptedException {
+ if (!latch.await(100L, TimeUnit.SECONDS))
+ throw new AssertionError("timed out waiting for latch");
}
private static void realMain(String[] args) throws Throwable {
- final Phaser phaser = new Phaser(3);
- Runnable trivialRunnable = new Runnable() {
- public void run() {
- phaser.arriveAndAwaitAdvance();
- }
+ final Executor[] executors = {
+ newSingleThreadExecutor(),
+ newSingleThreadExecutor(defaultThreadFactory()),
+ // TODO: should these executors also auto-shutdown?
+ //newFixedThreadPool(1),
+ //newSingleThreadScheduledExecutor(),
+ //newSingleThreadScheduledExecutor(defaultThreadFactory()),
};
- int count0 = Thread.activeCount();
- Executor e1 = newSingleThreadExecutor();
- Executor e2 = newSingleThreadExecutor(defaultThreadFactory());
- e1.execute(trivialRunnable);
- e2.execute(trivialRunnable);
- phaser.arriveAndAwaitAdvance();
- equal(Thread.activeCount(), count0 + 2);
- e1 = e2 = null;
- for (int i = 0; i < 10 && Thread.activeCount() > count0; i++)
- tryWaitForFinalizersToRun();
- for (int i = 0; i < 10; ++i) { // give JVM a chance to settle.
- if (Thread.activeCount() == count0)
- return;
- Thread.sleep(1000);
+ final ConcurrentLinkedQueue<WeakReference<Thread>> poolThreads
+ = new ConcurrentLinkedQueue<>();
+ final CountDownLatch threadStarted
+ = new CountDownLatch(executors.length);
+ final CountDownLatch pleaseProceed
+ = new CountDownLatch(1);
+ Runnable task = new Runnable() { public void run() {
+ try {
+ poolThreads.add(new WeakReference<>(Thread.currentThread()));
+ threadStarted.countDown();
+ await(pleaseProceed);
+ } catch (Throwable t) { unexpected(t); }
+ }};
+ for (Executor executor : executors)
+ executor.execute(task);
+ await(threadStarted);
+ pleaseProceed.countDown();
+ Arrays.fill(executors, null); // make executors unreachable
+ boolean done = false;
+ for (long timeout = 1L; !done && timeout <= 128L; timeout *= 2) {
+ System.gc();
+ done = true;
+ for (WeakReference<Thread> ref : poolThreads) {
+ Thread thread = ref.get();
+ if (thread != null) {
+ TimeUnit.SECONDS.timedJoin(thread, timeout);
+ if (thread.isAlive())
+ done = false;
+ }
+ }
}
- equal(Thread.activeCount(), count0);
+ if (!done)
+ throw new AssertionError("pool threads did not terminate");
}
//--------------------- Infrastructure ---------------------------
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,100 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8073704
+ * @summary Checks that once isDone() returns true,
+ * get() never throws InterruptedException or TimeoutException
+ */
+
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class DoneMeansDone {
+ public static void main(String[] args) throws Throwable {
+ final int iters = 1000;
+ final int nThreads = 2;
+ final AtomicBoolean done = new AtomicBoolean(false);
+ final AtomicReference<FutureTask<Boolean>> a = new AtomicReference<>();
+ final CountDownLatch threadsStarted = new CountDownLatch(nThreads);
+ final Callable<Boolean> alwaysTrue = new Callable<Boolean>() {
+ public Boolean call() {
+ return true;
+ }};
+
+ final Runnable observer = new Runnable() { public void run() {
+ threadsStarted.countDown();
+ final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+ try {
+ for (FutureTask<Boolean> f; !done.get();) {
+ f = a.get();
+ if (f != null) {
+ do {} while (!f.isDone());
+ Thread.currentThread().interrupt();
+ if (!(rnd.nextBoolean()
+ ? f.get()
+ : f.get(-1L, TimeUnit.DAYS)))
+ throw new AssertionError();
+ }
+ }
+ } catch (Exception t) { throw new AssertionError(t); }
+ }};
+
+ final ArrayList<Future<?>> futures = new ArrayList<>(nThreads);
+ final ExecutorService pool = Executors.newCachedThreadPool();
+ for (int i = 0; i < nThreads; i++)
+ futures.add(pool.submit(observer));
+ threadsStarted.await();
+ for (int i = 0; i < iters; i++) {
+ FutureTask<Boolean> f = new FutureTask<>(alwaysTrue);
+ a.set(f);
+ f.run();
+ }
+ done.set(true);
+ pool.shutdown();
+ if (!pool.awaitTermination(10L, TimeUnit.SECONDS))
+ throw new AssertionError();
+ for (Future<?> future : futures)
+ future.get();
+ }
+}
--- a/jdk/test/java/util/concurrent/FutureTask/DoneTimedGetLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/FutureTask/DoneTimedGetLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -1,5 +1,4 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,6 +21,11 @@
*/
/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
* Written by Martin Buchholz with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
--- a/jdk/test/java/util/concurrent/FutureTask/ExplicitSet.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/FutureTask/ExplicitSet.java Tue Oct 20 08:24:37 2015 -0700
@@ -58,7 +58,7 @@
SettableTask() {
super(new Callable<Boolean>() {
public Boolean call() {
- fail ("The task should never be run!");
+ fail("The task should never be run!");
return null;
};
});
--- a/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java Tue Oct 20 08:24:37 2015 -0700
@@ -44,4 +44,3 @@
} catch (TimeoutException success) {}
}
}
-
--- a/jdk/test/java/util/concurrent/Phaser/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/Phaser/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -97,7 +97,8 @@
equal(phase, atTheStartingGate.arrive());
int awaitPhase = atTheStartingGate.awaitAdvanceInterruptibly
(phase, 30, SECONDS);
- if (expectNextPhase) check(awaitPhase == (phase + 1));
+ if (expectNextPhase) check(awaitPhase == phase + 1);
+ else check(awaitPhase == phase || awaitPhase == phase + 1);
pass();
} catch (Throwable t) {
@@ -249,13 +250,11 @@
Phaser phaser = new Phaser(3);
Iterator<Arriver> arrivers = arriverIterator(phaser);
int phase = phaser.getPhase();
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 10; i++) {
check(phaser.getPhase() == phase);
Awaiter a1 = awaiter(phaser, 30, SECONDS); a1.start();
Arriver a2 = arrivers.next(); a2.start();
toTheStartingGate();
- // allow a1 to block in awaitAdvanceInterruptibly
- Thread.sleep(2000);
a1.interrupt();
a1.join();
phaser.arriveAndAwaitAdvance();
@@ -273,7 +272,7 @@
// Phaser is terminated while threads are waiting
//----------------------------------------------------------------
try {
- for (int i = 0; i < 4; i++) {
+ for (int i = 0; i < 10; i++) {
Phaser phaser = new Phaser(3);
Iterator<Awaiter> awaiters = awaiterIterator(phaser);
Arriver a1 = awaiters.next(); a1.start();
--- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java Tue Oct 20 08:24:37 2015 -0700
@@ -88,7 +88,7 @@
/**
* Attempts to test exhaustively and deterministically, all 20
* possible ways that one task can be scheduled in the maximal
- * distant future, while at the same time an existing tasks's time
+ * distant future, while at the same time an existing task's time
* has already expired.
*/
void test(String[] args) throws Throwable {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,136 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea and Martin Buchholz with assistance from members of
+ * JCP JSR-166 Expert Group and released to the public domain, as explained
+ * at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Ensure that waiting pool threads don't retain refs to tasks.
+ */
+
+import java.lang.ref.*;
+import java.util.concurrent.*;
+
+public class GCRetention {
+ /**
+ * A custom thread pool with a custom RunnableScheduledFuture, for the
+ * sole purpose of ensuring that the task retains a strong reference to
+ * the Runnable even after cancellation.
+ */
+ static class CustomPool extends ScheduledThreadPoolExecutor {
+ CustomPool(int n) { super(n); }
+ protected <V> RunnableScheduledFuture<V> decorateTask(
+ final Runnable r,
+ final RunnableScheduledFuture<V> task) {
+ return new RunnableScheduledFuture<V>() {
+ public void run() { System.err.println(r); task.run(); }
+ public boolean isPeriodic() { return task.isPeriodic(); }
+ public V get()
+ throws InterruptedException,ExecutionException
+ { return task.get(); }
+ public V get(long x, TimeUnit y)
+ throws InterruptedException,ExecutionException,TimeoutException
+ { return task.get(x, y); }
+ public boolean isDone() { return task.isDone(); }
+ public boolean isCancelled() { return task.isCancelled(); }
+ public boolean cancel(boolean x) { return task.cancel(x); }
+ public long getDelay(TimeUnit x) { return task.getDelay(x); }
+ public int compareTo(Delayed x) { return task.compareTo(x); }
+ };
+ }
+ }
+
+ int countRefsCleared(WeakReference<?>[] refs) {
+ int count = 0;
+ for (WeakReference<?> ref : refs)
+ if (ref.get() == null)
+ count++;
+ return count;
+ }
+
+ void test(String[] args) throws Throwable {
+ CustomPool pool = new CustomPool(10);
+ final int size = 100;
+ WeakReference<?>[] refs = new WeakReference<?>[size];
+ Future<?>[] futures = new Future<?>[size];
+ for (int i = 0; i < size; i++) {
+ final Object x = new Object();
+ refs[i] = new WeakReference<Object>(x);
+ // Create a Runnable with a strong ref to x.
+ Runnable r = new Runnable() {
+ public void run() { System.out.println(x); }
+ };
+ // Schedule a custom task with a strong reference to r.
+ // Later tasks have earlier expiration, to ensure multiple
+ // residents of queue head.
+ futures[i] = pool.schedule(r, size*2-i, TimeUnit.MINUTES);
+ }
+ Thread.sleep(10);
+ for (int i = 0; i < size; i++) {
+ if (futures[i] != null) {
+ futures[i].cancel(false);
+ futures[i] = null;
+ }
+ }
+ pool.purge();
+ int cleared = 0;
+ for (int i = 0;
+ i < 10 && (cleared = countRefsCleared(refs)) < size;
+ i++) {
+ System.gc();
+ System.runFinalization();
+ Thread.sleep(10);
+ }
+ pool.shutdown();
+ pool.awaitTermination(10, TimeUnit.SECONDS);
+ if (cleared < size)
+ throw new Error(String.format
+ ("references to %d/%d tasks retained (\"leaked\")",
+ size - cleared, size));
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new GCRetention().instanceMain(args);}
+ void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,117 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8022642 8065320 8129861
+ * @summary Ensure relative sanity when zero core threads
+ */
+
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.*;
+import java.util.concurrent.locks.*;
+import java.lang.reflect.*;
+
+public class ZeroCoreThreads {
+ static boolean hasWaiters(ReentrantLock lock, Condition condition) {
+ lock.lock();
+ try {
+ return lock.hasWaiters(condition);
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ static <T> T getField(Object x, String fieldName) {
+ try {
+ Field field = x.getClass().getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return (T) field.get(x);
+ } catch (ReflectiveOperationException ex) {
+ throw new AssertionError(ex);
+ }
+ }
+
+ void test(String[] args) throws Throwable {
+ ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(0);
+ try {
+ test(p);
+ } finally {
+ p.shutdownNow();
+ check(p.awaitTermination(10L, SECONDS));
+ }
+ }
+
+ void test(ScheduledThreadPoolExecutor p) throws Throwable {
+ Runnable dummy = new Runnable() { public void run() {
+ throw new AssertionError("shouldn't get here"); }};
+ BlockingQueue q = p.getQueue();
+ ReentrantLock lock = getField(q, "lock");
+ Condition available = getField(q, "available");
+
+ equal(0, p.getPoolSize());
+ equal(0, p.getLargestPoolSize());
+ equal(0L, p.getTaskCount());
+ equal(0L, p.getCompletedTaskCount());
+ p.schedule(dummy, 1L, HOURS);
+ // Ensure one pool thread actually waits in timed queue poll
+ long t0 = System.nanoTime();
+ while (!hasWaiters(lock, available)) {
+ if (System.nanoTime() - t0 > SECONDS.toNanos(10L))
+ throw new AssertionError
+ ("timed out waiting for a waiter to show up");
+ Thread.yield();
+ }
+ equal(1, p.getPoolSize());
+ equal(1, p.getLargestPoolSize());
+ equal(1L, p.getTaskCount());
+ equal(0L, p.getCompletedTaskCount());
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new ZeroCoreThreads().instanceMain(args);}
+ void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Tue Oct 20 08:24:37 2015 -0700
@@ -55,7 +55,7 @@
return count;
}
- long millisElapsedSince(long t0) {
+ static long millisElapsedSince(long t0) {
return (System.nanoTime() - t0) / (1000L * 1000L);
}
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java Tue Oct 20 08:24:37 2015 -0700
@@ -41,7 +41,6 @@
if (x == null ? y == null : x.equals(y)) pass();
else {System.out.println(x + " not equal to " + y); fail(); }}
-
private static class CustomTask<V> extends FutureTask<V> {
public static final AtomicInteger births = new AtomicInteger(0);
CustomTask(Callable<V> c) { super(c); births.getAndIncrement(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,108 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz and Doug Lea with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Should be able to shutdown a pool when worker creation failed.
+ */
+
+import java.util.concurrent.*;
+
+public class FlakyThreadFactory {
+ void test(String[] args) throws Throwable {
+ test(NullPointerException.class,
+ new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ throw new NullPointerException();
+ }});
+ test(OutOfMemoryError.class,
+ new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ new Thread(null, r, "a natural OOME", 1L << 60);
+ // """On some platforms, the value of the stackSize
+ // parameter may have no effect whatsoever."""
+ throw new OutOfMemoryError("artificial OOME");
+ }});
+ test(null,
+ new ThreadFactory() {
+ public Thread newThread(Runnable r) {
+ return null;
+ }});
+ }
+
+ void test(final Class<?> exceptionClass,
+ final ThreadFactory failingThreadFactory)
+ throws Throwable {
+ ThreadFactory flakyThreadFactory = new ThreadFactory() {
+ int seq = 0;
+ public Thread newThread(Runnable r) {
+ if (seq++ < 4)
+ return new Thread(r);
+ else
+ return failingThreadFactory.newThread(r);
+ }};
+ ThreadPoolExecutor pool =
+ new ThreadPoolExecutor(10, 10,
+ 0L, TimeUnit.SECONDS,
+ new LinkedBlockingQueue(),
+ flakyThreadFactory);
+ try {
+ for (int i = 0; i < 8; i++)
+ pool.submit(new Runnable() { public void run() {} });
+ check(exceptionClass == null);
+ } catch (Throwable t) {
+ /* t.printStackTrace(); */
+ check(exceptionClass.isInstance(t));
+ }
+ pool.shutdown();
+ check(pool.awaitTermination(10L, TimeUnit.SECONDS));
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new FlakyThreadFactory().instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,80 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz and Jason Mehrens with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @summary Only one thread should be created when a thread needs to
+ * be kept alive to service a delayed task waiting in the queue.
+ */
+
+import java.util.concurrent.*;
+import static java.util.concurrent.TimeUnit.*;
+import java.util.concurrent.atomic.*;
+
+public class ThreadRestarts {
+ public static void main(String[] args) throws Exception {
+ test(false);
+ test(true);
+ }
+
+ private static void test(boolean allowTimeout) throws Exception {
+ CountingThreadFactory ctf = new CountingThreadFactory();
+ ScheduledThreadPoolExecutor stpe
+ = new ScheduledThreadPoolExecutor(10, ctf);
+ try {
+ Runnable nop = new Runnable() { public void run() {}};
+ stpe.schedule(nop, 10*1000L, MILLISECONDS);
+ stpe.setKeepAliveTime(1L, MILLISECONDS);
+ stpe.allowCoreThreadTimeOut(allowTimeout);
+ MILLISECONDS.sleep(100L);
+ } finally {
+ stpe.shutdownNow();
+ stpe.awaitTermination(Long.MAX_VALUE, MILLISECONDS);
+ }
+ if (ctf.count.get() > 1)
+ throw new AssertionError(
+ String.format("%d threads created, 1 expected",
+ ctf.count.get()));
+ }
+
+ static class CountingThreadFactory implements ThreadFactory {
+ final AtomicLong count = new AtomicLong(0L);
+
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ count.getAndIncrement();
+ return t;
+ }
+ }
+}
--- a/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/forkjoin/FJExceptionTableLeak.java Tue Oct 20 08:24:37 2015 -0700
@@ -36,11 +36,12 @@
* @author Doug Lea
* @bug 8004138
* @summary Check if ForkJoinPool table leaks thrown exceptions.
- * @run main/othervm -Xmx32m FJExceptionTableLeak
+ * @run main/othervm/timeout=1200 -Xmx32m FJExceptionTableLeak
*/
import java.util.concurrent.*;
public class FJExceptionTableLeak {
+ // TODO: make this test use less time!
// Run with TASKS_PER_STEP * 40 < Xmx < STEPS * TASKS_PER_STEP * 40
// These work for Xmx32m:
--- a/jdk/test/java/util/concurrent/forkjoin/Integrate.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/forkjoin/Integrate.java Tue Oct 20 08:24:37 2015 -0700
@@ -59,14 +59,15 @@
static final int DYNAMIC = 0;
static final int FORK = 1;
- // the function to integrate
- static double computeFunction(double x) {
+ /** the function to integrate */
+ static double computeFunction(double x) {
return (x * x + 1.0) * x;
}
static final double start = 0.0;
static final double end = 1536.0;
- /*
+
+ /**
* The number of recursive calls for
* integrate from start to end.
* (Empirically determined)
@@ -127,7 +128,6 @@
g.shutdown();
}
-
// Sequential version
static final class SQuad extends RecursiveAction {
static double computeArea(ForkJoinPool pool, double l, double r) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,412 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 4486658
+ * @run main/timeout=7200 CheckedLockLoops
+ * @summary basic safety and liveness of ReentrantLocks, and other locks based on them
+ */
+
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.*;
+
+public final class CheckedLockLoops {
+ static final ExecutorService pool = Executors.newCachedThreadPool();
+ static final LoopHelpers.SimpleRandom rng = new LoopHelpers.SimpleRandom();
+ static boolean print = false;
+ static boolean doBuiltin = false;
+
+ public static void main(String[] args) throws Exception {
+ int maxThreads = 5;
+ int iters = 100000;
+
+ if (args.length > 0)
+ maxThreads = Integer.parseInt(args[0]);
+
+ rng.setSeed(3122688L);
+
+ print = false;
+ System.out.println("Warmup...");
+ oneTest(3, 10000);
+ Thread.sleep(1000);
+ oneTest(2, 10000);
+ Thread.sleep(100);
+ oneTest(1, 100000);
+ Thread.sleep(100);
+ oneTest(1, 100000);
+ Thread.sleep(1000);
+ print = true;
+
+ for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) {
+ System.out.println("Threads:" + i);
+ oneTest(i, iters / i);
+ Thread.sleep(100);
+ }
+ pool.shutdown();
+ if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS))
+ throw new Error();
+ }
+
+ static void oneTest(int nthreads, int iters) throws Exception {
+ int v = rng.next();
+ if (doBuiltin) {
+ if (print)
+ System.out.print("builtin lock ");
+ new BuiltinLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+ }
+
+ if (print)
+ System.out.print("ReentrantLock ");
+ new ReentrantLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("Mutex ");
+ new MutexLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("ReentrantWriteLock ");
+ new ReentrantWriteLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("ReentrantReadWriteLock");
+ new ReentrantReadWriteLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("Semaphore ");
+ new SemaphoreLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("fair Semaphore ");
+ new FairSemaphoreLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("FairReentrantLock ");
+ new FairReentrantLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("FairRWriteLock ");
+ new FairReentrantWriteLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+
+ if (print)
+ System.out.print("FairRReadWriteLock ");
+ new FairReentrantReadWriteLockLoop().test(v, nthreads, iters);
+ Thread.sleep(10);
+ }
+
+ abstract static class LockLoop implements Runnable {
+ int value;
+ int checkValue;
+ int iters;
+ volatile int result;
+ final LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
+ CyclicBarrier barrier;
+
+ final int setValue(int v) {
+ checkValue = v ^ 0x55555555;
+ value = v;
+ return v;
+ }
+
+ final int getValue() {
+ int v = value;
+ if (checkValue != ~(v ^ 0xAAAAAAAA))
+ throw new Error("lock protection failure");
+ return v;
+ }
+
+ final void test(int initialValue, int nthreads, int iters) throws Exception {
+ setValue(initialValue);
+ this.iters = iters;
+ barrier = new CyclicBarrier(nthreads+1, timer);
+ for (int i = 0; i < nthreads; ++i)
+ pool.execute(this);
+ barrier.await();
+ barrier.await();
+ long time = timer.getTime();
+ if (print) {
+ long tpi = time / (iters * nthreads);
+ System.out.print("\t" + LoopHelpers.rightJustify(tpi) + " ns per update");
+ // double secs = (double)(time) / 1000000000.0;
+ // System.out.print("\t " + secs + "s run time");
+ System.out.println();
+ }
+
+ if (result == 0) // avoid overoptimization
+ System.out.println("useless result: " + result);
+ }
+ abstract int loop(int n);
+ public final void run() {
+ try {
+ barrier.await();
+ result += loop(iters);
+ barrier.await();
+ }
+ catch (Exception ie) {
+ return;
+ }
+ }
+
+ }
+
+ private static class BuiltinLockLoop extends LockLoop {
+ final int loop(int n) {
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ synchronized (this) {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class ReentrantLockLoop extends LockLoop {
+ private final ReentrantLock lock = new ReentrantLock();
+ final int loop(int n) {
+ final ReentrantLock lock = this.lock;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ lock.lock();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ lock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class MutexLoop extends LockLoop {
+ private final Mutex lock = new Mutex();
+ final int loop(int n) {
+ final Mutex lock = this.lock;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ lock.lock();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ lock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class FairReentrantLockLoop extends LockLoop {
+ private final ReentrantLock lock = new ReentrantLock(true);
+ final int loop(int n) {
+ final ReentrantLock lock = this.lock;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ lock.lock();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ lock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class ReentrantWriteLockLoop extends LockLoop {
+ private final Lock lock = new ReentrantReadWriteLock().writeLock();
+ final int loop(int n) {
+ final Lock lock = this.lock;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ lock.lock();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ lock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class FairReentrantWriteLockLoop extends LockLoop {
+ final Lock lock = new ReentrantReadWriteLock(true).writeLock();
+ final int loop(int n) {
+ final Lock lock = this.lock;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ lock.lock();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ lock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class SemaphoreLoop extends LockLoop {
+ private final Semaphore sem = new Semaphore(1, false);
+ final int loop(int n) {
+ final Semaphore sem = this.sem;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ sem.acquireUninterruptibly();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ sem.release();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+ private static class FairSemaphoreLoop extends LockLoop {
+ private final Semaphore sem = new Semaphore(1, true);
+ final int loop(int n) {
+ final Semaphore sem = this.sem;
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ sem.acquireUninterruptibly();
+ try {
+ x = setValue(LoopHelpers.compute1(getValue()));
+ }
+ finally {
+ sem.release();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ return sum;
+ }
+ }
+
+ private static class ReentrantReadWriteLockLoop extends LockLoop {
+ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+ final int loop(int n) {
+ final Lock rlock = lock.readLock();
+ final Lock wlock = lock.writeLock();
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ if ((n & 16) != 0) {
+ rlock.lock();
+ try {
+ x = LoopHelpers.compute1(getValue());
+ x = LoopHelpers.compute2(x);
+ }
+ finally {
+ rlock.unlock();
+ }
+ }
+ else {
+ wlock.lock();
+ try {
+ setValue(x);
+ }
+ finally {
+ wlock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ }
+ return sum;
+ }
+
+ }
+
+ private static class FairReentrantReadWriteLockLoop extends LockLoop {
+ private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+ final int loop(int n) {
+ final Lock rlock = lock.readLock();
+ final Lock wlock = lock.writeLock();
+ int sum = 0;
+ int x = 0;
+ while (n-- > 0) {
+ if ((n & 16) != 0) {
+ rlock.lock();
+ try {
+ x = LoopHelpers.compute1(getValue());
+ x = LoopHelpers.compute2(x);
+ }
+ finally {
+ rlock.unlock();
+ }
+ }
+ else {
+ wlock.lock();
+ try {
+ setValue(x);
+ }
+ finally {
+ wlock.unlock();
+ }
+ sum += LoopHelpers.compute2(x);
+ }
+ }
+ return sum;
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/LoopHelpers.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,129 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Misc utilities in JSR166 performance tests
+ */
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+class LoopHelpers {
+
+ // Some mindless computation to do between synchronizations...
+
+ /**
+ * generates 32 bit pseudo-random numbers.
+ * Adapted from http://www.snippets.org
+ */
+ public static int compute1(int x) {
+ int lo = 16807 * (x & 0xFFFF);
+ int hi = 16807 * (x >>> 16);
+ lo += (hi & 0x7FFF) << 16;
+ if ((lo & 0x80000000) != 0) {
+ lo &= 0x7fffffff;
+ ++lo;
+ }
+ lo += hi >>> 15;
+ if (lo == 0 || (lo & 0x80000000) != 0) {
+ lo &= 0x7fffffff;
+ ++lo;
+ }
+ return lo;
+ }
+
+ /**
+ * Computes a linear congruential random number a random number
+ * of times.
+ */
+ public static int compute2(int x) {
+ int loops = (x >>> 4) & 7;
+ while (loops-- > 0) {
+ x = (x * 2147483647) % 16807;
+ }
+ return x;
+ }
+
+ /**
+ * An actually useful random number generator, but unsynchronized.
+ * Basically same as java.util.Random.
+ */
+ public static class SimpleRandom {
+ private static final long multiplier = 0x5DEECE66DL;
+ private static final long addend = 0xBL;
+ private static final long mask = (1L << 48) - 1;
+ static final AtomicLong seq = new AtomicLong(1);
+ private long seed = System.nanoTime() + seq.getAndIncrement();
+
+ public void setSeed(long s) {
+ seed = s;
+ }
+
+ public int next() {
+ long nextseed = (seed * multiplier + addend) & mask;
+ seed = nextseed;
+ return ((int)(nextseed >>> 17)) & 0x7FFFFFFF;
+ }
+ }
+
+ public static class BarrierTimer implements Runnable {
+ public volatile long startTime;
+ public volatile long endTime;
+ public void run() {
+ long t = System.nanoTime();
+ if (startTime == 0)
+ startTime = t;
+ else
+ endTime = t;
+ }
+ public void clear() {
+ startTime = 0;
+ endTime = 0;
+ }
+ public long getTime() {
+ return endTime - startTime;
+ }
+ }
+
+ public static String rightJustify(long n) {
+ // There's probably a better way to do this...
+ String field = " ";
+ String num = Long.toString(n);
+ if (num.length() >= field.length())
+ return num;
+ StringBuffer b = new StringBuffer(field);
+ b.replace(b.length()-num.length(), b.length(), num);
+ return b.toString();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/Lock/Mutex.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,82 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+import java.io.*;
+
+/**
+ * A sample user extension of AbstractQueuedSynchronizer.
+ */
+public class Mutex implements Lock, java.io.Serializable {
+ private static class Sync extends AbstractQueuedSynchronizer {
+ public boolean isHeldExclusively() { return getState() == 1; }
+
+ public boolean tryAcquire(int acquires) {
+ assert acquires == 1; // Does not use multiple acquires
+ return compareAndSetState(0, 1);
+ }
+
+ public boolean tryRelease(int releases) {
+ setState(0);
+ return true;
+ }
+
+ Condition newCondition() { return new ConditionObject(); }
+
+ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
+ s.defaultReadObject();
+ setState(0); // reset to unlocked state
+ }
+ }
+
+ private final Sync sync = new Sync();
+ public void lock() {
+ sync.acquire(1);
+ }
+ public boolean tryLock() {
+ return sync.tryAcquire(1);
+ }
+ public void lockInterruptibly() throws InterruptedException {
+ sync.acquireInterruptibly(1);
+ }
+ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+ public void unlock() { sync.release(1); }
+ public Condition newCondition() { return sync.newCondition(); }
+ public boolean isLocked() { return sync.isHeldExclusively(); }
+ public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+}
--- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java Tue Oct 20 08:24:37 2015 -0700
@@ -28,14 +28,32 @@
* @author Martin Buchholz
*/
-// Note: this file is now out of sync with the jsr166 CVS repository due to the fix for 7092140
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
-import java.util.*;
-import java.util.regex.*;
-import java.util.concurrent.*;
-import java.util.concurrent.locks.*;
-import static java.util.concurrent.TimeUnit.*;
-import java.io.*;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.lang.ref.WeakReference;
+import java.util.Random;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class TimedAcquireLeak {
static String javahome() {
@@ -96,18 +114,34 @@
Callable<T> callable) throws Throwable {
p.getInputStream().read();
T result = callable.call();
- OutputStream os = p.getOutputStream();
- os.write((byte)'\n'); os.flush();
+ sendByte(p.getOutputStream());
return result;
}
+ /** No guarantees, but effective in practice. */
+ private static void forceFullGc() {
+ CountDownLatch finalizeDone = new CountDownLatch(1);
+ WeakReference<?> ref = new WeakReference<Object>(new Object() {
+ protected void finalize() { finalizeDone.countDown(); }});
+ try {
+ for (int i = 0; i < 10; i++) {
+ System.gc();
+ if (finalizeDone.await(1L, SECONDS) && ref.get() == null) {
+ System.runFinalization(); // try to pick up stragglers
+ return;
+ }
+ }
+ } catch (InterruptedException unexpected) {
+ throw new AssertionError("unexpected InterruptedException");
+ }
+ throw new AssertionError("failed to do a \"full\" gc");
+ }
+
// To be called exactly twice by the child process
public static void rendezvousChild() {
try {
- for (int i = 0; i < 100; i++) {
- System.gc(); System.runFinalization(); Thread.sleep(50);
- }
- System.out.write((byte)'\n'); System.out.flush();
+ forceFullGc();
+ sendByte(System.out);
System.in.read();
} catch (Throwable t) { throw new Error(t); }
}
@@ -118,6 +152,12 @@
return matcher.group(group);
}
+ /** It's all about sending a message! */
+ static void sendByte(OutputStream s) throws IOException {
+ s.write('!');
+ s.flush();
+ }
+
static int objectsInUse(final Process child,
final String childPid,
final String className) {
@@ -155,6 +195,9 @@
childClassName, uniqueID
};
final Process p = new ProcessBuilder(jobCmd).start();
+ // Ensure subprocess jvm has started, so that jps can find it
+ p.getInputStream().read();
+ sendByte(p.getOutputStream());
final String childPid =
match(commandOutputOf(jps, "-m"),
@@ -167,10 +210,19 @@
failed += p.exitValue();
// Check that no objects were leaked.
+ //
+ // TODO: This test is very brittle, depending on current JDK
+ // implementation, and needing occasional adjustment.
System.out.printf("%d -> %d%n", n0, n1);
- check(Math.abs(n1 - n0) < 2); // Almost always n0 == n1
- check(n1 < 20);
+ // Almost always n0 == n1
+ // Maximum jitter observed in practice is 10 -> 17
+ check(Math.abs(n1 - n0) < 10);
+ check(n1 < 25);
drainers.shutdown();
+ if (!drainers.awaitTermination(10L, SECONDS)) {
+ drainers.shutdownNow(); // last resort
+ throw new AssertionError("thread pool did not terminate");
+ }
}
//----------------------------------------------------------------
@@ -187,6 +239,10 @@
}
public static void main(String[] args) throws Throwable {
+ // Synchronize with parent process, so that jps can find us
+ sendByte(System.out);
+ System.in.read();
+
final ReentrantLock lock = new ReentrantLock();
lock.lock();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,163 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz with assistance from members of JCP
+ * JSR-166 Expert Group and released to the public domain, as
+ * explained at http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/*
+ * @test
+ * @bug 8074773
+ * @summary Stress test looks for lost unparks
+ * @run main/timeout=1200 ParkLoops
+ */
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+import java.util.concurrent.locks.LockSupport;
+
+public final class ParkLoops {
+ static final int THREADS = 4; // must be power of two
+ // static final int ITERS = 2_000_000;
+ // static final int TIMEOUT = 3500; // in seconds
+ static final int ITERS = 100_000;
+ static final int TIMEOUT = 1000; // in seconds
+
+ static class Parker implements Runnable {
+ static {
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
+ }
+
+ private final AtomicReferenceArray<Thread> threads;
+ private final CountDownLatch done;
+
+ Parker(AtomicReferenceArray<Thread> threads, CountDownLatch done) {
+ this.threads = threads;
+ this.done = done;
+ }
+
+ public void run() {
+ final SimpleRandom rng = new SimpleRandom();
+ final Thread current = Thread.currentThread();
+ for (int k = ITERS, j; k > 0; k--) {
+ do {
+ j = rng.next() & (THREADS - 1);
+ } while (!threads.compareAndSet(j, null, current));
+ do { // handle spurious wakeups
+ LockSupport.park();
+ } while (threads.get(j) == current);
+ }
+ done.countDown();
+ }
+ }
+
+ static class Unparker implements Runnable {
+ static {
+ // Reduce the risk of rare disastrous classloading in first call to
+ // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
+ Class<?> ensureLoaded = LockSupport.class;
+ }
+
+ private final AtomicReferenceArray<Thread> threads;
+ private final CountDownLatch done;
+
+ Unparker(AtomicReferenceArray<Thread> threads, CountDownLatch done) {
+ this.threads = threads;
+ this.done = done;
+ }
+
+ public void run() {
+ final SimpleRandom rng = new SimpleRandom();
+ for (int n = 0; (n++ & 0xff) != 0 || done.getCount() > 0;) {
+ int j = rng.next() & (THREADS - 1);
+ Thread parker = threads.get(j);
+ if (parker != null &&
+ threads.compareAndSet(j, parker, null)) {
+ LockSupport.unpark(parker);
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ final ExecutorService pool = Executors.newCachedThreadPool();
+ final AtomicReferenceArray<Thread> threads
+ = new AtomicReferenceArray<>(THREADS);
+ final CountDownLatch done = new CountDownLatch(THREADS);
+ final Runnable parker = new Parker(threads, done);
+ final Runnable unparker = new Unparker(threads, done);
+ for (int i = 0; i < THREADS; i++) {
+ pool.submit(parker);
+ pool.submit(unparker);
+ }
+ try {
+ if (!done.await(TIMEOUT, SECONDS)) {
+ dumpAllStacks();
+ throw new AssertionError("lost unpark");
+ }
+ } finally {
+ pool.shutdown();
+ pool.awaitTermination(10L, SECONDS);
+ }
+ }
+
+ static void dumpAllStacks() {
+ ThreadInfo[] threadInfos =
+ ManagementFactory.getThreadMXBean().dumpAllThreads(true, true);
+ for (ThreadInfo threadInfo : threadInfos) {
+ System.err.print(threadInfo);
+ }
+ }
+
+ /**
+ * An actually useful random number generator, but unsynchronized.
+ * Basically same as java.util.Random.
+ */
+ public static class SimpleRandom {
+ private static final long multiplier = 0x5DEECE66DL;
+ private static final long addend = 0xBL;
+ private static final long mask = (1L << 48) - 1;
+ static final AtomicLong seq = new AtomicLong(1);
+ private long seed = System.nanoTime() + seq.getAndIncrement();
+
+ public int next() {
+ long nextseed = (seed * multiplier + addend) & mask;
+ seed = nextseed;
+ return ((int)(nextseed >>> 17)) & 0x7FFFFFFF;
+ }
+ }
+}
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,10 +35,10 @@
* @test
* @bug 4486658
* @run main/timeout=2800 CancelledLockLoops
- * @summary tests lockInterruptibly.
- * Checks for responsiveness of locks to interrupts. Runs under that
- * assumption that ITERS_VALUE computations require more than TIMEOUT
- * msecs to complete.
+ * @summary tests ReentrantLock.lockInterruptibly.
+ * Checks for responsiveness of locks to interrupts. Runs under the
+ * assumption that ITERS computations require more than TIMEOUT msecs
+ * to complete.
*/
import java.util.concurrent.*;
@@ -48,11 +48,12 @@
public final class CancelledLockLoops {
static final Random rng = new Random();
static boolean print = false;
- static final int ITERS = 5000000;
+ static final int ITERS = 1000000;
static final long TIMEOUT = 100;
public static void main(String[] args) throws Exception {
int maxThreads = (args.length > 0) ? Integer.parseInt(args[0]) : 5;
+
print = true;
for (int i = 2; i <= maxThreads; i += (i+1) >>> 1) {
@@ -112,7 +113,7 @@
lock.unlock();
}
if (c != 2)
- throw new Error("Completed != 2");
+ throw new Error("Completed == " + c + "; expected 2");
int r = result;
if (r == 0) // avoid overoptimization
System.out.println("useless result: " + r);
--- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -57,7 +57,6 @@
if (args.length > 0)
maxThreads = Integer.parseInt(args[0]);
-
print = true;
for (int i = 1; i <= maxThreads; i += (i+1) >>> 1) {
@@ -140,6 +139,4 @@
}
}
}
-
-
}
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java Tue Oct 20 08:24:37 2015 -0700
@@ -134,7 +134,7 @@
int position;
int total;
- Runner(Map<Integer,Integer> map, Integer[] key, CyclicBarrier barrier) {
+ Runner(Map<Integer,Integer> map, Integer[] key, CyclicBarrier barrier) {
this.map = map;
this.key = key;
this.barrier = barrier;
@@ -142,7 +142,7 @@
}
int step() {
- // random-walk around key positions, bunching accesses
+ // random-walk around key positions, bunching accesses
int r = rng.next();
position += (r & 7) - 3;
while (position >= key.length) position -= key.length;
@@ -156,7 +156,7 @@
throw new Error("bad mapping: " + x + " to " + k);
if (r < removesPerMaxRandom) {
- // get awy from this position
+ // get away from this position
position = r % key.length;
map.remove(k);
return 2;
--- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/RWMap.java Tue Oct 20 08:24:37 2015 -0700
@@ -35,13 +35,11 @@
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
-
/**
* This is an incomplete implementation of a wrapper class
* that places read-write locks around unsynchronized Maps.
* Exists as a sample input for MapLoops test.
*/
-
public class RWMap implements Map {
private final Map m;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
@@ -86,7 +84,6 @@
finally { rwl.readLock().unlock(); }
}
-
public Set keySet() { // Not implemented
return null;
}
--- a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java Tue Oct 13 14:59:44 2015 +0300
+++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java Tue Oct 20 08:24:37 2015 -0700
@@ -78,7 +78,7 @@
abstract static class Locker extends Thread {
static AtomicInteger count = new AtomicInteger(1);
private volatile Throwable thrown;
- private volatile long stamp;;
+ private volatile long stamp;
protected void thrown(Throwable thrown) { this.thrown = thrown; }
public Throwable thrown() { return thrown; }
protected void stamp(long stamp) { this.stamp = stamp; }
@@ -371,7 +371,7 @@
check(!sl.tryUnlockRead());
check(!sl.tryUnlockWrite());
check(sl.tryOptimisticRead() != 0L);
- Locker[] wThreads = new Locker[100];;
+ Locker[] wThreads = new Locker[100];
for (int j=0; j<100; j++)
wThreads[j] = writers.next();
for (int j=0; j<100; j++)
@@ -401,7 +401,7 @@
check(!sl.tryUnlockRead());
check(!sl.tryUnlockWrite());
check(sl.tryOptimisticRead() != 0L);
- Locker[] rThreads = new Locker[100];;
+ Locker[] rThreads = new Locker[100];
for (int j=0; j<100; j++)
rThreads[j] = readers.next();
for (int j=0; j<100; j++)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ZipFile/ZipEntryFreeTest.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6907252
+ * @summary ZipFileInputStream Not Thread-Safe
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main ZipEntryFreeTest
+ */
+
+import java.io.*;
+import java.nio.file.Paths;
+import java.util.Random;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.zip.*;
+import jdk.testlibrary.FileUtils;
+
+public class ZipEntryFreeTest extends Thread {
+
+ private static final int NUM_THREADS = 5;
+ private static final int TEST_ITERATIONS = 5;
+ private static final String ZIPFILE_NAME = "large.zip";
+ private static final String ZIPENTRY_NAME = "random.txt";
+ private static InputStream is = null;
+ final Timer timer = new Timer();
+
+ public static void main(String args[]) throws Exception {
+ createZipFile();
+ try {
+ for (int i = 0; i < TEST_ITERATIONS; i++) {
+ runTest();
+ }
+ } finally {
+ FileUtils.deleteFileIfExistsWithRetry(Paths.get(ZIPFILE_NAME));
+ }
+ }
+
+ private static void runTest() throws Exception {
+ try (ZipFile zf = new ZipFile(new File(ZIPFILE_NAME))) {
+ is = zf.getInputStream(zf.getEntry(ZIPENTRY_NAME + "_0"));
+ Thread[] threadArray = new Thread[NUM_THREADS];
+ for (int i = 0; i < threadArray.length; i++) {
+ threadArray[i] = new ZipEntryFreeTest();
+ }
+ for (int i = 0; i < threadArray.length; i++) {
+ threadArray[i].start();
+ }
+ for (int i = 0; i < threadArray.length; i++) {
+ threadArray[i].join();
+ }
+ }
+ }
+
+ private static void createZipFile() throws Exception {
+ Random rnd = new Random(1000L);
+ byte[] contents = new byte[2_000_000];
+ ZipEntry ze = null;
+
+ try (ZipOutputStream zos =
+ new ZipOutputStream(new FileOutputStream(ZIPFILE_NAME))) {
+ // uncompressed mode seemed to tickle the crash
+ zos.setMethod(ZipOutputStream.STORED);
+ for (int ze_count = 0; ze_count < 10; ze_count++) {
+ rnd.nextBytes(contents);
+ ze = createZipEntry(contents, ze_count);
+ zos.putNextEntry(ze);
+ zos.write(contents, 0, contents.length);
+ }
+ zos.flush();
+ }
+ }
+
+ private static ZipEntry createZipEntry(byte[] b, int i) {
+ ZipEntry ze = new ZipEntry(ZIPENTRY_NAME + "_" + i);
+ ze.setCompressedSize(b.length);
+ ze.setSize(b.length);
+ CRC32 crc = new CRC32();
+ crc.update(b);
+ ze.setCrc(crc.getValue());
+ return ze;
+ }
+
+ @Override
+ public void run() {
+ try {
+ int iteration = 0;
+ TimerTask tt = (new TimerTask() {
+ @Override
+ public void run() {
+ try {
+ is.close();
+ } catch (Exception ex) {
+ ex.printStackTrace(System.out);
+ }
+ }
+ });
+ timer.schedule(tt, 50);
+ while (is.read() != -1 && iteration++ < 1_000) { }
+ } catch (ZipException ze) {
+ // ZipException now expected instead of ZIP_Read crash
+ System.out.println(ze);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ timer.cancel();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/bind/jxc/8073519/InputWithError.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType
+public class InputWithError {
+ public int a;
+ int compile-error;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/bind/jxc/8073519/SchemagenErrorReporting.java Tue Oct 20 08:24:37 2015 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8073519
+ * @summary test that schemagen tool reports errors during
+ * xsd generation process
+ * @library /lib/testlibrary
+ * @run testng/othervm SchemagenErrorReporting
+ */
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import jdk.testlibrary.JDKToolLauncher;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class SchemagenErrorReporting {
+
+ @Test
+ public void schemagenErrorReporting() throws Exception {
+ //schemagen tool output file name
+ final String SCHEMA_FILE = "schema1.xsd";
+ //Schemagen input java file with not compilable source
+ final String CLASS_FILE = "InputWithError.java";
+ //Test working, src directories and test output file
+ Path testWorkDir, testSrcDir, testOutput;
+
+ //Prepare test environment
+ //Create test directory inside scratch
+ testWorkDir = Paths.get(System.getProperty("user.dir", "."))
+ .resolve("SchemagenErrorReporting");
+ //Get test source directory
+ testSrcDir = Paths.get(System.getProperty("test.src", "."));
+ //Set test output file path
+ testOutput = testWorkDir.resolve("stdErrContent");
+ //Create test directory inside scratch directory
+ Files.createDirectory(testWorkDir);
+ //Copy java source from test.src to the test directory
+ Files.copy(testSrcDir.resolve(CLASS_FILE), testWorkDir.resolve(CLASS_FILE),
+ StandardCopyOption.REPLACE_EXISTING);
+
+ //Prepare process builder to run schemagen tool and save its output
+ JDKToolLauncher sgl = JDKToolLauncher.createUsingTestJDK("schemagen");
+ sgl.addToolArg(CLASS_FILE);
+ System.out.println("Executing: " + Arrays.asList(sgl.getCommand()));
+ ProcessBuilder pb = new ProcessBuilder(sgl.getCommand());
+ //Set schemagen work directory with the input java file
+ pb.directory(testWorkDir.toFile());
+ //Redirect schemagen output to file
+ pb.redirectError(testOutput.toFile());
+ Process p = pb.start();
+ int result = p.waitFor();
+ p.destroy();
+
+ //Read schemagen output from the file
+ String stdErrContent = Files.lines(testOutput)
+ .collect(Collectors.joining(System.lineSeparator(), System.lineSeparator(), ""));
+ System.out.println("Schemagen return value:" + result);
+ System.out.println("Error output:" + stdErrContent);
+ //Check test results:
+ //Schemagen finished with non-0 return value
+ Assert.assertNotEquals(result, 0);
+ //Schemagen output contains compile error message
+ Assert.assertTrue(stdErrContent.contains("InputWithError.java:28: error"));
+ }
+}
--- a/langtools/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/langtools/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -328,3 +328,4 @@
6b3b94a2ebca4a99b2effefb2a1556cee954fd2f jdk9-b83
e3445ccab58f741801021dec9aa46e7f2c09efd9 jdk9-b84
7ef2c66892a3af15540c2800104c660c4f7f45e9 jdk9-b85
+130a7c2a85900dde04e119bc36853b73146e3414 jdk9-b86
--- a/nashorn/.hgtags Tue Oct 13 14:59:44 2015 +0300
+++ b/nashorn/.hgtags Tue Oct 20 08:24:37 2015 -0700
@@ -319,3 +319,4 @@
21b86b980a5f0d27f1f758a3e4818d3331387172 jdk9-b83
214b97ba911f4d768c0214098739e32ab54c8503 jdk9-b84
285628dac94332d95979de365630c93ab8fa9962 jdk9-b85
+e4283eeb182cbdf5004740728a404aac6afa1104 jdk9-b86