@@ -69,6 +69,12 @@ impl Arena {
6969 pub const fn capacity ( & self ) -> usize {
7070 self . cap
7171 }
72+
73+ /// Returns the number of bytes remaining bytes can be allocated by the arena.
74+ #[ inline]
75+ pub fn remaining ( & self ) -> usize {
76+ self . cap . saturating_sub ( self . size ( ) )
77+ }
7278}
7379
7480impl Arena {
@@ -199,25 +205,27 @@ impl Arena {
199205 align : u32 ,
200206 overflow : u32 ,
201207 ) -> Result < ( u32 , u32 ) , ArenaError > {
202- // Verify that the arena isn't already full.
203- let orig_size = self . n . load ( Ordering :: Acquire ) ;
204- if orig_size > self . cap as u64 {
205- return Err ( ArenaError ) ;
206- }
207-
208208 // Pad the allocation with enough bytes to ensure the requested alignment.
209209 let padded = size as u64 + align as u64 - 1 ;
210210
211- let new_size = self . n . fetch_add ( padded, Ordering :: AcqRel ) + padded;
211+ let res = self
212+ . n
213+ . fetch_update ( Ordering :: Release , Ordering :: Acquire , |orig| {
214+ if orig + padded + overflow as u64 > self . cap as u64 {
215+ return None ;
216+ }
217+ Some ( orig + padded)
218+ } ) ;
212219
213- if new_size + overflow as u64 > self . cap as u64 {
214- return Err ( ArenaError ) ;
220+ match res {
221+ Ok ( new_size) => {
222+ // Return the aligned offset.
223+ let new_size = new_size + padded;
224+ let offset = ( new_size as u32 - size) & !( align - 1 ) ;
225+ Ok ( ( offset, padded as u32 ) )
226+ }
227+ Err ( _) => Err ( ArenaError ) ,
215228 }
216-
217- // Return the aligned offset.
218- let offset = ( new_size as u32 - size) & !( align - 1 ) ;
219-
220- Ok ( ( offset, padded as u32 ) )
221229 }
222230
223231 /// ## Safety:
0 commit comments