IsoPoolable

Trait IsoPoolable 

Source
pub unsafe trait IsoPoolable: Poolable {
    const DISCRIMINANT: Option<Discriminant>;
}
Expand description

Trait for isomorphicly poolable objects.

That is objects that can safely be pooled by memory layout and container type. For example two HashMaps, HashMap<usize, usize> and HashMap<ArcStr, ArcStr> are isomorphic, their memory allocations can be used interchangably so long as they are empty.

Required Associated Constants§

Source

const DISCRIMINANT: Option<Discriminant>

§Getting the Layout Right

You must pass every type variable that can effect the layout of the container’s inner allocation to Discriminant. Take HashMap as an example. If you build the discriminant such as Discriminant::new_p1::<HashMap<K, V>>() it would always be the same for any K, V, because the HashMap struct doesn’t actually contain any Ks or Vs, just a pointer to some Ks and Vs. If you implemented discriminant this way it would cause your program to crash when you tried to pool two HashMap’s with K, V types that aren’t isomorphic. Instead you must pass K and V to Discriminant::new_p2::<K, V>() to get the real layout of the inner collection of HashMap. This is why this trait is unsafe to implement, if you aren’t careful when you build the discriminant very bad things will happen.

§Why not TypeId

The reason why Discriminant is used instead of TypeId (which would accomplish the same goal) is twofold. First Discriminant is 1 word on a 64 bit machine, and thus very fast to index, and second TypeId only supports types without references. However we often want to pool empty containers where the inner type is a reference, thus we cannot use TypeId.

§Why Return Option

Discriminant is a compressed version of layout that squeezes 2 layouts a size and a container type into 8 bytes. As such there are some layouts that are too big to fit in it, and the constructor will return None in those cases. For the purpose of pooling containers of small objects these tradeoffs seemed worth it. If you must pool containers of huge objects like this, you can use the thread safe pools.

§Arc

It is not safe to implement this trait in general for something like Arc, or any container that can’t be totally empty (like array). This is because having the same Discriminant only guarantees that two types are isomorphic, it does not guarantee that they have the same bit patterns. Normal container types are safe in spite of this because reset makes sure they are empty, and thus no errent bit patterns exist in the container and all we care about is that the container’s allocation is isomorphic with respect to the types we want to put in it.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl IsoPoolable for String

Source§

impl<K, R> IsoPoolable for HashSet<K, R>
where K: Hash + Eq, R: Default + BuildHasher,

Source§

impl<K, R> IsoPoolable for IndexSet<K, R>
where K: Hash + Eq, R: Default + BuildHasher,

Source§

impl<K, V, R> IsoPoolable for HashMap<K, V, R>
where K: Hash + Eq, R: Default + BuildHasher,

Source§

impl<K, V, R> IsoPoolable for IndexMap<K, V, R>
where K: Hash + Eq, R: Default + BuildHasher,

Source§

impl<T> IsoPoolable for VecDeque<T>

Source§

impl<T> IsoPoolable for Vec<T>

Implementors§