Skip to content

Commit 83db092

Browse files
WIP: Change how we save data, mimicing what Greenlet does
This doesn't actually work, it still sees a series of errors (timing dependant...) when debugging and running.
1 parent da8b793 commit 83db092

1 file changed

Lines changed: 79 additions & 7 deletions

File tree

context/_coroutine.c

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,28 @@ static void *coroutine_wrapper(void *action_, void *arg_)
8181

8282
/* New coroutine gets a brand new Python interpreter stack frame. */
8383
#if PY_VERSION_HEX >= 0x30B0000
84-
PyThreadState *new_threadstate = PyThreadState_New(thread_state->interp);
85-
thread_state = PyThreadState_Swap(new_threadstate);
84+
// TODO: This section should just set up a clean stack frame
85+
86+
// PyObject *context = thread_state->context;
87+
// _PyCFrame *cframe = thread_state->cframe;
88+
// struct _PyInterpreterFrame *current_frame = thread_state->cframe->current_frame;
89+
90+
// thread_state->cframe = thread_state->cframe;
91+
92+
// int recursion_depth = thread_state->recursion_limit - thread_state->recursion_remaining;
93+
94+
// // May not be needed?
95+
96+
// _PyStackChunk *datastack_chunk = thread_state->datastack_chunk;
97+
// PyObject **datastack_top = thread_state->datastack_top;
98+
// PyObject **datastack_limit = thread_state->datastack_limit;
99+
100+
// PyFrameObject *frame = PyThreadState_GetFrame(thread_state);
101+
// Py_XDECREF(frame); // PyThreadState_GetFrame gives us a new reference.
102+
103+
// int trash_delete_nesting = thread_state->trash_delete_nesting;
104+
105+
thread_state->recursion_remaining = thread_state->recursion_limit;
86106
#else
87107
thread_state->frame = NULL;
88108
thread_state->recursion_depth = 0;
@@ -108,9 +128,20 @@ static void *coroutine_wrapper(void *action_, void *arg_)
108128

109129

110130
#if PY_VERSION_HEX >= 0x30B0000
111-
new_threadstate = PyThreadState_Swap(thread_state);
112-
PyThreadState_Clear(new_threadstate);
113-
PyThreadState_Delete(new_threadstate);
131+
// thread_state->context = context;
132+
// /* Incrementing this value invalidates the contextvars cache,
133+
// which would otherwise remain valid across switches */
134+
// thread_state->context_ver++;
135+
136+
// thread_state->cframe = cframe;
137+
138+
// thread_state->recursion_remaining = thread_state->recursion_limit - recursion_depth;
139+
140+
// thread_state->cframe->current_frame = interp_frame;
141+
142+
// thread_state->datastack_chunk = datastack_chunk;
143+
// thread_state->datastack_top = datastack_top;
144+
// thread_state->datastack_limit = datastack_limit;
114145
#else
115146
/* Some of the stuff we've initialised can leak through, so far I've only
116147
* seen exc_type still set at this point, but maybe other fields can also
@@ -162,7 +193,30 @@ static PyObject *coroutine_switch(PyObject *Self, PyObject *args)
162193
{
163194
PyThreadState *thread_state = PyThreadState_GET();
164195

165-
#if PY_VERSION_HEX < 0x30B0000
196+
#if PY_VERSION_HEX >= 0x30B0000
197+
PyObject *context = thread_state->context;
198+
_PyCFrame *cframe = thread_state->cframe;
199+
struct _PyInterpreterFrame *current_frame = thread_state->cframe->current_frame;
200+
201+
// thread_state->cframe = NULL;
202+
203+
int recursion_depth = thread_state->recursion_limit - thread_state->recursion_remaining;
204+
205+
// May not be needed?
206+
207+
_PyStackChunk *datastack_chunk = thread_state->datastack_chunk;
208+
PyObject **datastack_top = thread_state->datastack_top;
209+
PyObject **datastack_limit = thread_state->datastack_limit;
210+
211+
PyFrameObject *frame = PyThreadState_GetFrame(thread_state);
212+
// assert(frame);
213+
Py_XDECREF(frame); // PyThreadState_GetFrame gives us a new reference.
214+
215+
int trash_delete_nesting = thread_state->trash_delete_nesting;
216+
217+
_PyErr_StackItem exc_state = thread_state->exc_state;
218+
_PyErr_StackItem *exc_info = thread_state->exc_info;
219+
#else
166220
/* Need to switch the Python interpreter's record of recursion depth and
167221
* top frame around as we switch frames, otherwise the interpreter gets
168222
* confused and thinks we've recursed too deep. In truth tracking this
@@ -191,7 +245,25 @@ static PyObject *coroutine_switch(PyObject *Self, PyObject *args)
191245
PyObject *result = switch_cocore(target, arg);
192246

193247
#if PY_VERSION_HEX >= 0x30B0000
194-
PyThreadState_Swap(thread_state);
248+
thread_state->context = context;
249+
/* Incrementing this value invalidates the contextvars cache,
250+
which would otherwise remain valid across switches */
251+
thread_state->context_ver++;
252+
253+
thread_state->cframe = cframe;
254+
255+
thread_state->recursion_remaining = thread_state->recursion_limit - recursion_depth;
256+
257+
thread_state->cframe->current_frame = current_frame;
258+
259+
thread_state->datastack_chunk = datastack_chunk;
260+
thread_state->datastack_top = datastack_top;
261+
thread_state->datastack_limit = datastack_limit;
262+
263+
thread_state->trash_delete_nesting = trash_delete_nesting;
264+
265+
thread_state->exc_state = exc_state;
266+
thread_state->exc_info = exc_info;
195267
#else
196268
/* Restore previously saved state. I wonder if PyThreadState_GET()
197269
* really needs to be called again here... */

0 commit comments

Comments
 (0)