Simulating Garbage Collection in Python
Python's automatic garbage collection is a powerful feature, but understanding how it works can be insightful. This challenge asks you to simulate a simplified version of garbage collection, focusing on reference counting, to gain a deeper appreciation for memory management. You'll be creating a custom object manager that tracks object creation and deletion based on reference counts.
Problem Description
You are tasked with implementing a basic object manager that mimics a simplified form of garbage collection using reference counting. The manager should track objects created and automatically delete them when their reference count reaches zero. The core functionality involves creating objects, incrementing/decrementing their reference counts, and triggering the deletion process when an object is no longer referenced. This exercise will help you understand the fundamental principles behind garbage collection and how reference counting plays a crucial role.
What needs to be achieved:
- Object Creation: A function to create new objects and register them with the manager.
- Reference Counting: Methods to increment and decrement the reference count of an object.
- Garbage Collection: A function that iterates through the managed objects and deletes those with a reference count of zero.
- Object Deletion: A mechanism to actually remove the object from the manager's tracking.
Key Requirements:
- The manager should maintain a dictionary of objects, where the key is the object itself and the value is its reference count.
- Incrementing the reference count should increase the count in the dictionary.
- Decrementing the reference count should decrease the count in the dictionary.
- When the reference count reaches zero, the object should be deleted from the dictionary, and a deletion event should be logged (printed to the console).
- The garbage collection function should iterate through the dictionary and delete objects with a reference count of zero.
Expected Behavior:
The manager should correctly track object references and delete objects when they are no longer needed. The console should display messages indicating when objects are created, their reference counts change, and when they are deleted.
Edge Cases to Consider:
- Deleting an object that has already been deleted.
- Handling multiple references to the same object.
- The garbage collection function should not raise errors if an object has already been deleted.
Examples
Example 1:
Input:
- Create object 'a'
- Increment reference count of 'a'
- Create object 'b'
- Decrement reference count of 'a'
- Decrement reference count of 'b'
- Call garbage collection
Output:
- "Object 'a' created with reference count 1"
- "Object 'b' created with reference count 1"
- "Reference count of 'a' incremented to 2"
- "Reference count of 'a' decremented to 1"
- "Reference count of 'b' decremented to 0"
- "Object 'b' deleted"
- "Reference count of 'a' decremented to 0"
- "Object 'a' deleted"
Explanation: Object 'a' and 'b' are created. The reference count of 'a' is incremented and decremented. 'b' is immediately deleted due to its reference count reaching zero. Finally, 'a' is deleted.
Example 2:
Input:
- Create object 'c'
- Create object 'd'
- Increment reference count of 'c'
- Decrement reference count of 'c'
- Call garbage collection
Output:
- "Object 'c' created with reference count 1"
- "Object 'd' created with reference count 1"
- "Reference count of 'c' incremented to 2"
- "Reference count of 'c' decremented to 1"
- "Reference count of 'd' decremented to 0"
- "Object 'd' deleted"
Explanation: 'c' and 'd' are created. The reference count of 'c' is incremented and decremented. 'd' is deleted because its reference count reaches zero.
Example 3: (Edge Case)
Input:
- Create object 'e'
- Decrement reference count of 'e' (twice)
- Call garbage collection
Output:
- "Object 'e' created with reference count 1"
- "Reference count of 'e' decremented to 0"
- "Object 'e' deleted"
- "Reference count of 'e' decremented to -1" (This should not cause an error)
- No further deletion messages.
Explanation: 'e' is created. Its reference count is decremented twice. The first decrement deletes it. The second decrement attempts to decrement a deleted object, but the manager should handle this gracefully without errors.
Constraints
- The number of objects created will be less than or equal to 1000.
- The object itself can be any Python object (e.g., integer, string, list).
- The garbage collection function should complete within 1 second.
- The manager should not leak memory.
Notes
- You don't need to implement a full-fledged garbage collector. This is a simplified simulation focusing on reference counting.
- Consider using a dictionary to store the objects and their reference counts.
- Think about how to handle the case where an object is deleted multiple times. You can ignore subsequent deletion attempts.
- The "deletion" process simply involves removing the object from the manager's dictionary and printing a message to the console. You don't need to actually deallocate the memory occupied by the object (Python handles that automatically).
- Focus on the logic of reference counting and garbage collection, not on complex memory management techniques.