Skip to content

Commit c912896

Browse files
PEP 797: Revisions from first discussion round (#4786)
* Add a terminology section. * Add a section about proxying methods. * Add the __share__ method. * Fix typo and add an example.
1 parent c9a6f28 commit c912896

File tree

1 file changed

+76
-9
lines changed

1 file changed

+76
-9
lines changed

peps/pep-0797.rst

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ For example:
3030
interp.prepare_main(file=proxy)
3131
interp.exec("file.write('I didn't expect the Spanish Inquisition')")
3232
33+
Terminology
34+
===========
35+
36+
This PEP uses the term "share", "sharing", and "shareable" to refer to objects
37+
that are *natively* shareable between interpreters. This differs from :pep:`734`,
38+
which uses these terms to also describe an object that supports the :mod:`pickle`
39+
module.
40+
41+
In addition to the new :class:`~concurrent.interpreters.SharedObjectProxy` type,
42+
the list of natively shareable objects can be found in :ref:`the documentation
43+
<interp-object-sharing>`.
44+
3345
Motivation
3446
==========
3547

@@ -69,21 +81,56 @@ implementing other methods to share objects between interpreters.
6981
Specification
7082
=============
7183

72-
.. class:: concurrent.interpreters.SharedObjectProxy
84+
85+
.. function:: concurrent.interpreters.share(obj)
86+
87+
Ensure *obj* is natively shareable.
88+
89+
If *obj* is natively shareable, this function does not create a proxy and
90+
simply returns *obj*. Otherwise, *obj* is wrapped in an instance of
91+
:class:`~concurrent.interpreters.SharedObjectProxy` and returned.
92+
93+
If *obj* has a :meth:`~object.__share__` method, the default behavior of
94+
this function is overridden; the object's ``__share__`` method will be
95+
called to convert *obj* into a natively shareable version of itself, which
96+
will be returned by this function. If the object returned by ``__share__``
97+
is not natively shareable, this function raises an exception.
98+
99+
The behavior of this function is roughly equivalent to:
100+
101+
.. code-block:: python
102+
103+
def share(obj):
104+
if _is_natively_shareable(obj):
105+
return obj
106+
107+
if hasattr(obj, "__share__"):
108+
shareable = obj.__share__()
109+
if not _is_natively_shareable(shareable):
110+
raise TypeError(f"__share__() returned unshareable object: {shareable!r}")
111+
112+
return shareable
113+
114+
return SharedObjectProxy(obj)
115+
116+
117+
.. class:: concurrent.interpreters.SharedObjectProxy(obj)
73118

74119
A proxy type that allows access to an object across multiple interpreters.
75-
This cannot be constructed from Python; instead, use the
76-
:func:`~concurrent.interpreters.share` function.
120+
Instances of this object are natively shareable between subinterpreters.
77121

122+
Unlike :func:`~concurrent.interpreters.share`, *obj* will always be wrapped,
123+
even if it is natively shareable already or already a ``SharedObjectProxy``
124+
instance. The object's :meth:`~object.__share__` method is not invoked if
125+
it is available. Thus, prefer using ``share`` where possible.
78126

79-
.. function:: concurrent.interpreters.share(obj)
80127

81-
Wrap *obj* in a :class:`~concurrent.interpreters.SharedObjectProxy`,
82-
allowing it to be used in other interpreter APIs as if it were natively
83-
shareable.
128+
.. function:: object.__share__()
84129

85-
If *obj* is natively shareable, this function does not create a proxy and
86-
simply returns *obj*.
130+
Return a natively shareable version of the current object. This includes
131+
shared object proxies, as they are also natively shareable. Objects composed
132+
of shared object proxies are also allowed, such as a :class:`tuple` whose
133+
elements are :class:`~concurrent.interpreters.SharedObjectProxy` instances.
87134

88135

89136
Interpreter Switching
@@ -108,6 +155,26 @@ accessed in subinterpreters through a proxy:
108155
interp.exec("foo()")
109156
110157
158+
Method Proxying
159+
---------------
160+
161+
Methods on a shared object proxy will switch to their owning interpreter when
162+
accessed. In addition, any arguments passed to the method are implicitly called
163+
with :func:`~concurrent.interpreters.share` to ensure they are shareable (only
164+
types that are not natively shareable are wrapped in a proxy). The same happens
165+
to the return value of the method.
166+
167+
For example, the ``__add__`` method on an object proxy is roughly equivalent
168+
to the following code:
169+
170+
.. code-block:: python
171+
172+
def __add__(self, other):
173+
with self.switch_interpreter():
174+
result = self.value.__add__(share(other))
175+
return share(result)
176+
177+
111178
Multithreaded Scaling
112179
---------------------
113180

0 commit comments

Comments
 (0)