Backed out 5 changesets (bug 1890092, bug 1888683) for causing build bustages & crash...
[gecko.git] / third_party / rust / uniffi_bindgen / src / bindings / python / templates / PointerManager.py
blob23aa28eab44ccb5e58d73f4068033f879d191738
1 class _UniffiPointerManagerCPython:
2 """
3 Manage giving out pointers to Python objects on CPython
5 This class is used to generate opaque pointers that reference Python objects to pass to Rust.
6 It assumes a CPython platform. See _UniffiPointerManagerGeneral for the alternative.
7 """
9 def new_pointer(self, obj):
10 """
11 Get a pointer for an object as a ctypes.c_size_t instance
13 Each call to new_pointer() must be balanced with exactly one call to release_pointer()
15 This returns a ctypes.c_size_t. This is always the same size as a pointer and can be
16 interchanged with pointers for FFI function arguments and return values.
17 """
18 # IncRef the object since we're going to pass a pointer to Rust
19 ctypes.pythonapi.Py_IncRef(ctypes.py_object(obj))
20 # id() is the object address on CPython
21 # (https://docs.python.org/3/library/functions.html#id)
22 return id(obj)
24 def release_pointer(self, address):
25 py_obj = ctypes.cast(address, ctypes.py_object)
26 obj = py_obj.value
27 ctypes.pythonapi.Py_DecRef(py_obj)
28 return obj
30 def lookup(self, address):
31 return ctypes.cast(address, ctypes.py_object).value
33 class _UniffiPointerManagerGeneral:
34 """
35 Manage giving out pointers to Python objects on non-CPython platforms
37 This has the same API as _UniffiPointerManagerCPython, but doesn't assume we're running on
38 CPython and is slightly slower.
40 Instead of using real pointers, it maps integer values to objects and returns the keys as
41 c_size_t values.
42 """
44 def __init__(self):
45 self._map = {}
46 self._lock = threading.Lock()
47 self._current_handle = 0
49 def new_pointer(self, obj):
50 with self._lock:
51 handle = self._current_handle
52 self._current_handle += 1
53 self._map[handle] = obj
54 return handle
56 def release_pointer(self, handle):
57 with self._lock:
58 return self._map.pop(handle)
60 def lookup(self, handle):
61 with self._lock:
62 return self._map[handle]
64 # Pick an pointer manager implementation based on the platform
65 if platform.python_implementation() == 'CPython':
66 _UniffiPointerManager = _UniffiPointerManagerCPython # type: ignore
67 else:
68 _UniffiPointerManager = _UniffiPointerManagerGeneral # type: ignore