@@ -1098,19 +1098,27 @@ public final Collection<RubyClass> subclasses() {
1098
1098
return subclasses (false );
1099
1099
}
1100
1100
1101
- public synchronized Collection <RubyClass > subclasses (boolean includeDescendants ) {
1101
+ public Collection <RubyClass > subclasses (boolean includeDescendants ) {
1102
1102
Set <RubyClass > subclasses = this .subclasses ;
1103
1103
if (subclasses != null ) {
1104
- Collection <RubyClass > mine = new ArrayList <>(subclasses );
1104
+ Collection <RubyClass > mine = new ArrayList <>();
1105
+ subclassesInner (mine , includeDescendants );
1106
+
1107
+ return mine ;
1108
+ }
1109
+ return Collections .EMPTY_LIST ;
1110
+ }
1111
+
1112
+ private void subclassesInner (Collection <RubyClass > mine , boolean includeDescendants ) {
1113
+ Set <RubyClass > subclasses = this .subclasses ;
1114
+ if (subclasses != null ) {
1115
+ mine .addAll (subclasses );
1105
1116
if (includeDescendants ) {
1106
1117
for (RubyClass klass : subclasses ) {
1107
- mine . addAll ( klass .subclasses ( includeDescendants ) );
1118
+ klass .subclassesInner ( mine , includeDescendants );
1108
1119
}
1109
1120
}
1110
-
1111
- return mine ;
1112
1121
}
1113
- return Collections .EMPTY_LIST ;
1114
1122
}
1115
1123
1116
1124
/**
@@ -1122,26 +1130,31 @@ public synchronized Collection<RubyClass> subclasses(boolean includeDescendants)
1122
1130
*
1123
1131
* @param subclass The subclass to add
1124
1132
*/
1125
- public synchronized void addSubclass (RubyClass subclass ) {
1126
- synchronized (runtime .getHierarchyLock ()) {
1127
- Set <RubyClass > subclasses = this .subclasses ;
1128
- if (subclasses == null ) this .subclasses = subclasses = new WeakHashSet <>(4 );
1129
- subclasses .add (subclass );
1133
+ public void addSubclass (RubyClass subclass ) {
1134
+ Set <RubyClass > subclasses = this .subclasses ;
1135
+ if (subclasses == null ) {
1136
+ // check again
1137
+ synchronized (this ) {
1138
+ subclasses = this .subclasses ;
1139
+ if (subclasses == null ) {
1140
+ this .subclasses = subclasses = Collections .synchronizedSet (new WeakHashSet <RubyClass >(4 ));
1141
+ }
1142
+ }
1130
1143
}
1144
+
1145
+ subclasses .add (subclass );
1131
1146
}
1132
1147
1133
1148
/**
1134
1149
* Remove a subclass from the weak set of subclasses.
1135
1150
*
1136
1151
* @param subclass The subclass to remove
1137
1152
*/
1138
- public synchronized void removeSubclass (RubyClass subclass ) {
1139
- synchronized (runtime .getHierarchyLock ()) {
1140
- Set <RubyClass > subclasses = this .subclasses ;
1141
- if (subclasses == null ) return ;
1153
+ public void removeSubclass (RubyClass subclass ) {
1154
+ Set <RubyClass > subclasses = this .subclasses ;
1155
+ if (subclasses == null ) return ;
1142
1156
1143
- subclasses .remove (subclass );
1144
- }
1157
+ subclasses .remove (subclass );
1145
1158
}
1146
1159
1147
1160
/**
@@ -1150,25 +1163,21 @@ public synchronized void removeSubclass(RubyClass subclass) {
1150
1163
* @param subclass The subclass to remove
1151
1164
* @param newSubclass The subclass to replace it with
1152
1165
*/
1153
- public synchronized void replaceSubclass (RubyClass subclass , RubyClass newSubclass ) {
1154
- synchronized (runtime .getHierarchyLock ()) {
1155
- Set <RubyClass > subclasses = this .subclasses ;
1156
- if (subclasses == null ) return ;
1166
+ public void replaceSubclass (RubyClass subclass , RubyClass newSubclass ) {
1167
+ Set <RubyClass > subclasses = this .subclasses ;
1168
+ if (subclasses == null ) return ;
1157
1169
1158
- subclasses .remove (subclass );
1159
- subclasses .add (newSubclass );
1160
- }
1170
+ subclasses .remove (subclass );
1171
+ subclasses .add (newSubclass );
1161
1172
}
1162
1173
1163
1174
@ Override
1164
1175
public void becomeSynchronized () {
1165
1176
// make this class and all subclasses sync
1166
- synchronized (runtime .getHierarchyLock ()) {
1167
- super .becomeSynchronized ();
1168
- Set <RubyClass > subclasses = this .subclasses ;
1169
- if (subclasses != null ) {
1170
- for (RubyClass subclass : subclasses ) subclass .becomeSynchronized ();
1171
- }
1177
+ super .becomeSynchronized ();
1178
+ Set <RubyClass > subclasses = this .subclasses ;
1179
+ if (subclasses != null ) {
1180
+ for (RubyClass subclass : subclasses ) subclass .becomeSynchronized ();
1172
1181
}
1173
1182
}
1174
1183
@@ -1188,11 +1197,9 @@ public void becomeSynchronized() {
1188
1197
public void invalidateCacheDescendants () {
1189
1198
super .invalidateCacheDescendants ();
1190
1199
1191
- synchronized (runtime .getHierarchyLock ()) {
1192
- Set <RubyClass > subclasses = this .subclasses ;
1193
- if (subclasses != null ) {
1194
- for (RubyClass subclass : subclasses ) subclass .invalidateCacheDescendants ();
1195
- }
1200
+ Set <RubyClass > subclasses = this .subclasses ;
1201
+ if (subclasses != null ) {
1202
+ for (RubyClass subclass : subclasses ) subclass .invalidateCacheDescendants ();
1196
1203
}
1197
1204
}
1198
1205
@@ -1208,12 +1215,7 @@ public void addInvalidatorsAndFlush(List<Invalidator> invalidators) {
1208
1215
if (subclasses == null || subclasses .isEmpty ()) return ;
1209
1216
1210
1217
// cascade into subclasses
1211
- synchronized (runtime .getHierarchyLock ()) {
1212
- subclasses = this .subclasses ;
1213
- if (subclasses != null ) {
1214
- for (RubyClass subclass : subclasses ) subclass .addInvalidatorsAndFlush (invalidators );
1215
- }
1216
- }
1218
+ for (RubyClass subclass : subclasses ) subclass .addInvalidatorsAndFlush (invalidators );
1217
1219
}
1218
1220
1219
1221
public final Ruby getClassRuntime () {
@@ -2326,7 +2328,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject self, String name,
2326
2328
protected final Ruby runtime ;
2327
2329
private ObjectAllocator allocator ; // the default allocator
2328
2330
protected ObjectMarshal marshal ;
2329
- private Set <RubyClass > subclasses ;
2331
+ private volatile Set <RubyClass > subclasses ;
2330
2332
public static final int CS_IDX_INITIALIZE = 0 ;
2331
2333
public enum CS_NAMES {
2332
2334
INITIALIZE ("initialize" );
0 commit comments