module TrackOpenInstances

Mixin to track instances of a class that require explicit cleanup

This module provides a mechanism to track instances of classes that need to be explicitly closed or cleaned up. It maintains a list of all instances created and allows checking for any unclosed instances, which can help in identifying resource leaks.

@example Basic Usage

class ManagedFile
  include TrackOpenInstances

  attr_reader :path

  def initialize(path)
    @path = path
    # Simulate opening the file
    puts "Opening file: #{path}"
    # Register the instance for tracking
    self.class.add_open_instance(self)
  end

  # Implement the close logic specific to the resource
  def close
    # Simulate closing the file
    puts "Closing file: #{path}"
    # Remove the instance from tracking
    self.class.remove_open_instance(self)
  end
end

file1 = ManagedFile.new('/tmp/file1.txt')
file2 = ManagedFile.new('/tmp/file2.txt')

puts ManagedFile.open_instances.count #=> 2
puts ManagedFile.open_instances.keys.inspect #=> [#<ManagedFile:...>, #<ManagedFile:...>]

file1.close

puts ManagedFile.open_instances.count #=> 1
puts ManagedFile.open_instances.keys.inspect #=> [#<ManagedFile:...>]

# In a test suite's teardown, you might use:
# ManagedFile.assert_no_open_instances # This would raise if file2 wasn't closed

file2.close
ManagedFile.assert_no_open_instances # This will now pass

@api public

Constants

VERSION

The last released version of this gem

Public Class Methods

included(base) click to toggle source

Ruby hook executed when this module is included in a base class

Sets up the necessary class instance variables and extends the base class with ClassMethods.

@param base [Class] The class including this module

@return [void]

@api private

# File lib/track_open_instances.rb, line 91
def self.included(base)
  base.extend(ClassMethods)
  # @!attribute [rw] open_instances
  #   Internal storage for all tracked instances
  #   @return [Hash{Object => OpenInstance}] The list of currently tracked instances
  base.instance_variable_set(:@open_instances, {}.compare_by_identity)
  # @!visibility private
  # @!attribute [r] open_instances_mutex
  #   Mutex to ensure thread-safe access to the open_instances hash
  base.instance_variable_set(:@open_instances_mutex, Thread::Mutex.new)
end