@@ -16,6 +16,10 @@ module Safe
1616 # Uses TracePoint to track in-flight method calls and detect concurrent access.
1717 class Monitor
1818 ASYNC_SAFE = true
19+
20+ IS_A = Kernel . instance_method ( :is_a? )
21+ FROZEN = Kernel . instance_method ( :frozen? )
22+ CLASS = Kernel . instance_method ( :class )
1923
2024 # Initialize a new concurrency monitor.
2125 def initialize
@@ -66,15 +70,15 @@ def transfer(*objects)
6670 object = trace_point . self
6771
6872 # Skip tracking class/module methods:
69- return if object . is_a? ( Module )
73+ return if IS_A . bind_call ( object , Module )
7074
7175 # Skip frozen objects:
72- return if object . frozen?
76+ return if FROZEN . bind_call ( object )
7377
7478 method = trace_point . method_id
7579
7680 # Check the object's actual class:
77- klass = object . class
81+ klass = CLASS . bind_call ( object )
7882
7983 # Check if the class or method is marked as async-safe:
8084 # Returns: true (skip), false (simple tracking), or Symbol (guard-based tracking)
@@ -140,15 +144,15 @@ def transfer(*objects)
140144 object = trace_point . self
141145
142146 # Skip tracking class/module methods:
143- return if object . is_a? ( Module )
147+ return if IS_A . bind_call ( object , Module )
144148
145149 # Skip frozen objects:
146- return if object . frozen?
150+ return if FROZEN . bind_call ( object )
147151
148152 method = trace_point . method_id
149153
150154 # Check the object's actual class:
151- klass = object . class
155+ klass = CLASS . bind_call ( object )
152156
153157 # Check if the class or method is marked as async-safe:
154158 safe = klass . async_safe? ( method )
@@ -159,6 +163,9 @@ def transfer(*objects)
159163 @mutex . synchronize do
160164 entry = @guards [ object ]
161165
166+ # No guard held, nothing to release:
167+ return unless entry
168+
162169 if safe == false
163170 # Simple tracking (single guard)
164171 # Release if this fiber holds it
0 commit comments