Skip to content

Commit ef4c837

Browse files
authored
Minimizes use of locking (#15)
Signed-off-by: Laird Nelson <[email protected]>
1 parent 8e85bf8 commit ef4c837

File tree

5 files changed

+303
-69
lines changed

5 files changed

+303
-69
lines changed

src/main/java/org/microbean/construct/DefaultDomain.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,10 @@ public boolean equals(final Object other) {
293293
if (this == other) {
294294
return true;
295295
} else if (other != null && other.getClass() == this.getClass()) {
296+
final DefaultDomain her = (DefaultDomain)other;
296297
return
297-
Objects.equals(this.pe(), ((DefaultDomain)other).pe()) &&
298-
Objects.equals(this.locker, ((DefaultDomain)other).locker);
298+
Objects.equals(this.pe(), her.pe()) &&
299+
Objects.equals(this.locker, her.locker);
299300
} else {
300301
return false;
301302
}
@@ -305,7 +306,7 @@ public boolean equals(final Object other) {
305306
public UniversalType erasure(TypeMirror t) {
306307
t = unwrap(t);
307308
try (var lock = lock()) {
308-
return UniversalType.of(this.types().erasure(t), this); // (unchecked warning; OK)
309+
return UniversalType.of(this.types().erasure(t), this);
309310
}
310311
}
311312

src/main/java/org/microbean/construct/Domain.java

Lines changed: 150 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@
4040
import javax.lang.model.type.TypeVariable;
4141
import javax.lang.model.type.WildcardType;
4242

43+
import org.microbean.construct.element.StringName;
44+
import org.microbean.construct.element.UniversalElement;
45+
46+
import org.microbean.construct.type.UniversalType;
47+
4348
import static javax.lang.model.element.ElementKind.CONSTRUCTOR;
4449
import static javax.lang.model.element.ElementKind.METHOD;
4550

@@ -358,9 +363,15 @@ public DeclaredType declaredType(final DeclaredType enclosingType,
358363
* 10.1
359364
*/
360365
public default TypeMirror elementType(final TypeMirror t) {
361-
try (var lock = lock()) {
362-
return t.getKind() == TypeKind.ARRAY ? this.elementType(((ArrayType)t).getComponentType()) : t;
366+
return switch (t) {
367+
case null -> throw new NullPointerException("t");
368+
case UniversalType ut -> ut.elementType();
369+
default -> {
370+
try (var lock = lock()) {
371+
yield t.getKind() == TypeKind.ARRAY ? this.elementType(((ArrayType)t).getComponentType()) : t;
372+
}
363373
}
374+
};
364375
}
365376

366377
/**
@@ -409,17 +420,19 @@ public default ExecutableElement executableElement(final TypeElement declaringEl
409420
final TypeMirror returnType,
410421
final CharSequence name,
411422
final TypeMirror... parameterTypes) {
412-
try (var lock = this.lock()) {
413-
final List<? extends Element> ees = declaringElement.getEnclosedElements();
414-
return ees.stream()
423+
return switch (declaringElement) {
424+
case null -> throw new NullPointerException("declaringElement");
425+
case UniversalElement ue -> {
426+
final List<? extends UniversalElement> ees = ue.getEnclosedElements();
427+
yield ees.stream()
415428
.sequential()
416429
.filter(e -> e.getKind().isExecutable() && e.getSimpleName().contentEquals(name))
417-
.map(ExecutableElement.class::cast)
430+
.map(UniversalElement.class::cast)
418431
.filter(ee -> {
419432
if (!this.sameType(returnType, ee.getReturnType())) {
420433
return false;
421434
}
422-
final List<? extends VariableElement> ps = ee.getParameters();
435+
final List<? extends UniversalElement> ps = ee.getParameters();
423436
if (ps.size() != parameterTypes.length) {
424437
return false;
425438
}
@@ -433,6 +446,33 @@ public default ExecutableElement executableElement(final TypeElement declaringEl
433446
.findFirst()
434447
.orElse(null);
435448
}
449+
default -> {
450+
try (var lock = this.lock()) {
451+
final List<? extends Element> ees = declaringElement.getEnclosedElements();
452+
yield ees.stream()
453+
.sequential()
454+
.filter(e -> e.getKind().isExecutable() && e.getSimpleName().contentEquals(name))
455+
.map(ExecutableElement.class::cast)
456+
.filter(ee -> {
457+
if (!this.sameType(returnType, ee.getReturnType())) {
458+
return false;
459+
}
460+
final List<? extends VariableElement> ps = ee.getParameters();
461+
if (ps.size() != parameterTypes.length) {
462+
return false;
463+
}
464+
for (int i = 0; i < parameterTypes.length; i++) {
465+
if (!this.sameType(ps.get(i).asType(), parameterTypes[i])) {
466+
return false;
467+
}
468+
}
469+
return true;
470+
})
471+
.findFirst()
472+
.orElse(null);
473+
}
474+
}
475+
};
436476
}
437477

438478
/**
@@ -459,15 +499,19 @@ public default ExecutableElement executableElement(final TypeElement declaringEl
459499
* 9.1.2
460500
*/
461501
public default boolean generic(final Element e) {
462-
if (Objects.requireNonNull(e, "e") instanceof Parameterizable p) {
502+
return switch (e) {
503+
case null -> throw new NullPointerException("e");
504+
case UniversalElement ue -> ue.generic();
505+
case Parameterizable p -> {
463506
try (var lock = this.lock()) {
464-
return switch (e.getKind()) {
507+
yield switch (e.getKind()) {
465508
case CLASS, CONSTRUCTOR, ENUM, INTERFACE, METHOD, RECORD -> !p.getTypeParameters().isEmpty();
466509
default -> false;
467510
};
468511
}
469512
}
470-
return false;
513+
default -> false;
514+
};
471515
}
472516

473517
/**
@@ -482,11 +526,17 @@ public default boolean generic(final Element e) {
482526
* @exception NullPointerException if {@code e} is {@code null}
483527
*/
484528
public default boolean javaLangObject(final Element e) {
485-
try (var lock = this.lock()) {
486-
return
487-
e.getKind() == ElementKind.CLASS &&
488-
((QualifiedNameable)e).getQualifiedName().contentEquals("java.lang.Object");
529+
return switch (e) {
530+
case null -> throw new NullPointerException("e");
531+
case UniversalElement ue -> ue.javaLangObject();
532+
default -> {
533+
try (var lock = this.lock()) {
534+
yield
535+
e.getKind() == ElementKind.CLASS &&
536+
((QualifiedNameable)e).getQualifiedName().contentEquals("java.lang.Object");
537+
}
489538
}
539+
};
490540
}
491541

492542
/**
@@ -503,11 +553,17 @@ public default boolean javaLangObject(final Element e) {
503553
* @see #javaLangObject(Element)
504554
*/
505555
public default boolean javaLangObject(final TypeMirror t) {
506-
try (var lock = this.lock()) {
507-
return
508-
t.getKind() == TypeKind.DECLARED &&
509-
javaLangObject(((DeclaredType)t).asElement());
556+
return switch (t) {
557+
case null -> throw new NullPointerException("t");
558+
case UniversalType ut -> ut.javaLangObject();
559+
default -> {
560+
try (var lock = this.lock()) {
561+
yield
562+
t.getKind() == TypeKind.DECLARED &&
563+
javaLangObject(((DeclaredType)t).asElement());
564+
}
510565
}
566+
};
511567
}
512568

513569
/**
@@ -660,11 +716,15 @@ public default TypeElement javaLangObject() {
660716
* @exception NullPointerException if {@code t} is {@code null}
661717
*/
662718
public default boolean parameterized(final TypeMirror t) {
663-
try (var lock = this.lock()) {
664-
return
665-
t.getKind() == TypeKind.DECLARED &&
666-
!((DeclaredType)t).getTypeArguments().isEmpty();
719+
return switch (t) {
720+
case null -> throw new NullPointerException("t");
721+
case UniversalType ut -> ut.parameterized();
722+
default -> {
723+
try (var lock = this.lock()) {
724+
yield t.getKind() == TypeKind.DECLARED && !((DeclaredType)t).getTypeArguments().isEmpty();
725+
}
667726
}
727+
};
668728
}
669729

670730
/**
@@ -795,16 +855,22 @@ public default PrimitiveType primitiveType(final TypeElement e) {
795855
* @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 4.8
796856
*/
797857
public default boolean raw(final TypeMirror t) {
798-
try (var lock = this.lock()) {
799-
return switch (t.getKind()) {
800-
case ARRAY -> raw(elementType((ArrayType)t));
801-
case DECLARED -> {
802-
final DeclaredType dt = (DeclaredType)t;
803-
yield generic(dt.asElement()) && dt.getTypeArguments().isEmpty();
858+
return switch (t) {
859+
case null -> throw new NullPointerException("t");
860+
case UniversalType ut -> ut.raw();
861+
default -> {
862+
try (var lock = this.lock()) {
863+
yield switch (t.getKind()) {
864+
case ARRAY -> raw(elementType((ArrayType)t));
865+
case DECLARED -> {
866+
final DeclaredType dt = (DeclaredType)t;
867+
yield generic(dt.asElement()) && dt.getTypeArguments().isEmpty();
868+
}
869+
default -> false;
870+
};
804871
}
805-
default -> false;
806-
};
807872
}
873+
};
808874
}
809875

810876
/**
@@ -822,15 +888,22 @@ public default boolean raw(final TypeMirror t) {
822888
*
823889
* @exception NullPointerException if {@code t} is {@code null}
824890
*
825-
* @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section 4.8
891+
* @spec https://docs.oracle.com/javase/specs/jls/se23/html/jls-4.html#jls-4.8 Java Language Specification, section
892+
* 4.8
826893
*/
827894
public default TypeMirror rawType(final TypeMirror t) {
828-
try (var lock = this.lock()) {
829-
return switch (t.getKind()) {
830-
case ARRAY -> this.rawType(this.elementType(t)); // recursive
831-
default -> this.parameterized(t) ? this.erasure(t) : null;
832-
};
895+
return switch (t) {
896+
case null -> throw new NullPointerException("t");
897+
case UniversalType ut -> ut.rawType();
898+
default -> {
899+
try (var lock = this.lock()) {
900+
yield switch (t.getKind()) {
901+
case ARRAY -> this.rawType(this.elementType(t)); // recursive
902+
default -> this.parameterized(t) ? this.erasure(t) : null;
903+
};
904+
}
833905
}
906+
};
834907
}
835908

836909
/**
@@ -938,6 +1011,7 @@ public default String toString(final CharSequence name) {
9381011
return switch (name) {
9391012
case null -> null;
9401013
case String s -> s;
1014+
case StringName sn -> sn.value();
9411015
case Name n -> {
9421016
try (var lock = this.lock()) {
9431017
yield n.toString();
@@ -1019,9 +1093,15 @@ public default String toString(final CharSequence name) {
10191093
// (Canonical.)
10201094
// (Boxing.)
10211095
public default TypeElement typeElement(final PrimitiveType t) {
1022-
try (var lock = this.lock()) {
1023-
return this.typeElement(t.getKind());
1096+
return switch (t) {
1097+
case null -> throw new NullPointerException("t");
1098+
case UniversalType ut -> this.typeElement(ut.getKind());
1099+
default -> {
1100+
try (var lock = this.lock()) {
1101+
yield this.typeElement(t.getKind());
1102+
}
10241103
}
1104+
};
10251105
}
10261106

10271107
/**
@@ -1076,20 +1156,26 @@ public default TypeParameterElement typeParameterElement(Parameterizable p, fina
10761156
Objects.requireNonNull(p, "p");
10771157
Objects.requireNonNull(name, "name");
10781158
while (p != null) {
1079-
// A call to getTypeParameters() does not cause symbol completion, but name acquisition also needs to be
1080-
// serialized globally.
1081-
try (var lock = this.lock()) {
1082-
for (final TypeParameterElement tpe : p.getTypeParameters()) {
1159+
switch (p) {
1160+
case UniversalElement ue:
1161+
for (final UniversalElement tpe : ue.getTypeParameters()) {
10831162
if (tpe.getSimpleName().contentEquals(name)) {
10841163
return tpe;
10851164
}
10861165
}
1166+
p = ue.getEnclosingElement();
1167+
break;
1168+
default:
1169+
try (var lock = this.lock()) {
1170+
for (final TypeParameterElement tpe : p.getTypeParameters()) {
1171+
if (tpe.getSimpleName().contentEquals(name)) {
1172+
return tpe;
1173+
}
1174+
}
1175+
p = (Parameterizable)((Element)p).getEnclosingElement();
1176+
}
1177+
break;
10871178
}
1088-
p = switch (p) {
1089-
case ExecutableElement ee -> (Parameterizable)ee.getEnclosingElement();
1090-
case TypeElement te -> (Parameterizable)te.getEnclosingElement();
1091-
default -> null;
1092-
};
10931179
}
10941180
return null;
10951181
}
@@ -1138,14 +1224,27 @@ public default TypeVariable typeVariable(Parameterizable p, final CharSequence n
11381224
*/
11391225
public default VariableElement variableElement(final Element enclosingElement, final CharSequence simpleName) {
11401226
Objects.requireNonNull(simpleName, "simpleName");
1141-
try (var lock = lock()) {
1142-
for (final Element ee : enclosingElement.getEnclosedElements()) {
1227+
return switch (enclosingElement) {
1228+
case null -> throw new NullPointerException("enclosingElement");
1229+
case UniversalElement ue -> {
1230+
for (final UniversalElement ee : ue.getEnclosedElements()) {
11431231
if (ee.getKind().isVariable() && ee.getSimpleName().contentEquals(simpleName)) {
1144-
return (VariableElement)ee;
1232+
yield ee;
11451233
}
11461234
}
1235+
yield null;
11471236
}
1148-
return null;
1237+
default -> {
1238+
try (var lock = lock()) {
1239+
for (final Element ee : enclosingElement.getEnclosedElements()) {
1240+
if (ee.getKind().isVariable() && ee.getSimpleName().contentEquals(simpleName)) {
1241+
yield (VariableElement)ee;
1242+
}
1243+
}
1244+
}
1245+
yield null;
1246+
}
1247+
};
11491248
}
11501249

11511250
/**

src/main/java/org/microbean/construct/element/StringName.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ public final record StringName(String value, Domain domain) implements Constable
5757
public StringName(final CharSequence value, final Domain domain) {
5858
// We deliberately route even String-typed values through Domain#toString(CharSequence) in case the Domain wishes to
5959
// cache the intermediate Name.
60-
this(domain.toString(value), domain);
60+
this(switch (value) {
61+
case StringName sn -> sn.value();
62+
default -> domain.toString(value);
63+
}, domain);
6164
}
6265

6366
/**

0 commit comments

Comments
 (0)