multiversx_chain_vm/with_shared/
shareable.rs1#![allow(deprecated)]
2
3use std::{
4 ops::{Deref, DerefMut},
5 sync::Arc,
6};
7
8#[deprecated(since = "0.57.0", note = "replaced by BlockchainVMRef and Arc")]
15pub enum Shareable<T> {
16 Owned(T),
17 Shared(Arc<T>),
18}
19
20impl<T> Shareable<T> {
21 pub fn new(t: T) -> Self {
22 Shareable::Owned(t)
23 }
24
25 pub fn into_inner(self) -> T {
27 if let Shareable::Owned(t) = self {
28 t
29 } else {
30 panic!("cannot access ShareableMut owned object")
31 }
32 }
33}
34
35impl<T> Default for Shareable<T>
36where
37 T: Default,
38{
39 fn default() -> Self {
40 Shareable::new(T::default())
41 }
42}
43
44impl<T> Deref for Shareable<T> {
45 type Target = T;
46
47 fn deref(&self) -> &Self::Target {
48 match self {
49 Shareable::Owned(t) => t,
50 Shareable::Shared(rc) => rc.deref(),
51 }
52 }
53}
54
55impl<T> DerefMut for Shareable<T> {
56 fn deref_mut(&mut self) -> &mut Self::Target {
57 match self {
58 Shareable::Owned(t) => t,
59 Shareable::Shared(_) => {
60 panic!("cannot mutably dereference ShareableMut when in Shared state")
61 }
62 }
63 }
64}
65
66impl<T> Shareable<T> {
67 fn get_arc(&self) -> Arc<T> {
68 if let Shareable::Shared(arc) = self {
69 arc.clone()
70 } else {
71 panic!("invalid ShareableMut state: Shared expected")
72 }
73 }
74
75 fn wrap_arc_strict(&mut self) {
76 unsafe {
77 let temp = std::ptr::read(self);
78 if let Shareable::Owned(t) = temp {
79 std::ptr::write(self, Shareable::Shared(Arc::new(t)));
80 } else {
81 std::mem::forget(temp);
82 panic!("invalid ShareableMut state: Owned expected")
83 }
84 }
85 }
86
87 fn unwrap_arc_strict(&mut self) {
88 unsafe {
89 let temp = std::ptr::read(self);
90 if let Shareable::Shared(arc) = temp {
91 match Arc::try_unwrap(arc) {
92 Ok(t) => {
93 std::ptr::write(self, Shareable::Owned(t));
94 }
95 Err(rc) => {
96 std::mem::forget(rc);
97 panic!(
98 "failed to recover Owned ShareableMut from Shared, not all Rc pointers dropped"
99 )
100 }
101 }
102 } else {
103 std::mem::forget(temp);
104 panic!("invalid ShareableMut state: Shared expected")
105 }
106 }
107 }
108
109 pub fn with_shared<F, R>(&mut self, f: F) -> R
116 where
117 F: FnOnce(Arc<T>) -> R,
118 {
119 self.wrap_arc_strict();
120
121 let result = f(self.get_arc());
122
123 self.unwrap_arc_strict();
124
125 result
126 }
127}
128
129#[cfg(test)]
130mod test {
131 #![allow(deprecated)]
132
133 use std::cell::RefCell;
134
135 use super::Shareable;
136
137 #[test]
138 fn test_shareable_mut_1() {
139 let mut s = Shareable::new("test string".to_string());
140 let l = s.with_shared(|s_arc| s_arc.len());
141 assert_eq!(s.len(), l);
142 }
143
144 #[test]
145 fn test_shareable_mut_2() {
146 let mut s = Shareable::new(RefCell::new("test string".to_string()));
147 s.with_shared(|s_arc| {
148 s_arc.borrow_mut().push_str(" ... changed");
149 });
150 assert_eq!(s.borrow().as_str(), "test string ... changed");
151 assert_eq!(s.into_inner().into_inner(), "test string ... changed");
152 }
153
154 #[test]
155 #[should_panic = "failed to recover Owned ShareableMut from Shared, not all Rc pointers dropped"]
156 fn test_shareable_mut_fail() {
157 let mut s = Shareable::new("test string".to_string());
158 let _illegally_extracted_arc = s.with_shared(|s_arc| s_arc);
159 }
160}