Pointers_Study_With_Core_Concepts/
cell.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! # Basic implementation of a Cell mutable container
//! With most essential info about it
use std::{cell::UnsafeCell, ptr};

/// # Info
/// Doesn't impl Sync, so if you have a ref to a cell
/// you cannot give it away to a different thread.
///
/// You cannot get a ref to the value inside the cell,
/// therefore it's always safe to mut it.
///
/// Guarantees it at compile time.
///
/// # Common Usage
///
/// Used for small copy types.
///
/// For small(er) values like numbers/flags that need to be mutated from multiple places
/// e.g Thread Locals.
///
/// When you want to have multiple shared ref to a thing.
///
///
/// # Required to wrap T in UnsafeCell
/// Because you are never allowed to cast a shared ref to an exclusive ref
/// in other way than by going through the unsafe cell. It's the only way to implement interior mutability.
#[derive(Debug)]
pub struct MyCell<T> {
    // implied by UnsafeCell
    // impl<T> !Sync for MyCell<T>
    value: UnsafeCell<T>,
}

impl<T: Copy> MyCell<T> {
    pub fn new(value: T) -> Self {
        MyCell {
            value: UnsafeCell::new(value),
        }
    }

    pub fn set(&self, value: T) {
        unsafe {
            *self.value.get() = value;
        }
    }

    pub fn get(&self) -> T
    where
        T: Copy,
    {
        unsafe { *self.value.get() }
    }

    pub fn swap(&self, other: &Self) {
        unsafe {
            if ptr::eq(self, other) {
                return;
            }

            ptr::swap(self.value.get(), other.value.get());
        }
    }
}