@@ -67,6 +67,45 @@ unsafe impl Allocator for Pool {
67
67
ngx_pfree ( self . 0 . as_ptr ( ) , ptr. as_ptr ( ) . cast ( ) ) ;
68
68
}
69
69
}
70
+
71
+ unsafe fn grow (
72
+ & self ,
73
+ ptr : NonNull < u8 > ,
74
+ old_layout : Layout ,
75
+ new_layout : Layout ,
76
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
77
+ debug_assert ! (
78
+ new_layout. size( ) >= old_layout. size( ) ,
79
+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
80
+ ) ;
81
+ self . resize_in_place ( ptr, old_layout, new_layout, false )
82
+ }
83
+
84
+ unsafe fn grow_zeroed (
85
+ & self ,
86
+ ptr : NonNull < u8 > ,
87
+ old_layout : Layout ,
88
+ new_layout : Layout ,
89
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
90
+ debug_assert ! (
91
+ new_layout. size( ) >= old_layout. size( ) ,
92
+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
93
+ ) ;
94
+ self . resize_in_place ( ptr, old_layout, new_layout, true )
95
+ }
96
+
97
+ unsafe fn shrink (
98
+ & self ,
99
+ ptr : NonNull < u8 > ,
100
+ old_layout : Layout ,
101
+ new_layout : Layout ,
102
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
103
+ debug_assert ! (
104
+ new_layout. size( ) <= old_layout. size( ) ,
105
+ "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
106
+ ) ;
107
+ self . resize_in_place ( ptr, old_layout, new_layout, false )
108
+ }
70
109
}
71
110
72
111
impl AsRef < ngx_pool_t > for Pool {
@@ -229,6 +268,54 @@ impl Pool {
229
268
p
230
269
}
231
270
}
271
+
272
+ /// Resizes a memory allocation in place if possible.
273
+ ///
274
+ /// If resizing is requested for the last allocation in the pool, it may be
275
+ /// possible to adjust pool data and avoid any real allocations.
276
+ ///
277
+ /// # Safety
278
+ /// This function is marked as unsafe because it involves raw pointer manipulation.
279
+ unsafe fn resize_in_place (
280
+ & self ,
281
+ ptr : NonNull < u8 > ,
282
+ old_layout : Layout ,
283
+ new_layout : Layout ,
284
+ zeroize : bool ,
285
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
286
+ if ptr. byte_add ( old_layout. size ( ) ) . as_ptr ( ) == self . as_ref ( ) . d . last
287
+ && ptr. byte_add ( new_layout. size ( ) ) . as_ptr ( ) <= self . as_ref ( ) . d . end
288
+ && ptr. align_offset ( new_layout. align ( ) ) == 0
289
+ {
290
+ let pool = self . 0 . as_ptr ( ) ;
291
+ unsafe {
292
+ ( * pool) . d . last = ( * pool)
293
+ . d
294
+ . last
295
+ . byte_offset ( new_layout. size ( ) as isize - old_layout. size ( ) as isize )
296
+ } ;
297
+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_layout. size ( ) ) )
298
+ } else {
299
+ let size = core:: cmp:: min ( old_layout. size ( ) , new_layout. size ( ) ) ;
300
+ let new_ptr = self . allocate ( new_layout) ?;
301
+ unsafe {
302
+ ptr:: copy_nonoverlapping ( ptr. as_ptr ( ) , new_ptr. as_ptr ( ) . cast ( ) , size) ;
303
+ self . deallocate ( ptr, old_layout) ;
304
+ }
305
+ Ok ( new_ptr)
306
+ }
307
+ . inspect ( |new_ptr| {
308
+ if zeroize && new_layout. size ( ) < old_layout. size ( ) {
309
+ unsafe {
310
+ ptr:: write_bytes (
311
+ new_ptr. as_ptr ( ) . cast :: < u8 > ( ) . byte_add ( new_layout. size ( ) ) ,
312
+ 0 ,
313
+ old_layout. size ( ) - new_layout. size ( ) ,
314
+ )
315
+ } ;
316
+ }
317
+ } )
318
+ }
232
319
}
233
320
234
321
/// Cleanup handler for a specific type `T`.
0 commit comments