14
14
15
15
use std:: ffi:: c_void;
16
16
use std:: pin:: Pin ;
17
- use std:: sync:: { Arc , Mutex } ;
17
+ use std:: sync:: Mutex ;
18
18
use std:: task:: { Context , Poll , Waker } ;
19
19
20
20
use crate :: ceph:: IoCtx ;
@@ -25,7 +25,7 @@ use crate::rados::{
25
25
rados_completion_t,
26
26
} ;
27
27
28
- struct Completion {
28
+ pub ( crate ) struct Completion < ' a > {
29
29
inner : rados_completion_t ,
30
30
31
31
// Box to provide a stable address for completion_complete callback
@@ -34,15 +34,15 @@ struct Completion {
34
34
35
35
// A reference to the IOCtx is required to issue a cancel on
36
36
// 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
38
38
// there would be nothing to stop the rados_ioctx_t being invalidated
39
39
// during the lifetime of this Completion.
40
40
// (AioCompletionImpl does hold a reference to IoCtxImpl for writes, but
41
41
// not for reads.)
42
- ioctx : Arc < IoCtx > ,
42
+ ioctx : & ' a IoCtx ,
43
43
}
44
44
45
- unsafe impl Send for Completion { }
45
+ unsafe impl Send for Completion < ' _ > { }
46
46
47
47
#[ no_mangle]
48
48
pub 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)
58
58
}
59
59
}
60
60
61
- impl Drop for Completion {
61
+ impl Drop for Completion < ' _ > {
62
62
fn drop ( & mut self ) {
63
63
// Ensure that after dropping the Completion, the AIO callback
64
64
// will not be called on our dropped waker Box. Only necessary
@@ -67,7 +67,11 @@ impl Drop for Completion {
67
67
let am_complete = unsafe { rados_aio_is_complete ( self . inner ) } != 0 ;
68
68
if !am_complete {
69
69
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
+
71
75
rados_aio_wait_for_complete_and_cb ( self . inner ) ;
72
76
}
73
77
}
@@ -78,7 +82,7 @@ impl Drop for Completion {
78
82
}
79
83
}
80
84
81
- impl std:: future:: Future for Completion {
85
+ impl std:: future:: Future for Completion < ' _ > {
82
86
type Output = crate :: error:: RadosResult < i32 > ;
83
87
84
88
fn poll ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Self :: Output > {
@@ -97,7 +101,10 @@ impl std::future::Future for Completion {
97
101
}
98
102
}
99
103
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 < ' _ > >
101
108
where
102
109
F : FnOnce ( rados_completion_t ) -> libc:: c_int ,
103
110
{
@@ -134,16 +141,3 @@ where
134
141
} )
135
142
}
136
143
}
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