X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bindings%2Fpython%2Fbt2%2Fbt2%2Fobject.py;fp=bindings%2Fpython%2Fbt2%2Fbt2%2Fobject.py;h=05c6deb75b63ac345aeabaa072ae63f836d83de5;hb=78288f581343ec033cc38898777fe43a02380719;hp=774027cbdc6685105b72bb1154d3992eb385fe5d;hpb=fca9fd7dfa103b71eb02ebc67ec92dd3f7d7b10d;p=babeltrace.git diff --git a/bindings/python/bt2/bt2/object.py b/bindings/python/bt2/bt2/object.py index 774027cb..05c6deb7 100644 --- a/bindings/python/bt2/bt2/object.py +++ b/bindings/python/bt2/bt2/object.py @@ -20,11 +20,16 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from bt2 import native_bt -import abc +class _BaseObject: + # Ensure that the object always has _ptr set, even if it throws during + # construction. + + def __new__(cls, *args, **kwargs): + obj = super().__new__(cls) + obj._ptr = None + return obj -class _Object: def __init__(self, ptr): self._ptr = ptr @@ -32,50 +37,91 @@ class _Object: def addr(self): return int(self._ptr) + def __repr__(self): + return '<{}.{} object @ {}>'.format(self.__class__.__module__, + self.__class__.__name__, + hex(self.addr)) + + def __copy__(self): + raise NotImplementedError + + def __deepcopy__(self, memo): + raise NotImplementedError + + +# A Python object that is itself not refcounted, but is wholly owned by an +# object that is itself refcounted (a _SharedObject). A Babeltrace unique +# object gets destroyed once its owner gets destroyed (its refcount drops to +# 0). +# +# In the Python bindings, to avoid having to deal with issues with the lifetime +# of unique objects, we make it so acquiring a reference on a unique object +# acquires a reference on its owner. + +class _UniqueObject(_BaseObject): + + # Create a _UniqueObject. + # + # - ptr: SWIG Object, pointer to the unique object. + # - owner_ptr: SWIG Object, pointer to the owner of the unique + # object. A new reference is acquired. + # - owner_get_ref: Callback to get a reference on the owner + # - owner_put_ref: Callback to put a reference on the owner. + @classmethod - def _create_from_ptr(cls, ptr): + def _create_from_ptr_and_get_ref(cls, ptr, owner_ptr, + owner_get_ref, owner_put_ref): obj = cls.__new__(cls) obj._ptr = ptr + obj._owner_ptr = owner_ptr + obj._owner_put_ref = owner_put_ref + owner_get_ref(obj._owner_ptr) return obj - def _get(self): - native_bt.get(self._ptr) - def __del__(self): - ptr = getattr(self, '_ptr', None) - native_bt.put(ptr) - self._ptr = None + self._owner_put_ref(self._owner_ptr) - def __repr__(self): - return '<{}.{} object @ {}>'.format(self.__class__.__module__, - self.__class__.__name__, - hex(self.addr)) +# Python object that owns a reference to a Babeltrace object. +class _SharedObject(_BaseObject): -class _PrivateObject: - def __del__(self): - pub_ptr = getattr(self, '_pub_ptr', None) - native_bt.put(pub_ptr) - self._pub_ptr = None - super().__del__() + # Get a new reference on ptr. + # + # This must be implemented by subclasses to work correctly with a pointer + # of the native type they wrap. + @staticmethod + def _get_ref(ptr): + raise NotImplementedError -class _Freezable(metaclass=abc.ABCMeta): - @property - def is_frozen(self): - return self._is_frozen() + # Put a reference on ptr. + # + # This must be implemented by subclasses to work correctly with a pointer + # of the native type they wrap. - @property - def frozen(self): - return self.is_frozen + @staticmethod + def _put_ref(ptr): + raise NotImplementedError - def freeze(self): - self._freeze() + # Create a _SharedObject from an existing reference. + # + # This assumes that the caller owns a reference to the Babeltrace object + # and transfers this ownership to the newly created Python object. - @abc.abstractmethod - def _is_frozen(self): - pass + @classmethod + def _create_from_ptr(cls, ptr_owned): + obj = cls.__new__(cls) + obj._ptr = ptr_owned + return obj - @abc.abstractmethod - def _freeze(self): - pass + # Like _create_from_ptr, but acquire a new reference rather than + # stealing the caller's reference. + + @classmethod + def _create_from_ptr_and_get_ref(cls, ptr): + obj = cls._create_from_ptr(ptr) + cls._get_ref(obj._ptr) + return obj + + def __del__(self): + self._put_ref(self._ptr)