Skip to content

Commit 5be1af3

Browse files
timfelotethal
authored andcommitted
handle multiple weakref callbacks that are available at once
1 parent 2ceea7f commit 5be1af3

File tree

2 files changed

+50
-25
lines changed

2 files changed

+50
-25
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/WeakRefModuleBuiltins.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
import java.lang.ref.Reference;
4444
import java.lang.ref.ReferenceQueue;
45+
import java.util.ArrayList;
4546
import java.util.List;
4647

4748
import com.oracle.graal.python.builtins.Builtin;
@@ -90,20 +91,28 @@ protected List<? extends NodeFactory<? extends PythonBuiltinBaseNode>> getNodeFa
9091
}
9192

9293
private static class WeakrefCallbackAction extends AsyncHandler.AsyncPythonAction {
93-
private final WeakRefStorage reference;
94+
private final WeakRefStorage[] references;
95+
private int index;
9496

95-
public WeakrefCallbackAction(PReferenceType.WeakRefStorage reference) {
96-
this.reference = reference;
97+
public WeakrefCallbackAction(WeakRefStorage[] weakRefStorages) {
98+
this.references = weakRefStorages;
99+
this.index = 0;
97100
}
98101

99102
@Override
100103
public Object callable() {
101-
return reference.getCallback();
104+
return references[index].getCallback();
102105
}
103106

104107
@Override
105108
public Object[] arguments() {
106-
return new Object[]{reference.getRef()};
109+
return new Object[]{references[index].getRef()};
110+
}
111+
112+
@Override
113+
public boolean proceed() {
114+
index++;
115+
return index < references.length;
107116
}
108117
}
109118

@@ -124,11 +133,17 @@ public void postInitialize(PythonCore core) {
124133
} catch (InterruptedException e) {
125134
Thread.currentThread().interrupt();
126135
}
127-
if (reference instanceof PReferenceType.WeakRefStorage) {
128-
return new WeakrefCallbackAction((PReferenceType.WeakRefStorage) reference);
129-
} else {
130-
return null;
136+
ArrayList<PReferenceType.WeakRefStorage> refs = new ArrayList<>();
137+
do {
138+
if (reference instanceof PReferenceType.WeakRefStorage) {
139+
refs.add((PReferenceType.WeakRefStorage) reference);
140+
}
141+
reference = weakRefQueue.poll();
142+
} while (reference != null);
143+
if (!refs.isEmpty()) {
144+
return new WeakrefCallbackAction(refs.toArray(new PReferenceType.WeakRefStorage[0]));
131145
}
146+
return null;
132147
});
133148
}
134149

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/AsyncHandler.java

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,27 +109,37 @@ protected int frameIndex() {
109109
return -1;
110110
}
111111

112+
/**
113+
* As long as a subclass wants to run multiple callables in a single action, it can return
114+
* {@code true} here.
115+
*/
116+
protected boolean proceed() {
117+
return false;
118+
}
119+
112120
@Override
113121
public final void execute(PythonContext context) {
114122
Object callable = callable();
115-
if (callable != null) {
116-
Object[] arguments = arguments();
117-
Object[] args = PArguments.create(arguments.length + CallRootNode.ASYNC_ARG_COUNT);
118-
PythonUtils.arraycopy(arguments, 0, args, PArguments.USER_ARGUMENTS_OFFSET + CallRootNode.ASYNC_ARG_COUNT, arguments.length);
119-
PArguments.setArgument(args, CallRootNode.ASYNC_CALLABLE_INDEX, callable);
120-
PArguments.setArgument(args, CallRootNode.ASYNC_FRAME_INDEX_INDEX, frameIndex());
123+
do {
124+
if (callable != null) {
125+
Object[] arguments = arguments();
126+
Object[] args = PArguments.create(arguments.length + CallRootNode.ASYNC_ARG_COUNT);
127+
PythonUtils.arraycopy(arguments, 0, args, PArguments.USER_ARGUMENTS_OFFSET + CallRootNode.ASYNC_ARG_COUNT, arguments.length);
128+
PArguments.setArgument(args, CallRootNode.ASYNC_CALLABLE_INDEX, callable);
129+
PArguments.setArgument(args, CallRootNode.ASYNC_FRAME_INDEX_INDEX, frameIndex());
121130

122-
try {
123-
GenericInvokeNode.getUncached().execute(context.getAsyncHandler().callTarget, args);
124-
} catch (RuntimeException e) {
125-
// we cannot raise the exception here (well, we could, but CPython
126-
// doesn't), so we do what they do and just print it
127-
128-
// Just print a Python-like stack trace; CPython does the same (see
129-
// 'weakrefobject.c: handle_callback')
130-
ExceptionUtils.printPythonLikeStackTrace(e);
131+
try {
132+
GenericInvokeNode.getUncached().execute(context.getAsyncHandler().callTarget, args);
133+
} catch (RuntimeException e) {
134+
// we cannot raise the exception here (well, we could, but CPython
135+
// doesn't), so we do what they do and just print it
136+
137+
// Just print a Python-like stack trace; CPython does the same (see
138+
// 'weakrefobject.c: handle_callback')
139+
ExceptionUtils.printPythonLikeStackTrace(e);
140+
}
131141
}
132-
}
142+
} while (proceed());
133143
}
134144
}
135145

0 commit comments

Comments
 (0)