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}