@@ -11,6 +11,8 @@ type ClosureGetDataFn = fn () voidptr
1111
1212type ClosureInitFn = fn ()
1313
14+ type ClosureDataDropFn = fn (voidptr )
15+
1416struct ClosurePage {
1517mut :
1618 next & ClosurePage = unsafe { nil }
@@ -21,6 +23,7 @@ struct ClosureLiveInfo {
2123mut :
2224 ctx voidptr
2325 owns_data bool
26+ drop_data voidptr
2427 generation u64
2528}
2629
@@ -354,11 +357,12 @@ fn closure_is_managed(exec_ptr voidptr) bool {
354357 return false
355358}
356359
357- fn closure_live_set (exec_ptr voidptr , data voidptr , owns_data bool ) {
360+ fn closure_live_set (exec_ptr voidptr , data voidptr , owns_data bool , drop_data voidptr ) {
358361 g_closure.next_generation++
359362 g_closure.live[exec_ptr] = ClosureLiveInfo{
360363 ctx: data
361364 owns_data: owns_data
365+ drop_data: drop_data
362366 generation: g_closure.next_generation
363367 }
364368}
@@ -482,6 +486,14 @@ fn closure_release_no_lock(exec_ptr voidptr, generation u64) bool {
482486 data := closure_slot_data (exec_ptr)
483487 _ := closure_live_delete (exec_ptr)
484488 if info.owns_data && ! isnil (data) {
489+ if ! isnil (info.drop_data) {
490+ drop_fn := ClosureDataDropFn (info.drop_data)
491+ // A user-defined drop can allocate another closure. Run it outside the
492+ // runtime mutex after removing this slot from the live map.
493+ closure_mtx_unlock_platform ()
494+ drop_fn (data)
495+ closure_mtx_lock_platform ()
496+ }
485497 unsafe { free (data) }
486498 }
487499 unsafe {
@@ -796,6 +808,12 @@ fn closure_create(func voidptr, data voidptr) voidptr {
796808// closure_create_with_data creates closure objects with explicit context ownership(INTERNAL COMPILER USE ONLY).
797809@[direct_array_access]
798810fn closure_create_with_data (func voidptr , data voidptr , owns_data bool ) voidptr {
811+ return closure_create_with_data_and_drop (func, data, owns_data, unsafe { nil })
812+ }
813+
814+ // closure_create_with_data_and_drop creates an owned closure context with type-aware cleanup(INTERNAL COMPILER USE ONLY).
815+ @[direct_array_access]
816+ fn closure_create_with_data_and_drop (func voidptr , data voidptr , owns_data bool , drop_data voidptr ) voidptr {
799817 closure_ensure_initialized ()
800818 closure_mtx_lock_platform ()
801819
@@ -837,7 +855,7 @@ fn closure_create_with_data(func voidptr, data voidptr, owns_data bool) voidptr
837855 p[1 ] = func // Target function to execute
838856 }
839857 }
840- closure_live_set (curr_closure, data, owns_data)
858+ closure_live_set (curr_closure, data, owns_data, drop_data )
841859 closure_lifetime_track_no_lock (curr_closure)
842860 closure_mtx_unlock_platform ()
843861
0 commit comments