From 6f5baf69b56f4dfdf51bbb22730943c4ab5f8eff Mon Sep 17 00:00:00 2001
From: o0Ignition0o <jeremy.lempereur@gmail.com>
Date: Tue, 13 Apr 2021 09:58:39 +0200
Subject: [PATCH 1/6] wip

---
 src/bastion/Cargo.toml                 |  1 +
 src/bastion/src/system/global_state.rs | 13 ++++++-------
 src/bastion/src/system/mod.rs          |  6 ++----
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/bastion/Cargo.toml b/src/bastion/Cargo.toml
index 3cdae511..f1eda889 100644
--- a/src/bastion/Cargo.toml
+++ b/src/bastion/Cargo.toml
@@ -55,5 +55,6 @@ lever = "0.1.1-alpha.11"
 lightproc = "0.3.5"
 regex = "1.3.9"
 uuid = { version = "0.8", features = ["v4"] }
+once_cell = "1.7.2"
 
 [dev-dependencies]
diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
index 1bac489a..5853933f 100644
--- a/src/bastion/src/system/global_state.rs
+++ b/src/bastion/src/system/global_state.rs
@@ -19,7 +19,7 @@ pub struct GlobalState {
 
 #[derive(Debug, Clone)]
 /// A container for user-defined types.
-struct GlobalDataContainer(Arc<AtomicBox<Box<dyn Any>>>);
+struct GlobalDataContainer(Arc<dyn Any + Send + Sync>);
 
 impl GlobalState {
     /// Returns a new instance of global state.
@@ -40,10 +40,10 @@ impl GlobalState {
     }
 
     /// Returns the requested data type to the caller.
-    pub fn read<'a, T: Send + Sync + 'static>(&mut self) -> Option<&'a T> {
+    pub fn read<T: Send + Sync + 'static>(&mut self) -> Option<Arc<T>> {
         self.table
-            .get(&TypeId::of::<T>())
-            .and_then(|container| container.read::<T>())
+            .get(&TypeId::of::<Arc<T>>())
+            .and_then(|gdc| gdc.read())
     }
 
     /// Checks the given values is storing in the global state.
@@ -65,9 +65,8 @@ impl GlobalDataContainer {
         GlobalDataContainer(Arc::new(AtomicBox::new(Box::new(value))))
     }
 
-    pub fn read<'a, T: Send + Sync + 'static>(&self) -> Option<&'a T> {
-        let inner = self.0.get();
-        inner.downcast_ref::<T>()
+    pub fn read<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
+        self.0.downcast_ref::<Arc<T>>().map(Arc::clone)
     }
 }
 
diff --git a/src/bastion/src/system/mod.rs b/src/bastion/src/system/mod.rs
index 94786d64..c9934e48 100644
--- a/src/bastion/src/system/mod.rs
+++ b/src/bastion/src/system/mod.rs
@@ -1,10 +1,8 @@
 mod global_state;
 mod node;
 
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
 
 use crate::system::node::Node;
 
-lazy_static! {
-    pub static ref SYSTEM: Node = Node::new();
-}
+pub static SYSTEM: Lazy<Node> = Lazy::new(Node::new);

From 0bf4a5eb6e486464fdebb4970d76571639dea0c6 Mon Sep 17 00:00:00 2001
From: o0Ignition0o <jeremy.lempereur@gmail.com>
Date: Tue, 13 Apr 2021 12:31:31 +0200
Subject: [PATCH 2/6] wip

---
 src/bastion/src/system/global_state.rs | 96 ++++++++++++++++++++------
 1 file changed, 75 insertions(+), 21 deletions(-)

diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
index 5853933f..cfdf0217 100644
--- a/src/bastion/src/system/global_state.rs
+++ b/src/bastion/src/system/global_state.rs
@@ -14,13 +14,9 @@ use crate::error::{BastionError, Result};
 
 #[derive(Debug)]
 pub struct GlobalState {
-    table: LOTable<TypeId, GlobalDataContainer>,
+    table: LOTable<TypeId, Arc<dyn Any + Send + Sync>>,
 }
 
