Class: Spotify::ManagedPointer Private

Inherits:
FFI::AutoPointer
  • Object
show all
Extended by:
TypeSafety
Defined in:
lib/spotify/managed_pointer.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Note:

The default ManagedPointer does not retain its pointer after initialization, but provides a class that does through ManagedPointer.retaining_class. This is better as it allows you to err on the side of segfaulting, instead of leaking memory.

An autopointer base class for Spotify pointers.

It contains a default implementation for release, retain, and a default constructor. When the underlying pointer is garbage collected, the pointer is released automatically.

This class is never instantiated; instead you’ll be dealing with any of it’s subclasses.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TypeSafety

to_native, type_class

Class Method Details

.from_native(pointer, ctx) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Casts all null pointers to nil.


59
60
61
62
# File 'lib/spotify/managed_pointer.rb', line 59

def from_native(pointer, ctx)
  value = super
  value unless value.null?
end

.release(pointer) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Schedules given pointer for release.


24
25
26
27
28
29
30
31
32
33
34
# File 'lib/spotify/managed_pointer.rb', line 24

def release(pointer)
  unless pointer.null?
    # this is to circumvent the type protection, and wrap the pointer
    # with the correct type for later freeing
    freeable = type_class.new(pointer)
    # and this is to not make this pointer trigger release again
    freeable.autorelease = false

    Spotify.performer.async { freeable.free }
  end
end

.retain(pointer) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retains the given pointer if it is not null.

This method derives the retain method from the class name.


41
42
43
44
45
46
# File 'lib/spotify/managed_pointer.rb', line 41

def retain(pointer)
  unless pointer.null?
    Spotify.log "Spotify.#{type}_add_ref(#{pointer.inspect})"
    Spotify.public_send(:"#{type}_add_ref", pointer)
  end
end

.retaining_classself

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retaining class is needed for the functions that return a pointer that does not have its reference count increased. This class is a subclass of the ManagedPointer, and should behave the same in all circumstances except for during initialization.

This dynamic method is needed to DRY the pointers up. We have about ten subclasses of ManagedPointer; all of them need a subclass that retains its pointer on initialization. We could create one manually for each Album, Artist, Track, and so on, but that would be annoying.


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/spotify/managed_pointer.rb', line 81

def retaining_class
  if defined?(self::Retaining)
    self::Retaining
  else
    subclass = Class.new(self) do
      class << self
        def type
          superclass.type
        end

        protected

        def type_class
          superclass
        end
      end

      alias_method :super_initialize, :initialize
      def initialize(*args, &block)
        super_initialize(*args, &block)
        self.class.retain(self)
      end
    end

    const_set("Retaining", subclass)
  end
end

.sizeInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns size of the native type, defined for JRuby.


66
67
68
# File 'lib/spotify/managed_pointer.rb', line 66

def size
  FFI.type_size(:pointer)
end

.to_native(value, ctx) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Makes all ManagedPointers typesafe in the sense that they will raise an argument error on any value that is not of the same kind.


50
51
52
53
54
55
56
# File 'lib/spotify/managed_pointer.rb', line 50

def to_native(value, ctx)
  if value.nil? or value.null?
    raise TypeError, "#{name} pointers cannot be null, was #{value.inspect}"
  else
    super
  end
end

.typeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Retrieves the normalized and downcased name of self, so for Spotify::Album we’ll receive just “album”.


111
112
113
# File 'lib/spotify/managed_pointer.rb', line 111

def type
  name.split('::')[-1].downcase
end

Instance Method Details

#freeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Does NOT call self.class.release.

Note:

This is NOT idempotent.

Immediately releases the underlying pointer.


125
126
127
128
129
130
131
# File 'lib/spotify/managed_pointer.rb', line 125

def free
  unless null?
    self.autorelease = false
    Spotify.log "Spotify.#{type}_release(#{inspect})"
    Spotify.public_send(:"#{type}_release", self)
  end
end

#inspectString Also known as: to_s

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns string representation of self.


134
135
136
# File 'lib/spotify/managed_pointer.rb', line 134

def inspect
  "#<#{self.class} address=0x%x>" % address
end

#typeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

See Also:

  • Spotify::ManagedPointer.selfself.classself.class.type

117
118
119
# File 'lib/spotify/managed_pointer.rb', line 117

def type
  self.class.type
end