@@ -67,14 +67,15 @@ pub struct FutureGroup<F> {
67
67
wakers : WakerVec ,
68
68
states : PollVec ,
69
69
keys : BTreeSet < usize > ,
70
+ capacity : usize ,
70
71
}
71
72
72
73
impl < T : Debug > Debug for FutureGroup < T > {
73
74
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
74
75
f. debug_struct ( "FutureGroup" )
75
76
. field ( "slab" , & "[..]" )
76
- . field ( "len" , & self . futures . len ( ) )
77
- . field ( "capacity" , & self . futures . capacity ( ) )
77
+ . field ( "len" , & self . len ( ) )
78
+ . field ( "capacity" , & self . capacity )
78
79
. finish ( )
79
80
}
80
81
}
@@ -110,6 +111,7 @@ impl<F> FutureGroup<F> {
110
111
wakers : WakerVec :: new ( capacity) ,
111
112
states : PollVec :: new ( capacity) ,
112
113
keys : BTreeSet :: new ( ) ,
114
+ capacity,
113
115
}
114
116
}
115
117
@@ -127,6 +129,7 @@ impl<F> FutureGroup<F> {
127
129
/// group.insert(future::ready(12));
128
130
/// assert_eq!(group.len(), 1);
129
131
/// ```
132
+ #[ inline( always) ]
130
133
pub fn len ( & self ) -> usize {
131
134
self . futures . len ( )
132
135
}
@@ -144,7 +147,7 @@ impl<F> FutureGroup<F> {
144
147
/// # let group: FutureGroup<usize> = group;
145
148
/// ```
146
149
pub fn capacity ( & self ) -> usize {
147
- self . futures . capacity ( )
150
+ self . capacity
148
151
}
149
152
150
153
/// Returns true if there are no futures currently active in the group.
@@ -209,6 +212,36 @@ impl<F> FutureGroup<F> {
209
212
pub fn contains_key ( & mut self , key : Key ) -> bool {
210
213
self . keys . contains ( & key. 0 )
211
214
}
215
+
216
+ /// Reserves capacity for `additional` more futures to be inserted.
217
+ /// Does nothing if the capacity is already sufficient.
218
+ ///
219
+ /// # Example
220
+ ///
221
+ /// ```rust
222
+ /// use futures_concurrency::future::FutureGroup;
223
+ /// use std::future::Ready;
224
+ /// # futures_lite::future::block_on(async {
225
+ /// let mut group: FutureGroup<Ready<usize>> = FutureGroup::with_capacity(0);
226
+ /// assert_eq!(group.capacity(), 0);
227
+ /// group.reserve(10);
228
+ /// assert_eq!(group.capacity(), 10);
229
+ ///
230
+ /// // does nothing if capacity is sufficient
231
+ /// group.reserve(5);
232
+ /// assert_eq!(group.capacity(), 10);
233
+ /// # })
234
+ /// ```
235
+ pub fn reserve ( & mut self , additional : usize ) {
236
+ if self . len ( ) + additional < self . capacity {
237
+ return ;
238
+ }
239
+ let new_cap = self . capacity + additional;
240
+ self . wakers . resize ( new_cap) ;
241
+ self . states . resize ( new_cap) ;
242
+ self . futures . reserve_exact ( additional) ;
243
+ self . capacity = new_cap;
244
+ }
212
245
}
213
246
214
247
impl < F : Future > FutureGroup < F > {
@@ -223,26 +256,22 @@ impl<F: Future> FutureGroup<F> {
223
256
/// let mut group = FutureGroup::with_capacity(2);
224
257
/// group.insert(future::ready(12));
225
258
/// ```
226
- pub fn insert ( & mut self , stream : F ) -> Key
259
+ pub fn insert ( & mut self , future : F ) -> Key
227
260
where
228
261
F : Future ,
229
262
{
230
- let index = self . futures . insert ( stream ) ;
231
- self . keys . insert ( index ) ;
232
- let key = Key ( index ) ;
263
+ if self . capacity < = self . len ( ) {
264
+ self . reserve ( self . capacity * 2 + 1 ) ;
265
+ }
233
266
234
- // If our slab allocated more space we need to
235
- // update our tracking structures along with it.
236
- let max_len = self . capacity ( ) . max ( index) ;
237
- self . wakers . resize ( max_len) ;
238
- self . states . resize ( max_len) ;
267
+ let index = self . futures . insert ( future) ;
268
+ self . keys . insert ( index) ;
239
269
240
270
// Set the corresponding state
241
271
self . states [ index] . set_pending ( ) ;
242
- let mut readiness = self . wakers . readiness ( ) ;
243
- readiness. set_ready ( index) ;
272
+ self . wakers . readiness ( ) . set_ready ( index) ;
244
273
245
- key
274
+ Key ( index )
246
275
}
247
276
248
277
/// Insert a value into a pinned `FutureGroup`
@@ -251,14 +280,14 @@ impl<F: Future> FutureGroup<F> {
251
280
/// `ConcurrentStream`. We should never expose this publicly, as the entire
252
281
/// point of this crate is that we abstract the futures poll machinery away
253
282
/// from end-users.
254
- pub ( crate ) fn insert_pinned ( self : Pin < & mut Self > , stream : F ) -> Key
283
+ pub ( crate ) fn insert_pinned ( self : Pin < & mut Self > , future : F ) -> Key
255
284
where
256
285
F : Future ,
257
286
{
258
287
let mut this = self . project ( ) ;
259
288
// SAFETY: inserting a value into the futures slab does not ever move
260
289
// any of the existing values.
261
- let index = unsafe { this. futures . as_mut ( ) . get_unchecked_mut ( ) } . insert ( stream ) ;
290
+ let index = unsafe { this. futures . as_mut ( ) . get_unchecked_mut ( ) } . insert ( future ) ;
262
291
this. keys . insert ( index) ;
263
292
let key = Key ( index) ;
264
293
@@ -455,4 +484,16 @@ mod test {
455
484
assert ! ( group. is_empty( ) ) ;
456
485
} ) ;
457
486
}
487
+
488
+ #[ test]
489
+ fn capacity_grow_on_insert ( ) {
490
+ futures_lite:: future:: block_on ( async {
491
+ let mut group = FutureGroup :: new ( ) ;
492
+ let cap = group. capacity ( ) ;
493
+
494
+ group. insert ( future:: ready ( 1 ) ) ;
495
+
496
+ assert ! ( group. capacity( ) > cap) ;
497
+ } ) ;
498
+ }
458
499
}
0 commit comments