17db96d56Sopenharmony_ci:mod:`multiprocessing.shared_memory` --- Shared memory for direct access across processes
27db96d56Sopenharmony_ci=========================================================================================
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci.. module:: multiprocessing.shared_memory
57db96d56Sopenharmony_ci   :synopsis: Provides shared memory for direct access across processes.
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci**Source code:** :source:`Lib/multiprocessing/shared_memory.py`
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci.. versionadded:: 3.8
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci.. index::
127db96d56Sopenharmony_ci   single: Shared Memory
137db96d56Sopenharmony_ci   single: POSIX Shared Memory
147db96d56Sopenharmony_ci   single: Named Shared Memory
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ci--------------
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciThis module provides a class, :class:`SharedMemory`, for the allocation
197db96d56Sopenharmony_ciand management of shared memory to be accessed by one or more processes
207db96d56Sopenharmony_cion a multicore or symmetric multiprocessor (SMP) machine.  To assist with
217db96d56Sopenharmony_cithe life-cycle management of shared memory especially across distinct
227db96d56Sopenharmony_ciprocesses, a :class:`~multiprocessing.managers.BaseManager` subclass,
237db96d56Sopenharmony_ci:class:`SharedMemoryManager`, is also provided in the
247db96d56Sopenharmony_ci``multiprocessing.managers`` module.
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ciIn this module, shared memory refers to "System V style" shared memory blocks
277db96d56Sopenharmony_ci(though is not necessarily implemented explicitly as such) and does not refer
287db96d56Sopenharmony_cito "distributed shared memory".  This style of shared memory permits distinct
297db96d56Sopenharmony_ciprocesses to potentially read and write to a common (or shared) region of
307db96d56Sopenharmony_civolatile memory.  Processes are conventionally limited to only have access to
317db96d56Sopenharmony_citheir own process memory space but shared memory permits the sharing
327db96d56Sopenharmony_ciof data between processes, avoiding the need to instead send messages between
337db96d56Sopenharmony_ciprocesses containing that data.  Sharing data directly via memory can provide
347db96d56Sopenharmony_cisignificant performance benefits compared to sharing data via disk or socket
357db96d56Sopenharmony_cior other communications requiring the serialization/deserialization and
367db96d56Sopenharmony_cicopying of data.
377db96d56Sopenharmony_ci
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ci.. class:: SharedMemory(name=None, create=False, size=0)
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ci   Creates a new shared memory block or attaches to an existing shared
427db96d56Sopenharmony_ci   memory block.  Each shared memory block is assigned a unique name.
437db96d56Sopenharmony_ci   In this way, one process can create a shared memory block with a
447db96d56Sopenharmony_ci   particular name and a different process can attach to that same shared
457db96d56Sopenharmony_ci   memory block using that same name.
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci   As a resource for sharing data across processes, shared memory blocks
487db96d56Sopenharmony_ci   may outlive the original process that created them.  When one process
497db96d56Sopenharmony_ci   no longer needs access to a shared memory block that might still be
507db96d56Sopenharmony_ci   needed by other processes, the :meth:`close()` method should be called.
517db96d56Sopenharmony_ci   When a shared memory block is no longer needed by any process, the
527db96d56Sopenharmony_ci   :meth:`unlink()` method should be called to ensure proper cleanup.
537db96d56Sopenharmony_ci
547db96d56Sopenharmony_ci   *name* is the unique name for the requested shared memory, specified as
557db96d56Sopenharmony_ci   a string.  When creating a new shared memory block, if ``None`` (the
567db96d56Sopenharmony_ci   default) is supplied for the name, a novel name will be generated.
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci   *create* controls whether a new shared memory block is created (``True``)
597db96d56Sopenharmony_ci   or an existing shared memory block is attached (``False``).
607db96d56Sopenharmony_ci
617db96d56Sopenharmony_ci   *size* specifies the requested number of bytes when creating a new shared
627db96d56Sopenharmony_ci   memory block.  Because some platforms choose to allocate chunks of memory
637db96d56Sopenharmony_ci   based upon that platform's memory page size, the exact size of the shared
647db96d56Sopenharmony_ci   memory block may be larger or equal to the size requested.  When attaching
657db96d56Sopenharmony_ci   to an existing shared memory block, the ``size`` parameter is ignored.
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci   .. method:: close()
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci      Closes access to the shared memory from this instance.  In order to
707db96d56Sopenharmony_ci      ensure proper cleanup of resources, all instances should call
717db96d56Sopenharmony_ci      ``close()`` once the instance is no longer needed.  Note that calling
727db96d56Sopenharmony_ci      ``close()`` does not cause the shared memory block itself to be
737db96d56Sopenharmony_ci      destroyed.
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci   .. method:: unlink()
767db96d56Sopenharmony_ci
777db96d56Sopenharmony_ci      Requests that the underlying shared memory block be destroyed.  In
787db96d56Sopenharmony_ci      order to ensure proper cleanup of resources, ``unlink()`` should be
797db96d56Sopenharmony_ci      called once (and only once) across all processes which have need
807db96d56Sopenharmony_ci      for the shared memory block.  After requesting its destruction, a
817db96d56Sopenharmony_ci      shared memory block may or may not be immediately destroyed and
827db96d56Sopenharmony_ci      this behavior may differ across platforms.  Attempts to access data
837db96d56Sopenharmony_ci      inside the shared memory block after ``unlink()`` has been called may
847db96d56Sopenharmony_ci      result in memory access errors.  Note: the last process relinquishing
857db96d56Sopenharmony_ci      its hold on a shared memory block may call ``unlink()`` and
867db96d56Sopenharmony_ci      :meth:`close()` in either order.
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci   .. attribute:: buf
897db96d56Sopenharmony_ci
907db96d56Sopenharmony_ci      A memoryview of contents of the shared memory block.
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ci   .. attribute:: name
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ci      Read-only access to the unique name of the shared memory block.
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci   .. attribute:: size
977db96d56Sopenharmony_ci
987db96d56Sopenharmony_ci      Read-only access to size in bytes of the shared memory block.
997db96d56Sopenharmony_ci
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ciThe following example demonstrates low-level use of :class:`SharedMemory`
1027db96d56Sopenharmony_ciinstances::
1037db96d56Sopenharmony_ci
1047db96d56Sopenharmony_ci   >>> from multiprocessing import shared_memory
1057db96d56Sopenharmony_ci   >>> shm_a = shared_memory.SharedMemory(create=True, size=10)
1067db96d56Sopenharmony_ci   >>> type(shm_a.buf)
1077db96d56Sopenharmony_ci   <class 'memoryview'>
1087db96d56Sopenharmony_ci   >>> buffer = shm_a.buf
1097db96d56Sopenharmony_ci   >>> len(buffer)
1107db96d56Sopenharmony_ci   10
1117db96d56Sopenharmony_ci   >>> buffer[:4] = bytearray([22, 33, 44, 55])  # Modify multiple at once
1127db96d56Sopenharmony_ci   >>> buffer[4] = 100                           # Modify single byte at a time
1137db96d56Sopenharmony_ci   >>> # Attach to an existing shared memory block
1147db96d56Sopenharmony_ci   >>> shm_b = shared_memory.SharedMemory(shm_a.name)
1157db96d56Sopenharmony_ci   >>> import array
1167db96d56Sopenharmony_ci   >>> array.array('b', shm_b.buf[:5])  # Copy the data into a new array.array
1177db96d56Sopenharmony_ci   array('b', [22, 33, 44, 55, 100])
1187db96d56Sopenharmony_ci   >>> shm_b.buf[:5] = b'howdy'  # Modify via shm_b using bytes
1197db96d56Sopenharmony_ci   >>> bytes(shm_a.buf[:5])      # Access via shm_a
1207db96d56Sopenharmony_ci   b'howdy'
1217db96d56Sopenharmony_ci   >>> shm_b.close()   # Close each SharedMemory instance
1227db96d56Sopenharmony_ci   >>> shm_a.close()
1237db96d56Sopenharmony_ci   >>> shm_a.unlink()  # Call unlink only once to release the shared memory
1247db96d56Sopenharmony_ci
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci
1277db96d56Sopenharmony_ciThe following example demonstrates a practical use of the :class:`SharedMemory`
1287db96d56Sopenharmony_ciclass with `NumPy arrays <https://numpy.org/>`_, accessing the
1297db96d56Sopenharmony_cisame ``numpy.ndarray`` from two distinct Python shells:
1307db96d56Sopenharmony_ci
1317db96d56Sopenharmony_ci.. doctest::
1327db96d56Sopenharmony_ci   :options: +SKIP
1337db96d56Sopenharmony_ci
1347db96d56Sopenharmony_ci   >>> # In the first Python interactive shell
1357db96d56Sopenharmony_ci   >>> import numpy as np
1367db96d56Sopenharmony_ci   >>> a = np.array([1, 1, 2, 3, 5, 8])  # Start with an existing NumPy array
1377db96d56Sopenharmony_ci   >>> from multiprocessing import shared_memory
1387db96d56Sopenharmony_ci   >>> shm = shared_memory.SharedMemory(create=True, size=a.nbytes)
1397db96d56Sopenharmony_ci   >>> # Now create a NumPy array backed by shared memory
1407db96d56Sopenharmony_ci   >>> b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)
1417db96d56Sopenharmony_ci   >>> b[:] = a[:]  # Copy the original data into shared memory
1427db96d56Sopenharmony_ci   >>> b
1437db96d56Sopenharmony_ci   array([1, 1, 2, 3, 5, 8])
1447db96d56Sopenharmony_ci   >>> type(b)
1457db96d56Sopenharmony_ci   <class 'numpy.ndarray'>
1467db96d56Sopenharmony_ci   >>> type(a)
1477db96d56Sopenharmony_ci   <class 'numpy.ndarray'>
1487db96d56Sopenharmony_ci   >>> shm.name  # We did not specify a name so one was chosen for us
1497db96d56Sopenharmony_ci   'psm_21467_46075'
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci   >>> # In either the same shell or a new Python shell on the same machine
1527db96d56Sopenharmony_ci   >>> import numpy as np
1537db96d56Sopenharmony_ci   >>> from multiprocessing import shared_memory
1547db96d56Sopenharmony_ci   >>> # Attach to the existing shared memory block
1557db96d56Sopenharmony_ci   >>> existing_shm = shared_memory.SharedMemory(name='psm_21467_46075')
1567db96d56Sopenharmony_ci   >>> # Note that a.shape is (6,) and a.dtype is np.int64 in this example
1577db96d56Sopenharmony_ci   >>> c = np.ndarray((6,), dtype=np.int64, buffer=existing_shm.buf)
1587db96d56Sopenharmony_ci   >>> c
1597db96d56Sopenharmony_ci   array([1, 1, 2, 3, 5, 8])
1607db96d56Sopenharmony_ci   >>> c[-1] = 888
1617db96d56Sopenharmony_ci   >>> c
1627db96d56Sopenharmony_ci   array([  1,   1,   2,   3,   5, 888])
1637db96d56Sopenharmony_ci
1647db96d56Sopenharmony_ci   >>> # Back in the first Python interactive shell, b reflects this change
1657db96d56Sopenharmony_ci   >>> b
1667db96d56Sopenharmony_ci   array([  1,   1,   2,   3,   5, 888])
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci   >>> # Clean up from within the second Python shell
1697db96d56Sopenharmony_ci   >>> del c  # Unnecessary; merely emphasizing the array is no longer used
1707db96d56Sopenharmony_ci   >>> existing_shm.close()
1717db96d56Sopenharmony_ci
1727db96d56Sopenharmony_ci   >>> # Clean up from within the first Python shell
1737db96d56Sopenharmony_ci   >>> del b  # Unnecessary; merely emphasizing the array is no longer used
1747db96d56Sopenharmony_ci   >>> shm.close()
1757db96d56Sopenharmony_ci   >>> shm.unlink()  # Free and release the shared memory block at the very end
1767db96d56Sopenharmony_ci
1777db96d56Sopenharmony_ci
1787db96d56Sopenharmony_ci.. class:: SharedMemoryManager([address[, authkey]])
1797db96d56Sopenharmony_ci   :module: multiprocessing.managers
1807db96d56Sopenharmony_ci
1817db96d56Sopenharmony_ci   A subclass of :class:`~multiprocessing.managers.BaseManager` which can be
1827db96d56Sopenharmony_ci   used for the management of shared memory blocks across processes.
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci   A call to :meth:`~multiprocessing.managers.BaseManager.start` on a
1857db96d56Sopenharmony_ci   :class:`SharedMemoryManager` instance causes a new process to be started.
1867db96d56Sopenharmony_ci   This new process's sole purpose is to manage the life cycle
1877db96d56Sopenharmony_ci   of all shared memory blocks created through it.  To trigger the release
1887db96d56Sopenharmony_ci   of all shared memory blocks managed by that process, call
1897db96d56Sopenharmony_ci   :meth:`~multiprocessing.managers.BaseManager.shutdown()` on the instance.
1907db96d56Sopenharmony_ci   This triggers a :meth:`SharedMemory.unlink()` call on all of the
1917db96d56Sopenharmony_ci   :class:`SharedMemory` objects managed by that process and then
1927db96d56Sopenharmony_ci   stops the process itself.  By creating ``SharedMemory`` instances
1937db96d56Sopenharmony_ci   through a ``SharedMemoryManager``, we avoid the need to manually track
1947db96d56Sopenharmony_ci   and trigger the freeing of shared memory resources.
1957db96d56Sopenharmony_ci
1967db96d56Sopenharmony_ci   This class provides methods for creating and returning :class:`SharedMemory`
1977db96d56Sopenharmony_ci   instances and for creating a list-like object (:class:`ShareableList`)
1987db96d56Sopenharmony_ci   backed by shared memory.
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci   Refer to :class:`multiprocessing.managers.BaseManager` for a description
2017db96d56Sopenharmony_ci   of the inherited *address* and *authkey* optional input arguments and how
2027db96d56Sopenharmony_ci   they may be used to connect to an existing ``SharedMemoryManager`` service
2037db96d56Sopenharmony_ci   from other processes.
2047db96d56Sopenharmony_ci
2057db96d56Sopenharmony_ci   .. method:: SharedMemory(size)
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci      Create and return a new :class:`SharedMemory` object with the
2087db96d56Sopenharmony_ci      specified ``size`` in bytes.
2097db96d56Sopenharmony_ci
2107db96d56Sopenharmony_ci   .. method:: ShareableList(sequence)
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ci      Create and return a new :class:`ShareableList` object, initialized
2137db96d56Sopenharmony_ci      by the values from the input ``sequence``.
2147db96d56Sopenharmony_ci
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ciThe following example demonstrates the basic mechanisms of a
2177db96d56Sopenharmony_ci:class:`SharedMemoryManager`:
2187db96d56Sopenharmony_ci
2197db96d56Sopenharmony_ci.. doctest::
2207db96d56Sopenharmony_ci   :options: +SKIP
2217db96d56Sopenharmony_ci
2227db96d56Sopenharmony_ci   >>> from multiprocessing.managers import SharedMemoryManager
2237db96d56Sopenharmony_ci   >>> smm = SharedMemoryManager()
2247db96d56Sopenharmony_ci   >>> smm.start()  # Start the process that manages the shared memory blocks
2257db96d56Sopenharmony_ci   >>> sl = smm.ShareableList(range(4))
2267db96d56Sopenharmony_ci   >>> sl
2277db96d56Sopenharmony_ci   ShareableList([0, 1, 2, 3], name='psm_6572_7512')
2287db96d56Sopenharmony_ci   >>> raw_shm = smm.SharedMemory(size=128)
2297db96d56Sopenharmony_ci   >>> another_sl = smm.ShareableList('alpha')
2307db96d56Sopenharmony_ci   >>> another_sl
2317db96d56Sopenharmony_ci   ShareableList(['a', 'l', 'p', 'h', 'a'], name='psm_6572_12221')
2327db96d56Sopenharmony_ci   >>> smm.shutdown()  # Calls unlink() on sl, raw_shm, and another_sl
2337db96d56Sopenharmony_ci
2347db96d56Sopenharmony_ciThe following example depicts a potentially more convenient pattern for using
2357db96d56Sopenharmony_ci:class:`SharedMemoryManager` objects via the :keyword:`with` statement to
2367db96d56Sopenharmony_ciensure that all shared memory blocks are released after they are no longer
2377db96d56Sopenharmony_cineeded:
2387db96d56Sopenharmony_ci
2397db96d56Sopenharmony_ci.. doctest::
2407db96d56Sopenharmony_ci   :options: +SKIP
2417db96d56Sopenharmony_ci
2427db96d56Sopenharmony_ci   >>> with SharedMemoryManager() as smm:
2437db96d56Sopenharmony_ci   ...     sl = smm.ShareableList(range(2000))
2447db96d56Sopenharmony_ci   ...     # Divide the work among two processes, storing partial results in sl
2457db96d56Sopenharmony_ci   ...     p1 = Process(target=do_work, args=(sl, 0, 1000))
2467db96d56Sopenharmony_ci   ...     p2 = Process(target=do_work, args=(sl, 1000, 2000))
2477db96d56Sopenharmony_ci   ...     p1.start()
2487db96d56Sopenharmony_ci   ...     p2.start()  # A multiprocessing.Pool might be more efficient
2497db96d56Sopenharmony_ci   ...     p1.join()
2507db96d56Sopenharmony_ci   ...     p2.join()   # Wait for all work to complete in both processes
2517db96d56Sopenharmony_ci   ...     total_result = sum(sl)  # Consolidate the partial results now in sl
2527db96d56Sopenharmony_ci
2537db96d56Sopenharmony_ciWhen using a :class:`SharedMemoryManager` in a :keyword:`with` statement, the
2547db96d56Sopenharmony_cishared memory blocks created using that manager are all released when the
2557db96d56Sopenharmony_ci:keyword:`with` statement's code block finishes execution.
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci
2587db96d56Sopenharmony_ci.. class:: ShareableList(sequence=None, *, name=None)
2597db96d56Sopenharmony_ci
2607db96d56Sopenharmony_ci   Provides a mutable list-like object where all values stored within are
2617db96d56Sopenharmony_ci   stored in a shared memory block.  This constrains storable values to
2627db96d56Sopenharmony_ci   only the ``int``, ``float``, ``bool``, ``str`` (less than 10M bytes each),
2637db96d56Sopenharmony_ci   ``bytes`` (less than 10M bytes each), and ``None`` built-in data types.
2647db96d56Sopenharmony_ci   It also notably differs from the built-in ``list`` type in that these
2657db96d56Sopenharmony_ci   lists can not change their overall length (i.e. no append, insert, etc.)
2667db96d56Sopenharmony_ci   and do not support the dynamic creation of new :class:`ShareableList`
2677db96d56Sopenharmony_ci   instances via slicing.
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci   *sequence* is used in populating a new ``ShareableList`` full of values.
2707db96d56Sopenharmony_ci   Set to ``None`` to instead attach to an already existing
2717db96d56Sopenharmony_ci   ``ShareableList`` by its unique shared memory name.
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci   *name* is the unique name for the requested shared memory, as described
2747db96d56Sopenharmony_ci   in the definition for :class:`SharedMemory`.  When attaching to an
2757db96d56Sopenharmony_ci   existing ``ShareableList``, specify its shared memory block's unique
2767db96d56Sopenharmony_ci   name while leaving ``sequence`` set to ``None``.
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci   .. method:: count(value)
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci      Returns the number of occurrences of ``value``.
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ci   .. method:: index(value)
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ci      Returns first index position of ``value``.  Raises :exc:`ValueError` if
2857db96d56Sopenharmony_ci      ``value`` is not present.
2867db96d56Sopenharmony_ci
2877db96d56Sopenharmony_ci   .. attribute:: format
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci      Read-only attribute containing the :mod:`struct` packing format used by
2907db96d56Sopenharmony_ci      all currently stored values.
2917db96d56Sopenharmony_ci
2927db96d56Sopenharmony_ci   .. attribute:: shm
2937db96d56Sopenharmony_ci
2947db96d56Sopenharmony_ci      The :class:`SharedMemory` instance where the values are stored.
2957db96d56Sopenharmony_ci
2967db96d56Sopenharmony_ci
2977db96d56Sopenharmony_ciThe following example demonstrates basic use of a :class:`ShareableList`
2987db96d56Sopenharmony_ciinstance:
2997db96d56Sopenharmony_ci
3007db96d56Sopenharmony_ci   >>> from multiprocessing import shared_memory
3017db96d56Sopenharmony_ci   >>> a = shared_memory.ShareableList(['howdy', b'HoWdY', -273.154, 100, None, True, 42])
3027db96d56Sopenharmony_ci   >>> [ type(entry) for entry in a ]
3037db96d56Sopenharmony_ci   [<class 'str'>, <class 'bytes'>, <class 'float'>, <class 'int'>, <class 'NoneType'>, <class 'bool'>, <class 'int'>]
3047db96d56Sopenharmony_ci   >>> a[2]
3057db96d56Sopenharmony_ci   -273.154
3067db96d56Sopenharmony_ci   >>> a[2] = -78.5
3077db96d56Sopenharmony_ci   >>> a[2]
3087db96d56Sopenharmony_ci   -78.5
3097db96d56Sopenharmony_ci   >>> a[2] = 'dry ice'  # Changing data types is supported as well
3107db96d56Sopenharmony_ci   >>> a[2]
3117db96d56Sopenharmony_ci   'dry ice'
3127db96d56Sopenharmony_ci   >>> a[2] = 'larger than previously allocated storage space'
3137db96d56Sopenharmony_ci   Traceback (most recent call last):
3147db96d56Sopenharmony_ci     ...
3157db96d56Sopenharmony_ci   ValueError: exceeds available storage for existing str
3167db96d56Sopenharmony_ci   >>> a[2]
3177db96d56Sopenharmony_ci   'dry ice'
3187db96d56Sopenharmony_ci   >>> len(a)
3197db96d56Sopenharmony_ci   7
3207db96d56Sopenharmony_ci   >>> a.index(42)
3217db96d56Sopenharmony_ci   6
3227db96d56Sopenharmony_ci   >>> a.count(b'howdy')
3237db96d56Sopenharmony_ci   0
3247db96d56Sopenharmony_ci   >>> a.count(b'HoWdY')
3257db96d56Sopenharmony_ci   1
3267db96d56Sopenharmony_ci   >>> a.shm.close()
3277db96d56Sopenharmony_ci   >>> a.shm.unlink()
3287db96d56Sopenharmony_ci   >>> del a  # Use of a ShareableList after call to unlink() is unsupported
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ciThe following example depicts how one, two, or many processes may access the
3317db96d56Sopenharmony_cisame :class:`ShareableList` by supplying the name of the shared memory block
3327db96d56Sopenharmony_cibehind it:
3337db96d56Sopenharmony_ci
3347db96d56Sopenharmony_ci   >>> b = shared_memory.ShareableList(range(5))         # In a first process
3357db96d56Sopenharmony_ci   >>> c = shared_memory.ShareableList(name=b.shm.name)  # In a second process
3367db96d56Sopenharmony_ci   >>> c
3377db96d56Sopenharmony_ci   ShareableList([0, 1, 2, 3, 4], name='...')
3387db96d56Sopenharmony_ci   >>> c[-1] = -999
3397db96d56Sopenharmony_ci   >>> b[-1]
3407db96d56Sopenharmony_ci   -999
3417db96d56Sopenharmony_ci   >>> b.shm.close()
3427db96d56Sopenharmony_ci   >>> c.shm.close()
3437db96d56Sopenharmony_ci   >>> c.shm.unlink()
3447db96d56Sopenharmony_ci
3457db96d56Sopenharmony_ciThe following examples demonstrates that ``ShareableList``
3467db96d56Sopenharmony_ci(and underlying ``SharedMemory``) objects
3477db96d56Sopenharmony_cican be pickled and unpickled if needed.
3487db96d56Sopenharmony_ciNote, that it will still be the same shared object.
3497db96d56Sopenharmony_ciThis happens, because the deserialized object has
3507db96d56Sopenharmony_cithe same unique name and is just attached to an existing
3517db96d56Sopenharmony_ciobject with the same name (if the object is still alive):
3527db96d56Sopenharmony_ci
3537db96d56Sopenharmony_ci   >>> import pickle
3547db96d56Sopenharmony_ci   >>> from multiprocessing import shared_memory
3557db96d56Sopenharmony_ci   >>> sl = shared_memory.ShareableList(range(10))
3567db96d56Sopenharmony_ci   >>> list(sl)
3577db96d56Sopenharmony_ci   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3587db96d56Sopenharmony_ci
3597db96d56Sopenharmony_ci   >>> deserialized_sl = pickle.loads(pickle.dumps(sl))
3607db96d56Sopenharmony_ci   >>> list(deserialized_sl)
3617db96d56Sopenharmony_ci   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3627db96d56Sopenharmony_ci
3637db96d56Sopenharmony_ci   >>> sl[0] = -1
3647db96d56Sopenharmony_ci   >>> deserialized_sl[1] = -2
3657db96d56Sopenharmony_ci   >>> list(sl)
3667db96d56Sopenharmony_ci   [-1, -2, 2, 3, 4, 5, 6, 7, 8, 9]
3677db96d56Sopenharmony_ci   >>> list(deserialized_sl)
3687db96d56Sopenharmony_ci   [-1, -2, 2, 3, 4, 5, 6, 7, 8, 9]
3697db96d56Sopenharmony_ci
3707db96d56Sopenharmony_ci   >>> sl.shm.close()
3717db96d56Sopenharmony_ci   >>> sl.shm.unlink()
372