| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | """Cross-interpreter Channels High Level Module.""" | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  | import time | 
					
						
							| 
									
										
										
										
											2024-04-24 10:18:24 -06:00
										 |  |  | import _interpchannels as _channels | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  | from . import _crossinterp | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | # aliases: | 
					
						
							| 
									
										
										
										
											2024-04-24 10:18:24 -06:00
										 |  |  | from _interpchannels import ( | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |     ChannelError, ChannelNotFoundError, ChannelClosedError, | 
					
						
							|  |  |  |     ChannelEmptyError, ChannelNotEmptyError, | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  | from ._crossinterp import ( | 
					
						
							|  |  |  |     UNBOUND_ERROR, UNBOUND_REMOVE, | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __all__ = [ | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     'UNBOUND', 'UNBOUND_ERROR', 'UNBOUND_REMOVE', | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     'create', 'list_all', | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |     'SendChannel', 'RecvChannel', | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  |     'ChannelError', 'ChannelNotFoundError', 'ChannelEmptyError', | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     'ItemInterpreterDestroyed', | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | ] | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  | class ItemInterpreterDestroyed(ChannelError, | 
					
						
							|  |  |  |                                _crossinterp.ItemInterpreterDestroyed): | 
					
						
							|  |  |  |     """Raised from get() and get_nowait().""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | UNBOUND = _crossinterp.UnboundItem.singleton('queue', __name__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _serialize_unbound(unbound): | 
					
						
							|  |  |  |     if unbound is UNBOUND: | 
					
						
							|  |  |  |         unbound = _crossinterp.UNBOUND | 
					
						
							|  |  |  |     return _crossinterp.serialize_unbound(unbound) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _resolve_unbound(flag): | 
					
						
							|  |  |  |     resolved = _crossinterp.resolve_unbound(flag, ItemInterpreterDestroyed) | 
					
						
							|  |  |  |     if resolved is _crossinterp.UNBOUND: | 
					
						
							|  |  |  |         resolved = UNBOUND | 
					
						
							|  |  |  |     return resolved | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create(*, unbounditems=UNBOUND): | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |     """Return (recv, send) for a new cross-interpreter channel.
 | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |     The channel may be used to pass data safely between interpreters. | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     "unbounditems" sets the default for the send end of the channel. | 
					
						
							|  |  |  |     See SendChannel.send() for supported values.  The default value | 
					
						
							|  |  |  |     is UNBOUND, which replaces the unbound item when received. | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     unbound = _serialize_unbound(unbounditems) | 
					
						
							|  |  |  |     unboundop, = unbound | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |     cid = _channels.create(unboundop, -1) | 
					
						
							|  |  |  |     recv, send = RecvChannel(cid), SendChannel(cid) | 
					
						
							|  |  |  |     send._set_unbound(unboundop, unbounditems) | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |     return recv, send | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-12 08:24:31 -07:00
										 |  |  | def list_all(): | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |     """Return a list of (recv, send) for all open channels.""" | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |     channels = [] | 
					
						
							|  |  |  |     for cid, unboundop, _ in _channels.list_all(): | 
					
						
							|  |  |  |         chan = _, send = RecvChannel(cid), SendChannel(cid) | 
					
						
							|  |  |  |         if not hasattr(send, '_unboundop'): | 
					
						
							|  |  |  |             send._set_unbound(unboundop) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2025-05-22 08:40:33 -06:00
										 |  |  |             assert send._unbound[0] == unboundop | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |         channels.append(chan) | 
					
						
							|  |  |  |     return channels | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  | class _ChannelEnd: | 
					
						
							|  |  |  |     """The base class for RecvChannel and SendChannel.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |     _end = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 08:54:46 -07:00
										 |  |  |     def __new__(cls, cid): | 
					
						
							|  |  |  |         self = super().__new__(cls) | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |         if self._end == 'send': | 
					
						
							|  |  |  |             cid = _channels._channel_id(cid, send=True, force=True) | 
					
						
							|  |  |  |         elif self._end == 'recv': | 
					
						
							|  |  |  |             cid = _channels._channel_id(cid, recv=True, force=True) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise NotImplementedError(self._end) | 
					
						
							|  |  |  |         self._id = cid | 
					
						
							| 
									
										
										
										
											2024-03-05 08:54:46 -07:00
										 |  |  |         return self | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							|  |  |  |         return f'{type(self).__name__}(id={int(self._id)})' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __hash__(self): | 
					
						
							|  |  |  |         return hash(self._id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         if isinstance(self, RecvChannel): | 
					
						
							|  |  |  |             if not isinstance(other, RecvChannel): | 
					
						
							|  |  |  |                 return NotImplemented | 
					
						
							|  |  |  |         elif not isinstance(other, SendChannel): | 
					
						
							|  |  |  |             return NotImplemented | 
					
						
							|  |  |  |         return other._id == self._id | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-05 08:54:46 -07:00
										 |  |  |     # for pickling: | 
					
						
							|  |  |  |     def __getnewargs__(self): | 
					
						
							|  |  |  |         return (int(self._id),) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # for pickling: | 
					
						
							|  |  |  |     def __getstate__(self): | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def id(self): | 
					
						
							|  |  |  |         return self._id | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-19 08:51:21 -06:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def _info(self): | 
					
						
							|  |  |  |         return _channels.get_info(self._id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def is_closed(self): | 
					
						
							|  |  |  |         return self._info.closed | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | _NOT_SET = object() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  | class RecvChannel(_ChannelEnd): | 
					
						
							|  |  |  |     """The receiving end of a cross-interpreter channel.""" | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |     _end = 'recv' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-17 17:05:49 -06:00
										 |  |  |     def recv(self, timeout=None, *, | 
					
						
							|  |  |  |              _sentinel=object(), | 
					
						
							|  |  |  |              _delay=10 / 1000,  # 10 milliseconds | 
					
						
							|  |  |  |              ): | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         """Return the next object from the channel.
 | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         This blocks until an object has been sent, if none have been | 
					
						
							|  |  |  |         sent already. | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2023-10-17 17:05:49 -06:00
										 |  |  |         if timeout is not None: | 
					
						
							|  |  |  |             timeout = int(timeout) | 
					
						
							|  |  |  |             if timeout < 0: | 
					
						
							|  |  |  |                 raise ValueError(f'timeout value must be non-negative') | 
					
						
							|  |  |  |             end = time.time() + timeout | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         obj, unboundop = _channels.recv(self._id, _sentinel) | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         while obj is _sentinel: | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |             time.sleep(_delay) | 
					
						
							| 
									
										
										
										
											2023-10-17 17:05:49 -06:00
										 |  |  |             if timeout is not None and time.time() >= end: | 
					
						
							|  |  |  |                 raise TimeoutError | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |             obj, unboundop = _channels.recv(self._id, _sentinel) | 
					
						
							|  |  |  |         if unboundop is not None: | 
					
						
							|  |  |  |             assert obj is None, repr(obj) | 
					
						
							|  |  |  |             return _resolve_unbound(unboundop) | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |         return obj | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def recv_nowait(self, default=_NOT_SET): | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         """Return the next object from the channel.
 | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         If none have been sent then return the default if one | 
					
						
							|  |  |  |         is provided or fail with ChannelEmptyError.  Otherwise this | 
					
						
							|  |  |  |         is the same as recv(). | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         if default is _NOT_SET: | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |             obj, unboundop = _channels.recv(self._id) | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |             obj, unboundop = _channels.recv(self._id, default) | 
					
						
							|  |  |  |         if unboundop is not None: | 
					
						
							|  |  |  |             assert obj is None, repr(obj) | 
					
						
							|  |  |  |             return _resolve_unbound(unboundop) | 
					
						
							|  |  |  |         return obj | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |     def close(self): | 
					
						
							|  |  |  |         _channels.close(self._id, recv=True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  | class SendChannel(_ChannelEnd): | 
					
						
							|  |  |  |     """The sending end of a cross-interpreter channel.""" | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |     _end = 'send' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  | #    def __new__(cls, cid, *, _unbound=None): | 
					
						
							|  |  |  | #        if _unbound is None: | 
					
						
							|  |  |  | #            try: | 
					
						
							|  |  |  | #                op = _channels.get_channel_defaults(cid) | 
					
						
							|  |  |  | #                _unbound = (op,) | 
					
						
							|  |  |  | #            except ChannelNotFoundError: | 
					
						
							|  |  |  | #                _unbound = _serialize_unbound(UNBOUND) | 
					
						
							|  |  |  | #        self = super().__new__(cls, cid) | 
					
						
							|  |  |  | #        self._unbound = _unbound | 
					
						
							|  |  |  | #        return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _set_unbound(self, op, items=None): | 
					
						
							|  |  |  |         assert not hasattr(self, '_unbound') | 
					
						
							|  |  |  |         if items is None: | 
					
						
							|  |  |  |             items = _resolve_unbound(op) | 
					
						
							|  |  |  |         unbound = (op, items) | 
					
						
							|  |  |  |         self._unbound = unbound | 
					
						
							|  |  |  |         return unbound | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @property | 
					
						
							|  |  |  |     def unbounditems(self): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             _, items = self._unbound | 
					
						
							|  |  |  |         except AttributeError: | 
					
						
							|  |  |  |             op, _ = _channels.get_queue_defaults(self._id) | 
					
						
							|  |  |  |             _, items = self._set_unbound(op) | 
					
						
							|  |  |  |         return items | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-19 08:51:21 -06:00
										 |  |  |     @property | 
					
						
							|  |  |  |     def is_closed(self): | 
					
						
							|  |  |  |         info = self._info | 
					
						
							|  |  |  |         return info.closed or info.closing | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     def send(self, obj, timeout=None, *, | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |              unbounditems=None, | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |              ): | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         """Send the object (i.e. its data) to the channel's receiving end.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This blocks until the object is received. | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |         if unbounditems is None: | 
					
						
							|  |  |  |             unboundop = -1 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |             unboundop, = _serialize_unbound(unbounditems) | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         _channels.send(self._id, obj, unboundop, timeout=timeout, blocking=True) | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     def send_nowait(self, obj, *, | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |                     unbounditems=None, | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |                     ): | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         """Send the object to the channel's receiving end.
 | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         If the object is immediately received then return True | 
					
						
							|  |  |  |         (else False).  Otherwise this is the same as send(). | 
					
						
							| 
									
										
										
										
											2020-06-10 00:53:23 -03:00
										 |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |         if unbounditems is None: | 
					
						
							|  |  |  |             unboundop = -1 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |             unboundop, = _serialize_unbound(unbounditems) | 
					
						
							| 
									
										
										
										
											2020-06-16 18:24:40 -06:00
										 |  |  |         # XXX Note that at the moment channel_send() only ever returns | 
					
						
							|  |  |  |         # None.  This should be fixed when channel_send_wait() is added. | 
					
						
							|  |  |  |         # See bpo-32604 and gh-19829. | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         return _channels.send(self._id, obj, unboundop, blocking=False) | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     def send_buffer(self, obj, timeout=None, *, | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |                     unbounditems=None, | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |                     ): | 
					
						
							| 
									
										
										
										
											2023-10-09 07:39:51 -06:00
										 |  |  |         """Send the object's buffer to the channel's receiving end.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This blocks until the object is received. | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |         if unbounditems is None: | 
					
						
							|  |  |  |             unboundop = -1 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |             unboundop, = _serialize_unbound(unbounditems) | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         _channels.send_buffer(self._id, obj, unboundop, | 
					
						
							|  |  |  |                               timeout=timeout, blocking=True) | 
					
						
							| 
									
										
										
										
											2023-10-09 07:39:51 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |     def send_buffer_nowait(self, obj, *, | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |                            unbounditems=None, | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |                            ): | 
					
						
							| 
									
										
										
										
											2023-10-09 07:39:51 -06:00
										 |  |  |         """Send the object's buffer to the channel's receiving end.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         If the object is immediately received then return True | 
					
						
							|  |  |  |         (else False).  Otherwise this is the same as send(). | 
					
						
							|  |  |  |         """
 | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |         if unbounditems is None: | 
					
						
							|  |  |  |             unboundop = -1 | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2025-05-22 06:50:06 -06:00
										 |  |  |             unboundop, = _serialize_unbound(unbounditems) | 
					
						
							| 
									
										
										
										
											2024-07-15 13:43:59 -06:00
										 |  |  |         return _channels.send_buffer(self._id, obj, unboundop, blocking=False) | 
					
						
							| 
									
										
										
										
											2023-10-09 07:39:51 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 14:47:41 -06:00
										 |  |  |     def close(self): | 
					
						
							|  |  |  |         _channels.close(self._id, send=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-03 18:36:50 -06:00
										 |  |  | # XXX This is causing leaks (gh-110318): | 
					
						
							| 
									
										
										
										
											2023-10-19 08:52:02 -06:00
										 |  |  | _channels._register_end_types(SendChannel, RecvChannel) |