@@ -61,9 +61,8 @@ use std::sync::atomic::Ordering;
61
61
mod container;
62
62
use container:: { TypeHolder , TypeHolderSend } ;
63
63
64
- use std:: any:: Any ;
65
- #[ cfg( feature = "arc" ) ]
66
64
use std:: any:: TypeId ;
65
+ use std:: any:: { type_name, Any } ;
67
66
use std:: borrow:: Borrow ;
68
67
use std:: convert:: AsRef ;
69
68
use std:: fmt:: { Debug , Display , Pointer } ;
@@ -195,9 +194,82 @@ where
195
194
F : FnOnce ( & mut T ) -> R ,
196
195
T : Any + Send + Default ,
197
196
{
198
- static INTERN_CONTAINERS : Mutex < TypeHolderSend > =
199
- parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ;
200
- f ( INTERN_CONTAINERS . lock ( ) . get_type_mut ( ) )
197
+ // Compute the hash of the type.
198
+ fn hash_of_type < T : ' static > ( ) -> u64 {
199
+ // We use very simple hasher, because it is optimized away to a constant:
200
+ // https://rust.godbolt.org/z/4T1fa4GGs
201
+ // which is not true for using `DefaultHasher`:
202
+ // https://rust.godbolt.org/z/qKar1WKfz
203
+ struct HasherForTypeId {
204
+ hash : u64 ,
205
+ }
206
+
207
+ impl Hasher for HasherForTypeId {
208
+ fn write ( & mut self , bytes : & [ u8 ] ) {
209
+ // Hash for type only calls `write_u64` once,
210
+ // but handle this case explicitly to make sure
211
+ // this code doesn't break if stdlib internals change.
212
+
213
+ for byte in bytes {
214
+ self . hash = self . hash . wrapping_mul ( 31 ) . wrapping_add ( * byte as u64 ) ;
215
+ }
216
+ }
217
+
218
+ fn write_u64 ( & mut self , v : u64 ) {
219
+ self . hash = v;
220
+ }
221
+
222
+ fn finish ( & self ) -> u64 {
223
+ self . hash
224
+ }
225
+ }
226
+
227
+ let mut hasher = HasherForTypeId { hash : 0 } ;
228
+ TypeId :: of :: < T > ( ) . hash ( & mut hasher) ;
229
+ hasher. hash
230
+ }
231
+
232
+ const INTERN_CONTAINER_COUNT : usize = 32 ;
233
+ static INTERN_CONTAINERS : [ Mutex < TypeHolderSend > ; INTERN_CONTAINER_COUNT ] = [
234
+ // There's no way to create a static array without copy-paste.
235
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
236
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
237
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
238
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
239
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
240
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
241
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
242
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
243
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
244
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
245
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
246
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
247
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
248
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
249
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
250
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
251
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
252
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
253
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
254
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
255
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
256
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
257
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
258
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
259
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
260
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
261
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
262
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
263
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
264
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
265
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
266
+ parking_lot:: const_mutex ( TypeHolderSend :: new ( ) ) ,
267
+ ] ;
268
+ f (
269
+ INTERN_CONTAINERS [ hash_of_type :: < T > ( ) as usize % INTERN_CONTAINER_COUNT ]
270
+ . lock ( )
271
+ . get_type_mut ( ) ,
272
+ )
201
273
}
202
274
203
275
impl < T : Eq + Hash + Send + Sync + ' static > Intern < T > {
0 commit comments