@@ -67,6 +67,54 @@ 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 ( ptr, old_layout, new_layout)
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
+ #[ allow( clippy:: manual_inspect) ]
95
+ self . resize ( ptr, old_layout, new_layout) . map ( |new_ptr| {
96
+ unsafe {
97
+ new_ptr
98
+ . cast :: < u8 > ( )
99
+ . byte_add ( old_layout. size ( ) )
100
+ . write_bytes ( 0 , new_layout. size ( ) - old_layout. size ( ) )
101
+ } ;
102
+ new_ptr
103
+ } )
104
+ }
105
+
106
+ unsafe fn shrink (
107
+ & self ,
108
+ ptr : NonNull < u8 > ,
109
+ old_layout : Layout ,
110
+ new_layout : Layout ,
111
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
112
+ debug_assert ! (
113
+ new_layout. size( ) <= old_layout. size( ) ,
114
+ "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
115
+ ) ;
116
+ self . resize ( ptr, old_layout, new_layout)
117
+ }
70
118
}
71
119
72
120
impl AsRef < ngx_pool_t > for Pool {
@@ -229,6 +277,39 @@ impl Pool {
229
277
p
230
278
}
231
279
}
280
+
281
+ /// Resizes a memory allocation in place if possible.
282
+ ///
283
+ /// If resizing is requested for the last allocation in the pool, it may be
284
+ /// possible to adjust pool data and avoid any real allocations.
285
+ ///
286
+ /// # Safety
287
+ /// `ptr` must point to allocated address and `old_layout` must match the current layout
288
+ /// of the allocation.
289
+ #[ inline( always) ]
290
+ unsafe fn resize (
291
+ & self ,
292
+ ptr : NonNull < u8 > ,
293
+ old_layout : Layout ,
294
+ new_layout : Layout ,
295
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
296
+ if ptr. byte_add ( old_layout. size ( ) ) . as_ptr ( ) == self . as_ref ( ) . d . last
297
+ && ptr. byte_add ( new_layout. size ( ) ) . as_ptr ( ) <= self . as_ref ( ) . d . end
298
+ && ptr. align_offset ( new_layout. align ( ) ) == 0
299
+ {
300
+ let pool = self . 0 . as_ptr ( ) ;
301
+ unsafe { ( * pool) . d . last = ptr. byte_add ( new_layout. size ( ) ) . as_ptr ( ) } ;
302
+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_layout. size ( ) ) )
303
+ } else {
304
+ let size = core:: cmp:: min ( old_layout. size ( ) , new_layout. size ( ) ) ;
305
+ let new_ptr = <Self as Allocator >:: allocate ( self , new_layout) ?;
306
+ unsafe {
307
+ ptr. copy_to_nonoverlapping ( new_ptr. cast ( ) , size) ;
308
+ self . deallocate ( ptr, old_layout) ;
309
+ }
310
+ Ok ( new_ptr)
311
+ }
312
+ }
232
313
}
233
314
234
315
/// Cleanup handler for a specific type `T`.
0 commit comments