1
1
#[ cfg( feature = "host" ) ]
2
- use std:: { borrow:: BorrowMut , future:: Future , future:: IntoFuture , marker:: PhantomData , task:: Poll } ;
2
+ use std:: {
3
+ borrow:: BorrowMut , future:: Future , future:: IntoFuture , marker:: PhantomData , ptr:: NonNull ,
4
+ task:: Poll ,
5
+ } ;
3
6
4
7
#[ cfg( feature = "host" ) ]
5
8
use rustacuda:: {
@@ -272,7 +275,7 @@ impl<'a, 'stream, T: BorrowMut<C::Completed>, C: Completion<T>> Async<'a, 'strea
272
275
}
273
276
}
274
277
275
- pub const fn as_ref ( & self ) -> AsyncProj < ' _ , ' stream , & T > {
278
+ pub fn as_ref ( & self ) -> AsyncProj < ' _ , ' stream , & T > {
276
279
// Safety: this projection captures this async
277
280
unsafe { AsyncProj :: new ( & self . value , None ) }
278
281
}
@@ -327,7 +330,7 @@ impl<'a, 'stream, T: BorrowMut<C::Completed>, C: Completion<T>> Async<'a, 'strea
327
330
(
328
331
this. stream ,
329
332
std:: ptr:: read ( & this. value ) ,
330
- ( std:: ptr:: read ( & this. status ) ) ,
333
+ std:: ptr:: read ( & this. status ) ,
331
334
)
332
335
}
333
336
}
@@ -478,7 +481,19 @@ pub struct AsyncProj<'a, 'stream, T: 'a> {
478
481
_capture : PhantomData < & ' a ( ) > ,
479
482
_stream : PhantomData < Stream < ' stream > > ,
480
483
value : T ,
481
- use_callback : Option < Box < dyn FnMut ( ) -> CudaResult < ( ) > + ' a > > ,
484
+ use_callback : Option < NonNull < dyn FnMut ( ) -> CudaResult < ( ) > + ' a > > ,
485
+ }
486
+
487
+ #[ cfg( feature = "host" ) ]
488
+ unsafe impl < #[ may_dangle] ' a , ' stream , T : ' a > Drop for AsyncProj < ' a , ' stream , T > {
489
+ fn drop ( & mut self ) {
490
+ if let Some ( use_callback) = self . use_callback . take ( ) {
491
+ let layout = unsafe { std:: alloc:: Layout :: for_value_raw ( use_callback. as_ptr ( ) ) } ;
492
+ if layout. size ( ) != 0 {
493
+ unsafe { std:: alloc:: dealloc ( use_callback. as_ptr ( ) . cast ( ) , layout) } ;
494
+ }
495
+ }
496
+ }
482
497
}
483
498
484
499
#[ cfg( feature = "host" ) ]
@@ -489,15 +504,16 @@ impl<'a, 'stream, T: 'a> AsyncProj<'a, 'stream, T> {
489
504
/// This projection must either capture an existing [`Async`] or come from
490
505
/// a source that ensures that the projected value can never (async) move
491
506
/// to a different [`Stream`].
492
- pub ( crate ) const unsafe fn new (
507
+ pub ( crate ) unsafe fn new (
493
508
value : T ,
494
509
use_callback : Option < Box < dyn FnMut ( ) -> CudaResult < ( ) > + ' a > > ,
495
510
) -> Self {
496
511
Self {
497
512
_capture : PhantomData :: < & ' a ( ) > ,
498
513
_stream : PhantomData :: < Stream < ' stream > > ,
499
514
value,
500
- use_callback,
515
+ use_callback : use_callback
516
+ . map ( |use_callback| unsafe { NonNull :: new_unchecked ( Box :: into_raw ( use_callback) ) } ) ,
501
517
}
502
518
}
503
519
@@ -511,7 +527,8 @@ impl<'a, 'stream, T: 'a> AsyncProj<'a, 'stream, T> {
511
527
/// computation out of smaller ones that have all been submitted to the
512
528
/// same [`Stream`].
513
529
pub ( crate ) unsafe fn unwrap_unchecked ( self ) -> T {
514
- self . value
530
+ let ( value, _use_callback) = self . unwrap_unchecked_with_use ( ) ;
531
+ value
515
532
}
516
533
517
534
#[ allow( clippy:: type_complexity) ]
@@ -527,7 +544,21 @@ impl<'a, 'stream, T: 'a> AsyncProj<'a, 'stream, T> {
527
544
pub ( crate ) unsafe fn unwrap_unchecked_with_use (
528
545
self ,
529
546
) -> ( T , Option < Box < dyn FnMut ( ) -> CudaResult < ( ) > + ' a > > ) {
530
- ( self . value , self . use_callback )
547
+ let this = std:: mem:: ManuallyDrop :: new ( self ) ;
548
+
549
+ // Safety: we destructure self into its droppable components,
550
+ // value and use_callback, without dropping self itself
551
+ let ( value, use_callback) = unsafe {
552
+ (
553
+ std:: ptr:: read ( & this. value ) ,
554
+ std:: ptr:: read ( & this. use_callback ) ,
555
+ )
556
+ } ;
557
+
558
+ (
559
+ value,
560
+ use_callback. map ( |use_callback| Box :: from_raw ( use_callback. as_ptr ( ) ) ) ,
561
+ )
531
562
}
532
563
}
533
564
@@ -556,16 +587,20 @@ impl<'a, 'stream, T: 'a> AsyncProj<'a, 'stream, T> {
556
587
_stream : PhantomData :: < Stream < ' stream > > ,
557
588
value : & mut self . value ,
558
589
use_callback : self . use_callback . as_mut ( ) . map ( |use_callback| {
590
+ let use_callback: & mut dyn FnMut ( ) -> CudaResult < ( ) > =
591
+ unsafe { & mut * use_callback. as_ptr ( ) } ;
559
592
let use_callback: Box < dyn FnMut ( ) -> CudaResult < ( ) > > = Box :: new ( use_callback) ;
560
- use_callback
593
+ unsafe { NonNull :: new_unchecked ( Box :: into_raw ( use_callback) ) }
561
594
} ) ,
562
595
}
563
596
}
564
597
565
598
pub ( crate ) fn record_mut_use ( & mut self ) -> CudaResult < ( ) > {
566
- self . use_callback
567
- . as_mut ( )
568
- . map_or ( Ok ( ( ) ) , |use_callback| use_callback ( ) )
599
+ self . use_callback . as_mut ( ) . map_or ( Ok ( ( ) ) , |use_callback| {
600
+ let use_callback: & mut dyn FnMut ( ) -> CudaResult < ( ) > =
601
+ unsafe { & mut * use_callback. as_ptr ( ) } ;
602
+ use_callback ( )
603
+ } )
569
604
}
570
605
}
571
606
@@ -623,8 +658,10 @@ impl<'a, 'stream, T: 'a> AsyncProj<'a, 'stream, &'a mut T> {
623
658
_stream : PhantomData :: < Stream < ' stream > > ,
624
659
value : self . value ,
625
660
use_callback : self . use_callback . as_mut ( ) . map ( |use_callback| {
661
+ let use_callback: & mut dyn FnMut ( ) -> CudaResult < ( ) > =
662
+ unsafe { & mut * use_callback. as_ptr ( ) } ;
626
663
let use_callback: Box < dyn FnMut ( ) -> CudaResult < ( ) > > = Box :: new ( use_callback) ;
627
- use_callback
664
+ unsafe { NonNull :: new_unchecked ( Box :: into_raw ( use_callback) ) }
628
665
} ) ,
629
666
}
630
667
}
0 commit comments