-#[derive(Debug, Clone)]
-/// A container for user-defined types.
-struct GlobalDataContainer(Arc<dyn Any + Send + Sync>);
-
 impl GlobalState {
     /// Returns a new instance of global state.
     pub(crate) fn new() -> Self {
@@ -32,18 +28,37 @@ impl GlobalState {
     /// Inserts the given value in the global state. If the value
     /// exists, it will be overridden.
     pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) -> bool {
-        let container = GlobalDataContainer::new(value);
         self.table
-            .insert(TypeId::of::<T>(), container)
+            .insert(
+                TypeId::of::<T>(),
+                Arc::new(value) as Arc<dyn Any + Send + Sync>,
+            )
             .ok()
             .is_some()
     }
 
-    /// Returns the requested data type to the caller.
-    pub fn read<T: Send + Sync + 'static>(&mut self) -> Option<Arc<T>> {
+    /// Invokes a function with the requested data type.
+    pub fn read<T: Send + Sync + 'static>(&mut self, f: impl FnOnce(Option<&T>)) {
+        self.table
+            .get(&TypeId::of::<T>())
+            .map(|value| f(value.downcast_ref()));
+    }
+
+    /// Invokes a function with the requested data type.
+    pub fn write<T: std::fmt::Debug + Send + Sync + 'static, F>(&mut self, f: F) -> Option<Arc<T>>
+    where
+        F: Fn(Option<Arc<T>>) -> Option<Arc<T>>,
+    {
         self.table
-            .get(&TypeId::of::<Arc<T>>())
-            .and_then(|gdc| gdc.read())
+            .replace_with(&TypeId::of::<T>(), |maybe_as_any| {
+                dbg!((&*(maybe_as_any.unwrap())).type_id(), TypeId::of::<T>());
+                let maybe_as_t = maybe_as_any.and_then(|v| v.downcast_ref::<Arc<T>>());
+                let maybe_output = f(maybe_as_t.map(|arc_t| Arc::clone(&arc_t)));
+
+                let maybe_as_any = maybe_output.map(|t| Arc::new(t) as Arc<dyn Any + Send + Sync>);
+                maybe_as_any
+            })
+            .and_then(|as_any| as_any.downcast_ref::<Arc<T>>().map(|t| Arc::clone(&t)))
     }
 
     /// Checks the given values is storing in the global state.
@@ -60,16 +75,6 @@ impl GlobalState {
     }
 }
 
-impl GlobalDataContainer {
-    pub fn new<T: Send + Sync + 'static>(value: T) -> Self {
-        GlobalDataContainer(Arc::new(AtomicBox::new(Box::new(value))))
-    }
-
-    pub fn read<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
-        self.0.downcast_ref::<Arc<T>>().map(Arc::clone)
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use crate::system::global_state::GlobalState;
@@ -135,4 +140,53 @@ mod tests {
         let is_removed = instance.remove::<usize>();
         assert_eq!(is_removed, false);
     }
+
+    #[test]
+    fn test_write_read() {
+        let mut instance = GlobalState::new();
+
+        #[derive(Debug, PartialEq, Clone)]
+        struct Hello {
+            foo: bool,
+            bar: usize,
+        }
+        use core::any::TypeId;
+        use std::sync::Arc;
+        dbg!(
+            TypeId::of::<Hello>(),
+            TypeId::of::<Arc<Hello>>(),
+            TypeId::of::<std::any::Any>(),
+            TypeId::of::<Option<Arc<Hello>>>(),
+        );
+
+        let expected = Hello { foo: true, bar: 42 };
+
+        instance.insert(expected.clone());
+
+        instance.read(|actual: Option<&Hello>| {
+            assert_eq!(&expected, actual.unwrap());
+        });
+
+        let expected_updated = Hello {
+            foo: false,
+            bar: 43,
+        };
+
+        let actual_updated = instance.write::<Hello, _>(|maybe_to_update| {
+            let to_update = maybe_to_update.unwrap();
+
+            let updated = Hello {
+                foo: false,
+                bar: 43,
+            };
+            Some(std::sync::Arc::new(updated))
+        });
+
+        assert_eq!(&expected_updated, &*actual_updated.unwrap());
+
+        instance.read(|updated: Option<&Hello>| {
+            let updated = updated.unwrap();
+            assert_eq!(&expected_updated, updated);
+        });
+    }
 }

From 62c057246a8715e96ac450824aecc869780d4e54 Mon Sep 17 00:00:00 2001
From: o0Ignition0o <jeremy.lempereur@gmail.com>
Date: Tue, 13 Apr 2021 13:08:32 +0200
Subject: [PATCH 3/6] wip

---
 src/bastion/src/system/global_state.rs | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
index cfdf0217..1c55cf40 100644
--- a/src/bastion/src/system/global_state.rs
+++ b/src/bastion/src/system/global_state.rs
@@ -45,20 +45,20 @@ impl GlobalState {
     }
 
     /// Invokes a function with the requested data type.
-    pub fn write<T: std::fmt::Debug + Send + Sync + 'static, F>(&mut self, f: F) -> Option<Arc<T>>
+    pub fn write<T: std::fmt::Debug + Send + Sync + 'static, F>(&mut self, f: F) -> Option<&T>
     where
