rust/hg-core/src/dirstate_tree/owning.rs
author Raphaël Gomès <rgomes@octobus.net>
Fri, 18 Mar 2022 16:15:44 +0100
branchstable
changeset 48973 e2f8ed37201c
parent 48567 d1210d56008b
child 48999 cfd270d83169
permissions -rw-r--r--
rust-status: cap the number of concurrent threads to 16 During benchmarking it was determined that the use of more threads is very advantageous... until we use more than 16. This is most likely due to some resource contention (thrashing, etc.). Until we have time to figure out and fix the underlying cause, let's just cap at 16 threads. Differential Revision: https://phab.mercurial-scm.org/D12384
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
     1
use super::dirstate_map::DirstateMap;
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
     2
use stable_deref_trait::StableDeref;
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
     3
use std::ops::Deref;
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     4
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     5
/// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
     6
/// borrows.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     7
///
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     8
/// This is similar to [`OwningRef`] which is more limited because it
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
     9
/// represents exactly one `&T` reference next to the value it borrows, as
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    10
/// opposed to a struct that may contain an arbitrary number of references in
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    11
/// arbitrarily-nested data structures.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    12
///
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    13
/// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    14
pub struct OwningDirstateMap {
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    15
    /// Owned handle to a bytes buffer with a stable address.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    16
    ///
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    17
    /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    18
    on_disk: Box<dyn Deref<Target = [u8]> + Send>,
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    19
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    20
    /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    21
    /// language cannot represent a lifetime referencing a sibling field.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    22
    /// This is not quite a self-referencial struct (moving this struct is not
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    23
    /// a problem as it doesn’t change the address of the bytes buffer owned
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    24
    /// by `on_disk`) but touches similar borrow-checker limitations.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    25
    ptr: *mut (),
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    26
}
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    27
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    28
impl OwningDirstateMap {
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    29
    pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    30
    where
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    31
        OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    32
    {
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    33
        let on_disk = Box::new(on_disk);
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    34
        let bytes: &'_ [u8] = &on_disk;
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    35
        let map = DirstateMap::empty(bytes);
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    36
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    37
        // Like in `bytes` above, this `'_` lifetime parameter borrows from
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    38
        // the bytes buffer owned by `on_disk`.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    39
        let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    40
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    41
        // Erase the pointed type entirely in order to erase the lifetime.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    42
        let ptr: *mut () = ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    43
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    44
        Self { on_disk, ptr }
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    45
    }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    46
48069
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
    47
    pub fn get_pair_mut<'a>(
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    48
        &'a mut self,
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    49
    ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    50
        // SAFETY: We cast the type-erased pointer back to the same type it had
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    51
        // in `new`, except with a different lifetime parameter. This time we
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    52
        // connect the lifetime to that of `self`. This cast is valid because
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    53
        // `self` owns the same `on_disk` whose buffer `DirstateMap`
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    54
        // references. That buffer has a stable memory address because our
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    55
        // `Self::new_empty` counstructor requires `StableDeref`.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    56
        let ptr: *mut DirstateMap<'a> = self.ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    57
        // SAFETY: we dereference that pointer, connecting the lifetime of the
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    58
        // new `&mut` to that of `self`. This is valid because the
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    59
        // raw pointer is to a boxed value, and `self` owns that box.
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    60
        (&self.on_disk, unsafe { &mut *ptr })
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    61
    }
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    62
48069
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
    63
    pub fn get_map_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
    64
        self.get_pair_mut().1
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    65
    }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    66
48069
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
    67
    pub fn get_map<'a>(&'a self) -> &'a DirstateMap<'a> {
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    68
        // SAFETY: same reasoning as in `get_pair_mut` above.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    69
        let ptr: *mut DirstateMap<'a> = self.ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    70
        unsafe { &*ptr }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    71
    }
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    72
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    73
    pub fn on_disk<'a>(&'a self) -> &'a [u8] {
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    74
        &self.on_disk
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
    75
    }
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    76
}
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    77
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    78
impl Drop for OwningDirstateMap {
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    79
    fn drop(&mut self) {
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    80
        // Silence a "field is never read" warning, and demonstrate that this
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    81
        // value is still alive.
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    82
        let _: &Box<dyn Deref<Target = [u8]> + Send> = &self.on_disk;
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    83
        // SAFETY: this cast is the same as in `get_mut`, and is valid for the
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    84
        // same reason. `self.on_disk` still exists at this point, drop glue
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    85
        // will drop it implicitly after this `drop` method returns.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    86
        let ptr: *mut DirstateMap<'_> = self.ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    87
        // SAFETY: `Box::from_raw` takes ownership of the box away from `self`.
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
    88
        // This is fine because drop glue does nothing for `*mut ()` and we’re
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    89
        // in `drop`, so `get` and `get_mut` cannot be called again.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    90
        unsafe { drop(Box::from_raw(ptr)) }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    91
    }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    92
}
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    93
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    94
fn _static_assert_is_send<T: Send>() {}
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    95
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    96
fn _static_assert_fields_are_send() {
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    97
    _static_assert_is_send::<Box<DirstateMap<'_>>>();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    98
}
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
    99
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   100
// SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   101
// thread-safety of raw pointers is unknown in the general case. However this
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   102
// particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
   103
// own. Since that `Box` is `Send` as shown in above, it is sound to mark
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
   104
// this struct as `Send` too.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
   105
unsafe impl Send for OwningDirstateMap {}