| 178 | |
| 179 | |
| 180 | def test_rvalue_ref() -> None: |
| 181 | use_count = tvm_ffi.get_global_func("testing.object_use_count") |
| 182 | |
| 183 | def callback(x: Any, expected_count: int) -> Any: |
| 184 | # The use count of TVM FFI objects is decremented as part of |
| 185 | # `ObjectRef.__del__`, which runs when the Python object is |
| 186 | # destructed. However, Python object destruction is not |
| 187 | # deterministic, and even CPython's reference-counting is |
| 188 | # considered an implementation detail. Therefore, to ensure |
| 189 | # correct results from this test, `gc.collect()` must be |
| 190 | # explicitly called. |
| 191 | gc.collect() |
| 192 | assert expected_count == use_count(x) |
| 193 | return x._move() |
| 194 | |
| 195 | f = tvm_ffi.convert(callback) |
| 196 | |
| 197 | def check0() -> None: |
| 198 | x = tvm_ffi.convert([1, 2]) |
| 199 | assert use_count(x) == 1 |
| 200 | f(x, 2) |
| 201 | f(x._move(), 1) |
| 202 | assert x.__ctypes_handle__().value is None |
| 203 | |
| 204 | def check1() -> None: |
| 205 | x = tvm_ffi.convert([1, 2]) |
| 206 | assert use_count(x) == 1 |
| 207 | y = f(x, 2) |
| 208 | f(x._move(), 2) |
| 209 | assert x.__ctypes_handle__().value is None |
| 210 | assert y.__ctypes_handle__().value is not None |
| 211 | |
| 212 | check0() |
| 213 | check1() |
| 214 | |
| 215 | |
| 216 | def test_echo_with_opaque_object() -> None: |