-        F: Fn(Option<Arc<T>>) -> Option<Arc<T>>,
+        F: Fn(Option<&T>) -> Option<T>,
     {
         self.table
             .replace_with(&TypeId::of::<T>(), |maybe_as_any| {
-                dbg!((&*(maybe_as_any.unwrap())).type_id(), TypeId::of::<T>());
-                let maybe_as_t = maybe_as_any.and_then(|v| v.downcast_ref::<Arc<T>>());
-                let maybe_output = f(maybe_as_t.map(|arc_t| Arc::clone(&arc_t)));
+                let maybe_output = f(maybe_as_any.and_then(|v| (*v).downcast_ref::<T>()));
+
+                dbg!(&maybe_output);
 
                 let maybe_as_any = maybe_output.map(|t| Arc::new(t) as Arc<dyn Any + Send + Sync>);
                 maybe_as_any
             })
-            .and_then(|as_any| as_any.downcast_ref::<Arc<T>>().map(|t| Arc::clone(&t)))
+            .and_then(|as_any| as_any.downcast_ref::<T>())
     }
 
     /// Checks the given values is storing in the global state.
@@ -176,10 +176,11 @@ mod tests {
             let to_update = maybe_to_update.unwrap();
 
             let updated = Hello {
-                foo: false,
-                bar: 43,
+                foo: !to_update.foo,
+                bar: to_update.bar + 1,
             };
-            Some(std::sync::Arc::new(updated))
+
+            Some(updated)
         });
 
         assert_eq!(&expected_updated, &*actual_updated.unwrap());

From c609f65e491627459c8fa7cbb124bc59208a887a Mon Sep 17 00:00:00 2001
From: o0Ignition0o <jeremy.lempereur@gmail.com>
Date: Tue, 13 Apr 2021 13:32:56 +0200
Subject: [PATCH 4/6] wip

---
 src/bastion/src/system/global_state.rs | 24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
index 1c55cf40..3c1ad239 100644
--- a/src/bastion/src/system/global_state.rs
+++ b/src/bastion/src/system/global_state.rs
@@ -45,20 +45,16 @@ impl GlobalState {
     }
 
     /// Invokes a function with the requested data type.
-    pub fn write<T: std::fmt::Debug + Send + Sync + 'static, F>(&mut self, f: F) -> Option<&T>
+    pub fn write<T: std::fmt::Debug + Send + Sync + 'static, F>(&mut self, f: F)
     where
         F: Fn(Option<&T>) -> Option<T>,
     {
-        self.table
-            .replace_with(&TypeId::of::<T>(), |maybe_as_any| {
-                let maybe_output = f(maybe_as_any.and_then(|v| (*v).downcast_ref::<T>()));
-
-                dbg!(&maybe_output);
-
-                let maybe_as_any = maybe_output.map(|t| Arc::new(t) as Arc<dyn Any + Send + Sync>);
-                maybe_as_any
-            })
-            .and_then(|as_any| as_any.downcast_ref::<T>())
+        self.table.replace_with(&TypeId::of::<T>(), |maybe_as_any| {
+            match f(maybe_as_any.and_then(|v| (*v).downcast_ref::<T>())) {
+                Some(output) => Some(Arc::new(output) as Arc<dyn Any + Send + Sync>),
+                None => None,
+            }
+        });
     }
 
     /// Checks the given values is storing in the global state.
@@ -172,7 +168,7 @@ mod tests {
             bar: 43,
         };
 
