@@ -77,24 +77,41 @@ impl<IT, N> Key<IT, N> {
7777 }
7878}
7979
80+ /// Module to hide the Entry type which needs to be public due to the generic-array internals.
81+ mod entry {
82+ pub enum Entry < IT > {
83+ Used ( IT ) ,
84+ EmptyNext ( usize ) ,
85+ EmptyLast
86+ }
87+ }
88+
89+ use entry:: Entry ;
90+
8091// Data type that stores values and returns a key that can be used to manipulate
8192// the stored values.
8293// Values can be read by anyone but can only be modified using the key.
8394pub struct Slots < IT , N >
84- where N : ArrayLength < Option < IT > > + ArrayLength < usize > + Unsigned {
85- items : GenericArray < Option < IT > , N > ,
86- free_list : GenericArray < usize , N > ,
95+ where N : ArrayLength < Entry < IT > > + Unsigned {
96+ items : GenericArray < Entry < IT > , N > ,
97+ // Could be optimized by making it just usize and relying on free_count to determine its
98+ // validity
99+ next_free : Option < usize > ,
87100 free_count : usize
88101}
89102
90103impl < IT , N > Slots < IT , N >
91- where N : ArrayLength < Option < IT > > + ArrayLength < usize > + Unsigned {
104+ where N : ArrayLength < Entry < IT > > + Unsigned {
92105 pub fn new ( ) -> Self {
93106 let size = N :: to_usize ( ) ;
94107
95108 Self {
96- items : GenericArray :: default ( ) ,
97- free_list : GenericArray :: generate ( |i : usize | size - i - 1 ) ,
109+ // Fill back-to-front
110+ // items: GenericArray::generate(|i: usize| if i == 0 { Entry::EmptyLast } else { Entry::EmptyNext(i - 1) }),
111+ // next_free: size.checked_sub(1),
112+ // Fill front-to-back
113+ items : GenericArray :: generate ( |i : usize | if i == size - 1 { Entry :: EmptyLast } else { Entry :: EmptyNext ( i + 1 ) } ) ,
114+ next_free : Some ( 0 ) ,
98115 free_count : size
99116 }
100117 }
@@ -108,37 +125,45 @@ impl<IT, N> Slots<IT, N>
108125 }
109126
110127 fn free ( & mut self , idx : usize ) {
111- self . free_list [ self . free_count ] = idx;
128+ self . items [ idx] = match self . next_free {
129+ Some ( n) => Entry :: EmptyNext ( n) ,
130+ None => Entry :: EmptyLast
131+ } ;
132+ self . next_free = Some ( idx) ;
112133 self . free_count += 1 ;
113134 }
114135
115136 fn alloc ( & mut self ) -> Option < usize > {
116137 if self . count ( ) == self . capacity ( ) {
117138 None
118139 } else {
119- let i = self . free_list [ self . free_count - 1 ] ;
140+ let result = self . next_free ;
141+ self . next_free = match self . items [ result. expect ( "Count mismatch" ) ] {
142+ Entry :: EmptyNext ( n) => Some ( n) ,
143+ Entry :: EmptyLast => None ,
144+ _ => unreachable ! ( "Non-empty item in entry behind free chain" ) ,
145+ } ;
120146 self . free_count -= 1 ;
121- Some ( i )
147+ result
122148 }
123149 }
124150
125151 pub fn store ( & mut self , item : IT ) -> Result < Key < IT , N > , IT > {
126152 match self . alloc ( ) {
127153 Some ( i) => {
128- self . items [ i] = Some ( item) ;
154+ self . items [ i] = Entry :: Used ( item) ;
129155 Ok ( Key :: new ( i) )
130156 }
131157 None => Err ( item)
132158 }
133159 }
134160
135161 pub fn take ( & mut self , key : Key < IT , N > ) -> IT {
136- match self . items [ key. index ] . take ( ) {
137- Some ( item) => {
138- self . free ( key. index ) ;
139- item
140- }
141- None => panic ! ( )
162+ let taken = core:: mem:: replace ( & mut self . items [ key. index ] , Entry :: EmptyLast ) ;
163+ self . free ( key. index ) ;
164+ match taken {
165+ Entry :: Used ( item) => item,
166+ _ => panic ! ( )
142167 }
143168 }
144169
@@ -151,15 +176,15 @@ impl<IT, N> Slots<IT, N>
151176
152177 pub fn try_read < T , F > ( & self , key : usize , function : F ) -> Option < T > where F : Fn ( & IT ) -> T {
153178 match & self . items [ key] {
154- Some ( item) => Some ( function ( & item) ) ,
155- None => None
179+ Entry :: Used ( item) => Some ( function ( & item) ) ,
180+ _ => None
156181 }
157182 }
158183
159184 pub fn modify < T , F > ( & mut self , key : & Key < IT , N > , function : F ) -> T where F : Fn ( & mut IT ) -> T {
160185 match self . items [ key. index ] {
161- Some ( ref mut item) => function ( item) ,
162- None => panic ! ( )
186+ Entry :: Used ( ref mut item) => function ( item) ,
187+ _ => panic ! ( )
163188 }
164189 }
165190}
0 commit comments