Skip to content

Commit

Permalink
Restructure BitMut to fit in two words
Browse files Browse the repository at this point in the history
Suggested by GitHub user @ImmemorConsultrixContrarie in PR #41, this
change structures the `BitMut` proxy reference as a memory pointer,
bit index, and bit cache. This structure fits within two words
instead of three (a full `&mut BitSlice` is not necessary, as the
structure only ever refers to one bit in one element).

This is purely a stack optimization; it has no effect on the
language-level inability to use it as the reference value in
ordinary access operations.
  • Loading branch information
myrrlyn committed Jan 23, 2020
1 parent a4b7c6d commit b87a81e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 11 deletions.
11 changes: 9 additions & 2 deletions src/slice/api.rs
Expand Up @@ -46,6 +46,7 @@ use crate::{

use core::{
cmp,
marker::PhantomData,
ops::{
Range,
RangeFrom,
Expand All @@ -54,6 +55,7 @@ use core::{
RangeTo,
RangeToInclusive,
},
ptr::NonNull,
slice,
};

Expand Down Expand Up @@ -2252,9 +2254,14 @@ where O: 'a + BitOrder, T: 'a + BitStore {
self,
slice: &'a mut BitSlice<O, T>,
) -> Self::Mut {
let bp = slice.bitptr();
let (offset, head) = bp.head().offset(self as isize);
let ptr = bp.pointer().a().offset(offset);
BitMut {
data: *slice.get_unchecked(self),
slot: slice.get_unchecked_mut(self ..= self),
_parent: PhantomData,
data: NonNull::new_unchecked(ptr as *mut T::Access),
head,
bit: (*ptr).get::<O>(head)
}
}

Expand Down
28 changes: 19 additions & 9 deletions src/slice/proxy.rs
Expand Up @@ -16,14 +16,20 @@ used in the `&mut` write reference system, as a good-enough substitute.
!*/

use crate::{
access::BitAccess,
indices::BitIdx,
order::BitOrder,
slice::BitSlice,
store::BitStore,
};

use core::ops::{
Deref,
DerefMut,
use core::{
marker::PhantomData,
ops::{
Deref,
DerefMut,
},
ptr::NonNull,
};

/** Proxy referential type, equivalent to `&mut bool`.
Expand All @@ -41,31 +47,35 @@ reference-like type is as close as Rust will allow.
**/
pub struct BitMut<'a, O, T>
where O: BitOrder, T: 'a + BitStore {
/// A reference to a single bit in memory.
pub(super) slot: &'a mut BitSlice<O, T>,
/// Inform the compiler that this has an exclusive borrow of a `BitSlice`
pub(super) _parent: PhantomData<&'a mut BitSlice<O, T>>,
/// Typed pointer to the memory element containing the proxied bit.
pub(super) data: NonNull<T::Access>,
/// Index of the proxied bit inside the targeted memory element.
pub(super) head: BitIdx<T>,
/// A local cache for `Deref` usage.
pub(super) data: bool,
pub(super) bit: bool,
}

impl<O, T> Deref for BitMut<'_, O, T>
where O: BitOrder, T: BitStore {
type Target = bool;

fn deref(&self) -> &Self::Target {
&self.data
&self.bit
}
}

impl<O, T> DerefMut for BitMut<'_, O, T>
where O: BitOrder, T: BitStore {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
&mut self.bit
}
}

impl<O, T> Drop for BitMut<'_, O, T>
where O: BitOrder, T: BitStore {
fn drop(&mut self) {
unsafe { self.slot.set_unchecked(0, self.data) }
unsafe { (*self.data.as_ptr()).set::<O>(self.head, self.bit) }
}
}

0 comments on commit b87a81e

Please sign in to comment.