Pointers_Study_With_Core_Concepts/
cell.rs

1//! # Basic implementation of a Cell mutable container
2//! With most essential info about it
3use std::{cell::UnsafeCell, ptr};
4
5/// # Info
6/// Doesn't impl Sync, so if you have a ref to a cell
7/// you cannot give it away to a different thread.
8///
9/// You cannot get a ref to the value inside the cell,
10/// therefore it's always safe to mut it.
11///
12/// Guarantees it at compile time.
13///
14/// # Common Usage
15///
16/// Used for small copy types.
17///
18/// For small(er) values like numbers/flags that need to be mutated from multiple places
19/// e.g Thread Locals.
20///
21/// When you want to have multiple shared ref to a thing.
22///
23///
24/// # Required to wrap T in UnsafeCell
25/// Because you are never allowed to cast a shared ref to an exclusive ref
26/// in other way than by going through the unsafe cell. It's the only way to implement interior mutability.
27#[derive(Debug)]
28pub struct MyCell<T> {
29    // implied by UnsafeCell
30    // impl<T> !Sync for MyCell<T>
31    value: UnsafeCell<T>,
32}
33
34impl<T: Copy> MyCell<T> {
35    pub fn new(value: T) -> Self {
36        MyCell {
37            value: UnsafeCell::new(value),
38        }
39    }
40
41    pub fn set(&self, value: T) {
42        unsafe {
43            *self.value.get() = value;
44        }
45    }
46
47    pub fn get(&self) -> T
48    where
49        T: Copy,
50    {
51        unsafe { *self.value.get() }
52    }
53
54    pub fn swap(&self, other: &Self) {
55        unsafe {
56            if ptr::eq(self, other) {
57                return;
58            }
59
60            ptr::swap(self.value.get(), other.value.get());
61        }
62    }
63}