1414
1515use std:: ffi:: c_void;
1616use std:: pin:: Pin ;
17- use std:: sync:: { Arc , Mutex } ;
17+ use std:: sync:: Mutex ;
1818use std:: task:: { Context , Poll , Waker } ;
1919
2020use crate :: ceph:: IoCtx ;
@@ -25,7 +25,7 @@ use crate::rados::{
2525 rados_completion_t,
2626} ;
2727
28- struct Completion {
28+ pub ( crate ) struct Completion < ' a > {
2929 inner : rados_completion_t ,
3030
3131 // Box to provide a stable address for completion_complete callback
@@ -34,15 +34,15 @@ struct Completion {
3434
3535 // A reference to the IOCtx is required to issue a cancel on
3636 // the operation if we are dropped before ready. This needs
37- // to be an Arc rather than a raw rados_ioctx_t because otherwise
37+ // to be a Rust reference rather than a raw rados_ioctx_t because otherwise
3838 // there would be nothing to stop the rados_ioctx_t being invalidated
3939 // during the lifetime of this Completion.
4040 // (AioCompletionImpl does hold a reference to IoCtxImpl for writes, but
4141 // not for reads.)
42- ioctx : Arc < IoCtx > ,
42+ ioctx : & ' a IoCtx ,
4343}
4444
45- unsafe impl Send for Completion { }
45+ unsafe impl Send for Completion < ' _ > { }
4646
4747#[ no_mangle]
4848pub extern "C" fn completion_complete ( _cb : rados_completion_t , arg : * mut c_void ) -> ( ) {
@@ -58,7 +58,7 @@ pub extern "C" fn completion_complete(_cb: rados_completion_t, arg: *mut c_void)
5858 }
5959}
6060
61- impl Drop for Completion {
61+ impl Drop for Completion < ' _ > {
6262 fn drop ( & mut self ) {
6363 // Ensure that after dropping the Completion, the AIO callback
6464 // will not be called on our dropped waker Box. Only necessary
@@ -67,7 +67,11 @@ impl Drop for Completion {
6767 let am_complete = unsafe { rados_aio_is_complete ( self . inner ) } != 0 ;
6868 if !am_complete {
6969 unsafe {
70- rados_aio_cancel ( self . ioctx . ioctx , self . inner ) ;
70+ let cancel_r = rados_aio_cancel ( self . ioctx . ioctx , self . inner ) ;
71+
72+ // It is unsound to proceed if the Objecter op is still in flight
73+ assert ! ( cancel_r == 0 || cancel_r == -libc:: ENOENT ) ;
74+
7175 rados_aio_wait_for_complete_and_cb ( self . inner ) ;
7276 }
7377 }
@@ -78,7 +82,7 @@ impl Drop for Completion {
7882 }
7983}
8084
81- impl std:: future:: Future for Completion {
85+ impl std:: future:: Future for Completion < ' _ > {
8286 type Output = crate :: error:: RadosResult < i32 > ;
8387
8488 fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
@@ -97,7 +101,10 @@ impl std::future::Future for Completion {
97101 }
98102}
99103
100- fn with_completion_impl < F > ( ioctx : Arc < IoCtx > , f : F ) -> RadosResult < Completion >
104+ /// Completions are only created via this wrapper, in order to ensure
105+ /// that the Completion struct is only constructed around 'armed' rados_completion_t
106+ /// instances (i.e. those that have been used to start an I/O).
107+ pub ( crate ) fn with_completion < F > ( ioctx : & IoCtx , f : F ) -> RadosResult < Completion < ' _ > >
101108where
102109 F : FnOnce ( rados_completion_t ) -> libc:: c_int ,
103110{
@@ -134,16 +141,3 @@ where
134141 } )
135142 }
136143}
137- /// Completions are only created via this wrapper, in order to ensure
138- /// that the Completion struct is only constructed around 'armed' rados_completion_t
139- /// instances (i.e. those that have been used to start an I/O).
140- pub async fn with_completion < F > ( ioctx : Arc < IoCtx > , f : F ) -> RadosResult < i32 >
141- where
142- F : FnOnce ( rados_completion_t ) -> libc:: c_int ,
143- {
144- // Hide c_void* temporaries in a non-async function so that the future generated
145- // by this function isn't encumbered by their non-Send-ness.
146- let completion = with_completion_impl ( ioctx, f) ?;
147-
148- completion. await
149- }
0 commit comments