Module: TrackOpenInstances::ClassMethods

Defined in:
lib/track_open_instances.rb

Overview

Contains class-level methods added to classes including TrackOpenInstances

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#open_instancesHash{Object => OpenInstance} (readonly)

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.

Direct access to the internal list of tracked instances

Note: This returns all instances ever tracked unless explicitly removed. Use open_instances for checking leaks. Direct use is uncommon.

Examples:

# Assuming MyResource includes TrackOpenInstances
res1 = MyResource.new
res2 = MyResource.new
res1.close
MyResource.open_instances.keys #=> [#<MyResource... object_id=res2>] (after res1 removed)

Returns:

  • (Hash{Object => OpenInstance})

    The raw list of currently tracked instances



122
123
124
125
126
# File 'lib/track_open_instances.rb', line 122

def open_instances
  @open_instances_mutex.synchronize do
    @open_instances.dup.freeze
  end
end

Instance Method Details

#add_open_instance(instance)

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.

This method returns an undefined value.

Adds an instance to the tracking list (thread-safe)

Typically called automatically by the instance's initialize method.

Parameters:

  • instance (Object)

    The instance to add



137
138
139
140
141
# File 'lib/track_open_instances.rb', line 137

def add_open_instance(instance)
  @open_instances_mutex.synchronize do
    @open_instances[instance] = OpenInstance.new(instance, caller_locations(3))
  end
end

#assert_no_open_instances

This method returns an undefined value.

Asserts that no instances of the class remain unclosed

Commonly used in test suite teardown blocks to enure that all resources were released.

unclosed instances

Examples:

# In RSpec teardown (e.g., after(:each))
MyResource.assert_no_open_instances

Raises:

  • (RuntimeError)

    If any instances are found unclosed with a report of



249
250
251
252
# File 'lib/track_open_instances.rb', line 249

def assert_no_open_instances
  report = open_instances_report
  raise(report.to_s) if report
end

#open_instance_countInteger

The number of currently open instances

Examples:

res1 = MyResource.new
res2 = MyResource.new
MyResource.open_instance_count #=> 2

Returns:

  • (Integer)


169
170
171
172
173
# File 'lib/track_open_instances.rb', line 169

def open_instance_count
  @open_instances_mutex.synchronize do
    @open_instances.size
  end
end

#open_instances_reportString?

Generates a report string listing unclosed instances and their creation stacks

Useful for debugging resource leaks. Returns nil if no instances are unclosed.

Examples:

res = MyResource.new
puts MyResource.open_instances_report
There is 1 open MyResource instance(s):
- object_id=701
  Created at:
    (caller stack line 1)
    (caller stack line 2)\n..."

Returns:

  • (String, nil)

    A formatted report string or nil if none are open



191
192
193
194
195
196
197
198
199
200
# File 'lib/track_open_instances.rb', line 191

def open_instances_report
  @open_instances_mutex.synchronize do
    return nil if @open_instances.count.zero?

    String.new.tap do |report|
      report << open_instances_report_header
      report << open_instances_report_body
    end
  end
end

#open_instances_report_bodyString

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.

The body of the report detailing each open instance

Returns:

  • (String)


222
223
224
225
226
227
228
229
230
231
232
# File 'lib/track_open_instances.rb', line 222

def open_instances_report_body
  String.new.tap do |body|
    @open_instances.each do |instance, open_instance|
      body << " - object_id=#{instance.object_id}\n"
      body << "   Call stack when created:\n"
      open_instance.creation_stack.each do |location|
        body << "     #{location.path}:#{location.lineno}:in `#{location.label}'\n"
      end
    end
  end
end

#open_instances_report_headerString

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.

The header string for the report

Returns:

  • (String)


208
209
210
211
212
213
214
# File 'lib/track_open_instances.rb', line 208

def open_instances_report_header
  count = @open_instances.count
  class_name = name || 'anonymous class'

  "There #{count == 1 ? 'is' : 'are'} #{count} " \
    "open #{class_name} instance#{count == 1 ? '' : 's'}:\n"
end

#remove_open_instance(instance)

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.

This method returns an undefined value.

Removes an instance from the tracking list (thread-safe)

Typically called automatically by the instance's close method.

Parameters:

  • instance (Object)

    The instance to remove



152
153
154
155
156
# File 'lib/track_open_instances.rb', line 152

def remove_open_instance(instance)
  @open_instances_mutex.synchronize do
    @open_instances.delete(instance)
  end
end