Commit | Line | Data |
---|---|---|
0235b0db | 1 | # SPDX-License-Identifier: MIT |
81447b5b | 2 | # |
811644b8 | 3 | # Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com> |
81447b5b | 4 | |
81447b5b | 5 | |
e57959f4 SM |
6 | import abc |
7 | ||
8 | ||
78288f58 SM |
9 | class _BaseObject: |
10 | # Ensure that the object always has _ptr set, even if it throws during | |
11 | # construction. | |
12 | ||
13 | def __new__(cls, *args, **kwargs): | |
14 | obj = super().__new__(cls) | |
15 | obj._ptr = None | |
16 | return obj | |
81447b5b | 17 | |
81447b5b PP |
18 | def __init__(self, ptr): |
19 | self._ptr = ptr | |
20 | ||
21 | @property | |
22 | def addr(self): | |
23 | return int(self._ptr) | |
24 | ||
78288f58 | 25 | def __repr__(self): |
f5567ea8 | 26 | return "<{}.{} object @ {}>".format( |
cfbd7cf3 FD |
27 | self.__class__.__module__, self.__class__.__name__, hex(self.addr) |
28 | ) | |
78288f58 SM |
29 | |
30 | def __copy__(self): | |
31 | raise NotImplementedError | |
32 | ||
33 | def __deepcopy__(self, memo): | |
34 | raise NotImplementedError | |
35 | ||
36 | ||
37 | # A Python object that is itself not refcounted, but is wholly owned by an | |
38 | # object that is itself refcounted (a _SharedObject). A Babeltrace unique | |
39 | # object gets destroyed once its owner gets destroyed (its refcount drops to | |
40 | # 0). | |
41 | # | |
42 | # In the Python bindings, to avoid having to deal with issues with the lifetime | |
43 | # of unique objects, we make it so acquiring a reference on a unique object | |
44 | # acquires a reference on its owner. | |
45 | ||
cfbd7cf3 | 46 | |
78288f58 SM |
47 | class _UniqueObject(_BaseObject): |
48 | ||
49 | # Create a _UniqueObject. | |
50 | # | |
51 | # - ptr: SWIG Object, pointer to the unique object. | |
52 | # - owner_ptr: SWIG Object, pointer to the owner of the unique | |
53 | # object. A new reference is acquired. | |
54 | # - owner_get_ref: Callback to get a reference on the owner | |
55 | # - owner_put_ref: Callback to put a reference on the owner. | |
56 | ||
81447b5b | 57 | @classmethod |
cfbd7cf3 | 58 | def _create_from_ptr_and_get_ref(cls, ptr, owner_ptr, owner_get_ref, owner_put_ref): |
81447b5b | 59 | obj = cls.__new__(cls) |
2ae9f48c | 60 | |
81447b5b | 61 | obj._ptr = ptr |
78288f58 | 62 | obj._owner_ptr = owner_ptr |
2ae9f48c | 63 | obj._owner_get_ref = owner_get_ref |
78288f58 | 64 | obj._owner_put_ref = owner_put_ref |
2ae9f48c SM |
65 | |
66 | obj._owner_get_ref(obj._owner_ptr) | |
67 | ||
81447b5b PP |
68 | return obj |
69 | ||
81447b5b | 70 | def __del__(self): |
78288f58 | 71 | self._owner_put_ref(self._owner_ptr) |
81447b5b | 72 | |
81447b5b | 73 | |
78288f58 | 74 | # Python object that owns a reference to a Babeltrace object. |
e57959f4 | 75 | class _SharedObject(_BaseObject, abc.ABC): |
78288f58 SM |
76 | # Get a new reference on ptr. |
77 | # | |
78 | # This must be implemented by subclasses to work correctly with a pointer | |
79 | # of the native type they wrap. | |
811644b8 | 80 | |
78288f58 | 81 | @staticmethod |
e57959f4 | 82 | @abc.abstractmethod |
78288f58 SM |
83 | def _get_ref(ptr): |
84 | raise NotImplementedError | |
811644b8 | 85 | |
78288f58 SM |
86 | # Put a reference on ptr. |
87 | # | |
88 | # This must be implemented by subclasses to work correctly with a pointer | |
89 | # of the native type they wrap. | |
81447b5b | 90 | |
78288f58 | 91 | @staticmethod |
e57959f4 | 92 | @abc.abstractmethod |
78288f58 SM |
93 | def _put_ref(ptr): |
94 | raise NotImplementedError | |
81447b5b | 95 | |
78288f58 SM |
96 | # Create a _SharedObject from an existing reference. |
97 | # | |
98 | # This assumes that the caller owns a reference to the Babeltrace object | |
99 | # and transfers this ownership to the newly created Python object. | |
81447b5b | 100 | |
78288f58 SM |
101 | @classmethod |
102 | def _create_from_ptr(cls, ptr_owned): | |
103 | obj = cls.__new__(cls) | |
104 | obj._ptr = ptr_owned | |
105 | return obj | |
81447b5b | 106 | |
78288f58 SM |
107 | # Like _create_from_ptr, but acquire a new reference rather than |
108 | # stealing the caller's reference. | |
109 | ||
110 | @classmethod | |
111 | def _create_from_ptr_and_get_ref(cls, ptr): | |
112 | obj = cls._create_from_ptr(ptr) | |
113 | cls._get_ref(obj._ptr) | |
114 | return obj | |
115 | ||
116 | def __del__(self): | |
117 | self._put_ref(self._ptr) |