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!("failed to recover Owned ShareableMut from Shared, not all Rc pointers dropped")
98 }
99 }
100 } else {
101 std::mem::forget(temp);
102 panic!("invalid ShareableMut state: Shared expected")
103 }
104 }
105 }
106
107 pub fn with_shared<F, R>(&mut self, f: F) -> R
114 where
115 F: FnOnce(Arc<T>) -> R,
116 {
117 self.wrap_arc_strict();
118
119 let result = f(self.get_arc());
120
121 self.unwrap_arc_strict();
122
123 result
124 }
125}
126
127#[cfg(test)]
128mod test {
129 #![allow(deprecated)]
130
131 use std::cell::RefCell;
132
133 use super::Shareable;
134
135 #[test]
136 fn test_shareable_mut_1() {
137 let mut s = Shareable::new("test string".to_string());
138 let l = s.with_shared(|s_arc| s_arc.len());
139 assert_eq!(s.len(), l);
140 }
141
142 #[test]
143 fn test_shareable_mut_2() {
144 let mut s = Shareable::new(RefCell::new("test string".to_string()));
145 s.with_shared(|s_arc| {
146 s_arc.borrow_mut().push_str(" ... changed");
147 });
148 assert_eq!(s.borrow().as_str(), "test string ... changed");
149 assert_eq!(s.into_inner().into_inner(), "test string ... changed");
150 }
151
152 #[test]
153 #[should_panic = "failed to recover Owned ShareableMut from Shared, not all Rc pointers dropped"]
154 fn test_shareable_mut_fail() {
155 let mut s = Shareable::new("test string".to_string());
156 let _illegally_extracted_arc = s.with_shared(|s_arc| s_arc);
157 }
158}