-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add debug checks for misusage of Stash indices #6
Comments
indices
That's what
I could do this in Unfortunately, I can't do either for
|
Also, sorry about the late reply. GitHub doesn't do reliable notification email delivery 😿. |
@Stebalien You are completely right that this feature would require an overhaul of the In my |
The problem isn't the overhaul, it's that using
The only difference is that each "slot" is versioned (your second check). |
The good thing is that you can use Mio's trait struct TaggedIndex<T> where T: ::mio::Index {
tag: Tag,
timestamp: Timestamp,
ticket: T
}
impl<T> ::mio::Index for TaggedIndex<T> where T: ::mio::Index { ... } But maybe I haven't understood what you exactly meant by "I designed it to work with MIO". |
Actually, it appears that slab (the crate that used to define However, I'd still need an extra "DebugIndex" trait for debug checks: struct Metadata {
slot_version: u64,
stash_id: u64,
}
// The `From` and `Into` implementations should probably panic.
trait DebugIndex: From<usize> + Into<usize> {
fn from(metadata: Metadata, index: usize) -> Self;
fn into(self) -> (Metadata, usize);
} The best way to make this work would be specialization. If one wanted debug assertions, one would implement: #[cfg(debug_assertions)]
impl DebugIndex for MyIndexType ... If you can figure out a maintainable way to do this that has only opt-in runtime costs and ensures, I'd be happy to accept a patch. However, I don't really have time right now to get something like this working myself.
It has to be possible to pick an index that's freely convertible to/from a |
In insaneinside's crate
symtern
(https://github.com/insaneinside/symtern) the system checks for misusage ofindices
into the string interner during debug builds and runs. For release builds these checks are disabled for performance reasons. Yet, this feature enables a very rich debugging experience when using his string interner.The same techniques could be applied to
stash-rs
!The checks are quite simple:
index
passed to methods such asget
,get_mut
andtake
was generated by this instance ofStash
.index
passed to methods such asget
,get_mut
andtake
was generated before this instance ofStash
removed it or was cleared: accesses an "old
" entry that is no longer present or has been updated meanwhile.Both checks could be implemented with tags and timestamps.
For example in debug builds, every instance of
Stash
receives and stores a unique identifier (which I will calltag
: should beu64
for stability purposes). Thistag
must also be stored for every outgoingindex
generated byput
. This enforces a generic implementation ofindices
: other people have already suggested this forStash
.Also every full entry within an instance of a
Stash
requires a unique timestamp which is again just a number that is incremented for an instance ofStash
whenever the userput
s a new item into it. This also has to be stored in debug-modeindices
generated byput
.With this structure it is then very easy to debug programs for invalid accesses to instances of
Stash
:When calling a method such as
get
,get_mut
ortake
with an indexidx
the following checks are made:idx.tag == self.tag
: This ensures that the index was generated by thisStash
instanceidx.timestamp == self[idx].timestamp
: This ensures that the entry that is associated with the timestamp ofidx
has not been updated (e.g. taken and put in again) during the lifetime ofidx
.Possible timestamp storage design
To store the lifetimes for every bucket it should be possible to create a separate array which stores a lifetime for every bucket. Whenever a bucket is assigned a new
Entry::Full
or whenver it is cleared we simply increase thetimestamp
for that bucket in theStash
. This design makes it easy to adjust the code for debug builds.Behaviour on
clear
After
clear
has been called on an instances
ofStash
all extern indicesidx
should be invalidated. This can be achived by settings.tag
to a new global unique identifier. No other changes are required besides that.How are failures handled?
The assertions should be handled with
debug_assert!
macro. This way the assertions are only enabled for debug builds and the API doesn't need to change toResult<_>
types.Feature gate or not?
This feature could also be provided behind a feature gate instead of being active by default for debug builds.
The text was updated successfully, but these errors were encountered: