Skip to content

Commit 37e4556

Browse files
committed
Implement the __share__() method.
1 parent a40da59 commit 37e4556

File tree

2 files changed

+103
-19
lines changed

2 files changed

+103
-19
lines changed

Modules/_interpretersmodule.c

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@
3333

3434
/*[clinic input]
3535
module _interpreters
36+
class _interpreters.SharedObjectProxy "SharedObjectProxy *" "&PyType_Type"
3637
[clinic start generated code]*/
37-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bfd967980a0de892]*/
38+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=4bb543de3f19aa0b]*/
3839

3940
static PyInterpreterState *
4041
_get_current_interp(void)
@@ -458,17 +459,44 @@ _sharedobjectproxy_exit(SharedObjectProxy *self, _PyXI_proxy_state *state)
458459
return 0;
459460
}
460461

461-
static PyObject *
462-
sharedobjectproxy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
462+
static SharedObjectProxy *
463+
sharedobjectproxy_alloc(PyTypeObject *type)
463464
{
464-
SharedObjectProxy *self = (SharedObjectProxy *)type->tp_alloc(type, 0);
465+
assert(type != NULL);
466+
assert(PyType_Check(type));
467+
SharedObjectProxy *self = SharedObjectProxy_CAST(type->tp_alloc(type, 0));
465468
if (self == NULL) {
466469
return NULL;
467470
}
468471

469-
self->object = Py_None;
470472
self->interp = _PyInterpreterState_GET();
473+
#ifndef NDEBUG
474+
self->object = NULL;
475+
#endif
476+
477+
return self;
478+
}
479+
480+
/*[clinic input]
481+
@classmethod
482+
_interpreters.SharedObjectProxy.__new__ as sharedobjectproxy_new
483+
484+
obj: object,
485+
/
486+
487+
Create a new cross-interpreter proxy.
488+
[clinic start generated code]*/
471489

490+
static PyObject *
491+
sharedobjectproxy_new_impl(PyTypeObject *type, PyObject *obj)
492+
/*[clinic end generated code: output=42ed0a0bc47ecedf input=fce004d93517c6df]*/
493+
{
494+
SharedObjectProxy *self = sharedobjectproxy_alloc(type);
495+
if (self == NULL) {
496+
return NULL;
497+
}
498+
499+
self->object = Py_NewRef(obj);
472500
return (PyObject *)self;
473501
}
474502

@@ -483,8 +511,7 @@ _sharedobjectproxy_create(PyObject *object, PyInterpreterState *owning_interp)
483511
return NULL;
484512
}
485513
assert(Py_TYPE(object) != type);
486-
SharedObjectProxy *proxy = SharedObjectProxy_CAST(sharedobjectproxy_new(type,
487-
NULL, NULL));
514+
SharedObjectProxy *proxy = sharedobjectproxy_alloc(type);
488515
if (proxy == NULL) {
489516
return NULL;
490517
}
@@ -1278,8 +1305,7 @@ static PyType_Slot SharedObjectProxy_slots[] = {
12781305
static PyType_Spec SharedObjectProxy_spec = {
12791306
.name = MODULE_NAME_STR ".SharedObjectProxy",
12801307
.basicsize = sizeof(SharedObjectProxy),
1281-
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1282-
Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE
1308+
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE
12831309
| Py_TPFLAGS_HAVE_GC),
12841310
.slots = SharedObjectProxy_slots,
12851311
};
@@ -2521,22 +2547,53 @@ _interpreters_capture_exception_impl(PyObject *module, PyObject *exc_arg)
25212547
return captured;
25222548
}
25232549

2550+
static PyObject *
2551+
call_share_method_steal(PyObject *method)
2552+
{
2553+
assert(method != NULL);
2554+
PyObject *result = PyObject_CallNoArgs(method);
2555+
Py_DECREF(method);
2556+
if (result == NULL) {
2557+
return NULL;
2558+
}
2559+
2560+
PyThreadState *tstate = _PyThreadState_GET();
2561+
assert(tstate != NULL);
2562+
2563+
if (_PyObject_CheckXIData(tstate, result) < 0) {
2564+
PyObject *exc = _PyErr_GetRaisedException(tstate);
2565+
_PyXIData_FormatNotShareableError(tstate, "__share__() returned unshareable object: %R", result);
2566+
PyObject *new_exc = _PyErr_GetRaisedException(tstate);
2567+
PyException_SetCause(new_exc, exc);
2568+
PyErr_SetRaisedException(new_exc);
2569+
Py_DECREF(result);
2570+
return NULL;
2571+
}
2572+
2573+
return result;
2574+
}
2575+
25242576
/*[clinic input]
25252577
_interpreters.share
25262578
op: object,
25272579
/
25282580
25292581
25302582
Wrap an object in a shareable proxy that allows cross-interpreter access.
2531-
2532-
The proxy will be assigned a context and may have its references cleared by
2533-
_interpreters.close_proxy().
25342583
[clinic start generated code]*/
25352584

25362585
static PyObject *
25372586
_interpreters_share(PyObject *module, PyObject *op)
2538-
/*[clinic end generated code: output=e2ce861ae3b58508 input=d333c93f128faf93]*/
2587+
/*[clinic end generated code: output=e2ce861ae3b58508 input=5fb300b5598bb7d2]*/
25392588
{
2589+
PyObject *share_method;
2590+
if (PyObject_GetOptionalAttrString(op, "__share__", &share_method) < 0) {
2591+
return NULL;
2592+
}
2593+
if (share_method != NULL) {
2594+
return call_share_method_steal(share_method /* stolen */);
2595+
}
2596+
25402597
return _sharedobjectproxy_create(op, _PyInterpreterState_GET());
25412598
}
25422599

Modules/clinic/_interpretersmodule.c.h

Lines changed: 33 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)