Skip to content

Commit a29d052

Browse files
committed
Add stateless setter API
1 parent 6c1eed1 commit a29d052

File tree

5 files changed

+98
-29
lines changed

5 files changed

+98
-29
lines changed

src/jdk.jfr/share/classes/jdk/jfr/ContextType.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@
1515
import jdk.jfr.internal.context.ContextRepository;
1616

1717
public abstract class ContextType extends BaseContextType {
18-
public static interface Registration {
18+
public interface Registration {
1919
Stream<Class<? extends ContextType>> types();
2020
}
2121

22+
public interface Setter {
23+
void setAttribute(String name, String value);
24+
void clearAttribute(String name);
25+
void clearAll();
26+
}
27+
2228
public static final class Captured<T extends ContextType.Capturable<T>> implements Closeable, AutoCloseable {
2329
private final T parent, current;
2430

@@ -55,4 +61,8 @@ public final Captured<T> capture() {
5561
}
5662

5763
protected ContextType() {}
64+
65+
public static Setter setterFor(Class<? extends ContextType> type) {
66+
return BaseContextType.setterFor(type);
67+
}
5868
}

src/jdk.jfr/share/classes/jdk/jfr/internal/context/BaseContextType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package jdk.jfr.internal.context;
22

3+
import jdk.jfr.ContextType;
34
import jdk.jfr.FlightRecorder;
45
import jdk.jfr.internal.JVM;
56
import jdk.jfr.internal.PlatformRecorder;
@@ -24,4 +25,8 @@ public final boolean isActive() {
2425
private static boolean shouldCaptureState() {
2526
return FlightRecorder.isInitialized() && PlatformRecorder.hasRecordings() && JVM.isContextEnabled();
2627
}
28+
29+
public static ContextType.Setter setterFor(Class<? extends ContextType> type) {
30+
return ContextRepository.getOrRegister(type);
31+
}
2732
}

src/jdk.jfr/share/classes/jdk/jfr/internal/context/ContextDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22

33
import java.lang.invoke.VarHandle;
44

5-
public record ContextDescriptor(String holderId, String name, String label, String description, VarHandle access) {
5+
public record ContextDescriptor(int order, String holderId, String name, String label, String description, VarHandle access) {
66
}

src/jdk.jfr/share/classes/jdk/jfr/internal/context/ContextRepository.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import java.lang.reflect.Field;
77
import java.util.ArrayList;
88
import java.util.Arrays;
9+
import java.util.HashSet;
910
import java.util.List;
11+
import java.util.Set;
1012
import java.util.concurrent.atomic.AtomicInteger;
1113

1214
import jdk.jfr.ContextType;
@@ -48,12 +50,13 @@ public static <T extends BaseContextType> ContextWriter getOrRegister(Class<T> c
4850
return contextWriters.get(contextTypeClass);
4951
}
5052

51-
private static <T extends BaseContextType> List<ContextDescriptor> descriptorsOf(Class<T> contextTypeClass) {
53+
private static <T extends BaseContextType> Set<ContextDescriptor> descriptorsOf(Class<T> contextTypeClass) {
5254
try {
53-
List<ContextDescriptor> ctxDescriptors = new ArrayList<>(8);
55+
Set<ContextDescriptor> ctxDescriptors = new HashSet<>(8);
5456
Name typeNameAnnot = contextTypeClass.getAnnotation(Name.class);
5557
String id = typeNameAnnot.value();
5658
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
59+
int order = 0;
5760
for (Field f : contextTypeClass.getFields()) {
5861
Name nameAnnot = f.getAnnotation(Name.class);
5962
Label labelAnnot = f.getAnnotation(Label.class);
@@ -62,7 +65,7 @@ private static <T extends BaseContextType> List<ContextDescriptor> descriptorsOf
6265
String name = nameAnnot != null ? nameAnnot.value() : f.getName();
6366
String label = labelAnnot != null ? labelAnnot.value() : name;
6467
String desc = descAnnot != null ? descAnnot.value() : "";
65-
ctxDescriptors.add(new ContextDescriptor(id, name, label, desc, lookup.unreflectVarHandle(f)));
68+
ctxDescriptors.add(new ContextDescriptor(order++, id, name, label, desc, lookup.unreflectVarHandle(f)));
6669
}
6770
}
6871
return ctxDescriptors;
@@ -72,7 +75,7 @@ private static <T extends BaseContextType> List<ContextDescriptor> descriptorsOf
7275
}
7376

7477
private static <T extends BaseContextType> ContextWriter writerFor(Class<T> type) {
75-
List<ContextDescriptor> ctxDescriptors = descriptorsOf(type);
78+
Set<ContextDescriptor> ctxDescriptors = descriptorsOf(type);
7679
int offset = register(ctxDescriptors);
7780
if (offset == -2) {
7881
Logger.log(JFR, INFO,
@@ -85,7 +88,7 @@ private static <T extends BaseContextType> ContextWriter writerFor(Class<T> type
8588
return offset > -1 ? new ContextWriter(offset, ctxDescriptors) : ContextWriter.NULL;
8689
}
8790

88-
private static int register(List<ContextDescriptor> descriptors) {
91+
private static int register(Set<ContextDescriptor> descriptors) {
8992
if (!shouldCaptureState()) {
9093
return -1;
9194
}
@@ -96,12 +99,12 @@ private static int register(List<ContextDescriptor> descriptors) {
9699
return -3;
97100
}
98101
final int offset = slotPointer;
99-
int idx = 0;
102+
int top = 0;
100103
for (var descriptor : descriptors) {
101-
allDescriptors[idx + slotPointer] = descriptor;
102-
idx++;
104+
allDescriptors[descriptor.order() + slotPointer] = descriptor;
105+
top = Math.max(top, descriptor.order());
103106
}
104-
slotPointer += idx;
107+
slotPointer += top + 1;
105108
JVM.setUsedContextSize(slotPointer);
106109
return offset;
107110
}
Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
package jdk.jfr.internal.context;
22

3-
import java.lang.invoke.MethodHandles.Lookup;
43
import java.nio.LongBuffer;
5-
import java.lang.invoke.MethodType;
6-
import java.lang.invoke.VarHandle;
7-
import java.util.ArrayList;
84
import java.util.Collections;
9-
import java.util.List;
5+
import java.util.Map;
6+
import java.util.Set;
7+
import java.util.stream.Collectors;
108

119
import jdk.jfr.ContextType;
12-
import jdk.jfr.FlightRecorder;
1310
import jdk.jfr.internal.JVM;
1411
import jdk.jfr.internal.StringPool;
1512

16-
public final class ContextWriter {
13+
public final class ContextWriter implements ContextType.Setter {
1714
static final ContextWriter NULL = new ContextWriter(-1, null);
1815
private final int offset;
19-
private final List<ContextDescriptor> descriptors;
16+
private final Set<ContextDescriptor> descriptors;
17+
private final Map<String, ContextDescriptor> attributeIndexMap;
2018

21-
ContextWriter(int offset, List<ContextDescriptor> descriptors) {
19+
ContextWriter(int offset, Set<ContextDescriptor> descriptors) {
2220
this.offset = offset;
23-
this.descriptors = offset > -1 ? Collections.unmodifiableList(descriptors) : null;
21+
this.descriptors = offset > -1 ? Collections.unmodifiableSet(descriptors) : null;
22+
this.attributeIndexMap = this.descriptors != null ? this.descriptors.stream().collect(Collectors.toUnmodifiableMap(ContextDescriptor::name, cd -> cd)) : null;
2423
}
2524

2625
public boolean isActive() {
@@ -35,12 +34,10 @@ void write(BaseContextType target) {
3534
if (context == null) {
3635
return;
3736
}
38-
int cntr = offset;
3937
for (ContextDescriptor cd : descriptors) {
40-
String value = (String) cd.access().get(target);
41-
context.put(cntr++, value != null ? StringPool.addString(value, false) : 0);
42-
if (cntr >= 8) {
43-
break;
38+
if (cd.order() < 8) {
39+
String value = (String) cd.access().get(target);
40+
context.put(offset + cd.order(), value != null ? StringPool.addString(value, false) : 0);
4441
}
4542
}
4643
}
@@ -53,10 +50,64 @@ void clear(BaseContextType target) {
5350
if (context == null) {
5451
return;
5552
}
56-
int cntr = 0;
5753
for (ContextDescriptor cd : descriptors) {
58-
context.put(offset + (cntr++), 0L);
59-
cd.access().set(target, null);
54+
if (cd.order() < 8) {
55+
context.put(offset + cd.order(), 0L);
56+
cd.access().set(target, null);
57+
}
58+
}
59+
}
60+
61+
@Override
62+
public void clearAll() {
63+
if (offset == -1 || descriptors == null) {
64+
return;
65+
}
66+
LongBuffer context = JVM.getThreadContextBuffer();
67+
if (context == null) {
68+
return;
69+
}
70+
for (ContextDescriptor cd : descriptors) {
71+
context.put(offset + cd.order(), 0L);
72+
}
73+
}
74+
75+
@Override
76+
public void setAttribute(String name, String value) {
77+
LongBuffer context = JVM.getThreadContextBuffer();
78+
if (context == null) {
79+
return;
80+
}
81+
int pos = getContextIndex(name, String.class);
82+
if (pos < 0) {
83+
System.err.println("===> set err: " + name + ": " + pos);
84+
return;
85+
}
86+
context.put(pos, StringPool.addString(value, false));
87+
}
88+
89+
@Override
90+
public void clearAttribute(String name) {
91+
LongBuffer context = JVM.getThreadContextBuffer();
92+
if (context == null) {
93+
return;
94+
}
95+
int pos = getContextIndex(name, String.class);
96+
if (pos < 0) {
97+
System.err.println("===> clear err: " + name + ": " + pos);
98+
return;
99+
}
100+
context.put(pos, 0);
101+
}
102+
103+
private int getContextIndex(String name, Class<?> type) {
104+
ContextDescriptor cd = attributeIndexMap.get(name);
105+
if (cd == null) {
106+
return -1;
107+
}
108+
if (cd.access().varType() != type) {
109+
return -2;
60110
}
111+
return offset + cd.order();
61112
}
62113
}

0 commit comments

Comments
 (0)