@@ -96,6 +96,7 @@ unsafe impl<SK> Sync for CustomSlotSupplier<SK> {}
9696
9797type CustomReserveSlotCallback =
9898 unsafe extern "C" fn ( ctx : SlotReserveCtx , sender : * mut libc:: c_void ) ;
99+ type CustomCancelReserveCallback = unsafe extern "C" fn ( token_source : * mut libc:: c_void ) ;
99100/// Must return C#-tracked id for the permit. A zero value means no permit was reserved.
100101type CustomTryReserveSlotCallback = unsafe extern "C" fn ( ctx : SlotReserveCtx ) -> usize ;
101102type CustomMarkSlotUsedCallback = unsafe extern "C" fn ( ctx : SlotMarkUsedCtx ) ;
@@ -108,6 +109,7 @@ pub struct CustomSlotSupplierCallbacksImpl(*const CustomSlotSupplierCallbacks);
108109#[ repr( C ) ]
109110pub struct CustomSlotSupplierCallbacks {
110111 reserve : CustomReserveSlotCallback ,
112+ cancel_reserve : CustomCancelReserveCallback ,
111113 try_reserve : CustomTryReserveSlotCallback ,
112114 mark_used : CustomMarkSlotUsedCallback ,
113115 release : CustomReleaseSlotCallback ,
@@ -139,6 +141,8 @@ pub struct SlotReserveCtx {
139141 worker_identity : ByteArrayRef ,
140142 worker_build_id : ByteArrayRef ,
141143 is_sticky : bool ,
144+ // The C# side will store a pointer here to the cancellation token source
145+ token_src : * mut libc:: c_void ,
142146}
143147
144148#[ repr( C ) ]
@@ -169,6 +173,21 @@ pub struct SlotReleaseCtx {
169173 slot_permit : usize ,
170174}
171175
176+ struct CancelReserveGuard {
177+ token_src : * mut libc:: c_void ,
178+ callback : CustomCancelReserveCallback ,
179+ }
180+ impl Drop for CancelReserveGuard {
181+ fn drop ( & mut self ) {
182+ if !self . token_src . is_null ( ) {
183+ unsafe {
184+ ( self . callback ) ( self . token_src ) ;
185+ }
186+ }
187+ }
188+ }
189+ unsafe impl Send for CancelReserveGuard { }
190+
172191#[ async_trait:: async_trait]
173192impl < SK : SlotKind + Send + Sync > temporal_sdk_core_api:: worker:: SlotSupplier
174193 for CustomSlotSupplier < SK >
@@ -180,10 +199,13 @@ impl<SK: SlotKind + Send + Sync> temporal_sdk_core_api::worker::SlotSupplier
180199 let ctx = Self :: convert_reserve_ctx ( ctx) ;
181200 let tx = Box :: into_raw ( Box :: new ( tx) ) as * mut libc:: c_void ;
182201 unsafe {
202+ let _drop_guard = CancelReserveGuard {
203+ token_src : ctx. token_src ,
204+ callback : ( * self . inner . 0 ) . cancel_reserve ,
205+ } ;
183206 ( ( * self . inner . 0 ) . reserve ) ( ctx, tx) ;
207+ rx. await . expect ( "reserve channel is not closed" )
184208 }
185- let r = rx. await . expect ( "reserve channel is not closed" ) ;
186- r
187209 }
188210
189211 fn try_reserve_slot ( & self , ctx : & dyn SlotReservationContext ) -> Option < SlotSupplierPermit > {
@@ -244,6 +266,7 @@ impl<SK: SlotKind + Send + Sync> CustomSlotSupplier<SK> {
244266 worker_identity : ctx. worker_identity ( ) . into ( ) ,
245267 worker_build_id : ctx. worker_build_id ( ) . into ( ) ,
246268 is_sticky : ctx. is_sticky ( ) ,
269+ token_src : std:: ptr:: null_mut ( ) ,
247270 }
248271 }
249272
@@ -738,6 +761,16 @@ pub extern "C" fn complete_async_reserve(sender: *mut libc::c_void, permit_id: u
738761 }
739762}
740763
764+ #[ no_mangle]
765+ pub unsafe extern "C" fn set_reserve_cancel_target (
766+ ctx : * mut SlotReserveCtx ,
767+ token_ptr : * mut libc:: c_void ,
768+ ) {
769+ if let Some ( ctx) = ctx. as_mut ( ) {
770+ ctx. token_src = token_ptr;
771+ }
772+ }
773+
741774impl TryFrom < & WorkerOptions > for temporal_sdk_core:: WorkerConfig {
742775 type Error = anyhow:: Error ;
743776
0 commit comments