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§
Sourceconst DISCRIMINANT: Option<Discriminant>
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.