-        let actual_updated = instance.write::<Hello, _>(|maybe_to_update| {
+        instance.write::<Hello, _>(|maybe_to_update| {
             let to_update = maybe_to_update.unwrap();
 
             let updated = Hello {
@@ -183,11 +179,9 @@ mod tests {
             Some(updated)
         });
 
-        assert_eq!(&expected_updated, &*actual_updated.unwrap());
-
         instance.read(|updated: Option<&Hello>| {
             let updated = updated.unwrap();
-            assert_eq!(&expected_updated, updated);
+            assert_eq!(updated, &expected_updated);
         });
     }
 }

From 81940b8ca23faeeef3536ee5b0e271340a79d35d Mon Sep 17 00:00:00 2001
From: o0Ignition0o <jeremy.lempereur@gmail.com>
Date: Tue, 13 Apr 2021 14:14:02 +0200
Subject: [PATCH 5/6] remove debug statements

---
 src/bastion/src/system/global_state.rs | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
index 3c1ad239..06fcce5a 100644
--- a/src/bastion/src/system/global_state.rs
+++ b/src/bastion/src/system/global_state.rs
@@ -146,14 +146,6 @@ mod tests {
             foo: bool,
             bar: usize,
         }
-        use core::any::TypeId;
-        use std::sync::Arc;
-        dbg!(
-            TypeId::of::<Hello>(),
-            TypeId::of::<Arc<Hello>>(),
-            TypeId::of::<std::any::Any>(),
-            TypeId::of::<Option<Arc<Hello>>>(),
-        );
 
         let expected = Hello { foo: true, bar: 42 };
 

From d2993d809d59295a5449a749e66a742dcb0fc75a Mon Sep 17 00:00:00 2001
From: o0Ignition0o <jeremy.lempereur@gmail.com>
Date: Tue, 13 Apr 2021 21:16:31 +0200
Subject: [PATCH 6/6] ok it doesnt get any uglier than this but it runs

---
 src/bastion/src/system/global_state.rs | 51 +++++++++++++++++---------
 1 file changed, 34 insertions(+), 17 deletions(-)

diff --git a/src/bastion/src/system/global_state.rs b/src/bastion/src/system/global_state.rs
index 06fcce5a..9ee1d40c 100644
--- a/src/bastion/src/system/global_state.rs
+++ b/src/bastion/src/system/global_state.rs
@@ -1,27 +1,32 @@
+use std::sync::Arc;
 /// This module contains implementation of the global state that
 /// available to all actors in runtime. To provide safety and avoid
 /// data races, the implementation is heavily relies on software
 /// transaction memory (or shortly STM) mechanisms to eliminate any
 /// potential data races and provide consistency across actors.
-use std::any::{Any, TypeId};
-use std::ops::Deref;
-use std::sync::Arc;
+use std::{
+    any::{Any, TypeId},
+    sync::RwLock,
+};
+use std::{collections::hash_map::Entry, ops::Deref};
 
 use lever::sync::atomics::AtomicBox;
 use lever::table::lotable::LOTable;
+use lightproc::proc_state::AsAny;
+use std::collections::HashMap;
 
 use crate::error::{BastionError, Result};
 
 #[derive(Debug)]
 pub struct GlobalState {
-    table: LOTable<TypeId, Arc<dyn Any + Send + Sync>>,
+    table: Arc<RwLock<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>>, // todo: remove the arc<rwlock< once we figure it out
 }
 
 impl GlobalState {
     /// Returns a new instance of global state.
     pub(crate) fn new() -> Self {
         GlobalState {
-            table: LOTable::new(),
+            table: Arc::new(RwLock::new(HashMap::new())),
         }
     }
 
@@ -29,17 +34,20 @@ impl GlobalState {
     /// exists, it will be overridden.
     pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) -> bool {
         self.table
+            .write()
+            .unwrap()
             .insert(
                 TypeId::of::<T>(),
                 Arc::new(value) as Arc<dyn Any + Send + Sync>,
             )
-            .ok()
             .is_some()
     }
 
     /// Invokes a function with the requested data type.
     pub fn read<T: Send + Sync + 'static>(&mut self, f: impl FnOnce(Option<&T>)) {
         self.table
+            .read()
+            .unwrap()
             .get(&TypeId::of::<T>())
             .map(|value| f(value.downcast_ref()));
     }
@@ -49,25 +57,34 @@ impl GlobalState {
     where
         F: Fn(Option<&T>) -> Option<T>,
     {
-        self.table.replace_with(&TypeId::of::<T>(), |maybe_as_any| {
-            match f(maybe_as_any.and_then(|v| (*v).downcast_ref::<T>())) {
-                Some(output) => Some(Arc::new(output) as Arc<dyn Any + Send + Sync>),
-                None => None,
-            }
-        });
+        let mut hm = self.table.write().unwrap();
+        let stuff_to_insert = match hm.entry(TypeId::of::<T>()) {
+            Entry::Occupied(data) => f(data.get().downcast_ref()),
+            Entry::Vacant(_) => f(None),
+        };
+
+        if let Some(stuff) = stuff_to_insert {
+            hm.insert(
+                TypeId::of::<T>(),
+                Arc::new(stuff) as Arc<dyn Any + Send + Sync>,
+            );
+        } else {
+            hm.remove(&TypeId::of::<T>());
+        };
     }
 
     /// Checks the given values is storing in the global state.
     pub fn contains<T: Send + Sync + 'static>(&self) -> bool {
-        self.table.contains_key(&TypeId::of::<T>())
+        self.table.read().unwrap().contains_key(&TypeId::of::<T>())
     }
 
     /// Deletes the entry from the global state.
     pub fn remove<T: Send + Sync + 'static>(&mut self) -> bool {
-        match self.table.remove(&TypeId::of::<T>()) {
-            Ok(entry) => entry.is_some(),
-            Err(_) => false,
-        }
+        self.table
+            .write()
+            .unwrap()
+            .remove(&TypeId::of::<T>())
+            .is_some()
     }
 }