[][src]Function moite_moite::sync::split_with

pub fn split_with<L, R, W, F>(value: W, f: F) -> (Part<L, W>, Part<R, W>) where
    L: ?Sized,
    R: ?Sized,
    F: FnOnce(&mut W) -> (&mut L, &mut R)

Splits a value into two owned parts.

Sharing

The internal reference counter is atomic, allowing the left and right parts to be safely shared across threads:

  • Part<T, W> is Sync if T is Sync;
  • Part<T, W> is Send if T is Send and W is Send.

There are no W: Sync bounds because users cannot get a reference to a split W, whereas there is a W: Send bound because the dropping code for W may be run on any thread, when its last part is dropped.

Example

use moite_moite::sync::{Part, split_with};
use std::ops::Drop;

struct Target<L, R>(Option<(L, R)>);

struct PairCell<'t, L, R> {
    target: &'t mut Option<(L, R)>,
    left: Option<L>,
    right: Option<R>,
}

impl<'t, L, R> PairCell<'t, L, R> {
    fn split(self) -> (Part<Option<L>, Self>, Part<Option<R>, Self>) {
        split_with(self, |this| (&mut this.left, &mut this.right))
    }
}

impl<'t, L, R> Drop for PairCell<'t, L, R> {
    fn drop(&mut self) {
        let left = self.left.take().expect("no left");
        let right = self.right.take().expect("no right");

        *self.target = Some((left, right));
    }
}

let mut target = Target(None);
{
    let cell = PairCell {
        target: &mut target.0,
        left: None,
        right: None,
    };

    let (mut left, mut right) = cell.split();

    *left = Some("Ram");
    *right = Some("Rem");
}

let (left, right) = target.0.expect("Where are the twin maids?");

assert_eq!(left, "Ram");
assert_eq!(right, "Rem");