| 127 | /// End deallocation and process any deferred objects if at outermost level. |
| 128 | #[inline] |
| 129 | pub(super) unsafe fn end() { |
| 130 | let depth = DEALLOC_DEPTH.with(|d| { |
| 131 | let depth = d.get(); |
| 132 | debug_assert!(depth > 0, "trashcan::end called without matching begin"); |
| 133 | let depth = depth - 1; |
| 134 | d.set(depth); |
| 135 | depth |
| 136 | }); |
| 137 | if depth == 0 { |
| 138 | // Process deferred deallocations iteratively |
| 139 | loop { |
| 140 | let next = DEALLOC_QUEUE.with(|q| { |
| 141 | let mut queue = q.take(); |
| 142 | let item = queue.pop(); |
| 143 | q.set(queue); |
| 144 | item |
| 145 | }); |
| 146 | if let Some((obj, dealloc)) = next { |
| 147 | unsafe { dealloc(obj) }; |
| 148 | } else { |
| 149 | break; |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | /// Default dealloc: handles __del__, weakref clearing, tp_clear, and memory free. |