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 | 47 | class _UniqueObject(_BaseObject): |
78288f58 SM |
48 | # Create a _UniqueObject. |
49 | # | |
50 | # - ptr: SWIG Object, pointer to the unique object. | |
51 | # - owner_ptr: SWIG Object, pointer to the owner of the unique | |
52 | # object. A new reference is acquired. | |
53 | # - owner_get_ref: Callback to get a reference on the owner | |
54 | # - owner_put_ref: Callback to put a reference on the owner. | |
55 | ||
81447b5b | 56 | @classmethod |
cfbd7cf3 | 57 | def _create_from_ptr_and_get_ref(cls, ptr, owner_ptr, owner_get_ref, owner_put_ref): |
81447b5b | 58 | obj = cls.__new__(cls) |
2ae9f48c | 59 | |
81447b5b | 60 | obj._ptr = ptr |
78288f58 | 61 | obj._owner_ptr = owner_ptr |
2ae9f48c | 62 | obj._owner_get_ref = owner_get_ref |
78288f58 | 63 | obj._owner_put_ref = owner_put_ref |
2ae9f48c SM |
64 | |
65 | obj._owner_get_ref(obj._owner_ptr) | |
66 | ||
81447b5b PP |
67 | return obj |
68 | ||
81447b5b | 69 | def __del__(self): |
78288f58 | 70 | self._owner_put_ref(self._owner_ptr) |
81447b5b | 71 | |
81447b5b | 72 | |
78288f58 | 73 | # Python object that owns a reference to a Babeltrace object. |
e57959f4 | 74 | class _SharedObject(_BaseObject, abc.ABC): |
78288f58 SM |
75 | # Get a new reference on ptr. |
76 | # | |
77 | # This must be implemented by subclasses to work correctly with a pointer | |
78 | # of the native type they wrap. | |
811644b8 | 79 | |
78288f58 | 80 | @staticmethod |
e57959f4 | 81 | @abc.abstractmethod |
78288f58 SM |
82 | def _get_ref(ptr): |
83 | raise NotImplementedError | |
811644b8 | 84 | |
78288f58 SM |
85 | # Put a reference on ptr. |
86 | # | |
87 | # This must be implemented by subclasses to work correctly with a pointer | |
88 | # of the native type they wrap. | |
81447b5b | 89 | |
78288f58 | 90 | @staticmethod |
e57959f4 | 91 | @abc.abstractmethod |
78288f58 SM |
92 | def _put_ref(ptr): |
93 | raise NotImplementedError | |
81447b5b | 94 | |
78288f58 SM |
95 | # Create a _SharedObject from an existing reference. |
96 | # | |
97 | # This assumes that the caller owns a reference to the Babeltrace object | |
98 | # and transfers this ownership to the newly created Python object. | |
81447b5b | 99 | |
78288f58 SM |
100 | @classmethod |
101 | def _create_from_ptr(cls, ptr_owned): | |
102 | obj = cls.__new__(cls) | |
103 | obj._ptr = ptr_owned | |
104 | return obj | |
81447b5b | 105 | |
78288f58 SM |
106 | # Like _create_from_ptr, but acquire a new reference rather than |
107 | # stealing the caller's reference. | |
108 | ||
109 | @classmethod | |
110 | def _create_from_ptr_and_get_ref(cls, ptr): | |
111 | obj = cls._create_from_ptr(ptr) | |
112 | cls._get_ref(obj._ptr) | |
113 | return obj | |
114 | ||
115 | def __del__(self): | |
116 | self._put_ref(self._ptr) |