1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#![allow(non_snake_case)]
#![allow(unused_parens)]

mod guard;
mod holder;

use std::sync::Arc;
use parking_lot::RawRwLock;
use parking_lot::lock_api::RwLockReadGuard;
use crate::guard::Guard;
use crate::holder::Holder;

/// HArcMut : Hyultis Arc Mut
/// store a content inside a Arc<RwLock<>> to be a mutable between thread
/// use a cloned "local" version of the content, for faster/simpler access
pub struct HArcMut<T>
	where T: Clone
{
	_shared: Arc<Holder<T>>,
	_local: Holder<T>,
}

impl<T> HArcMut<T>
	where T: Clone
{
	pub fn new(data: T) -> Self
	{
		return HArcMut
		{
			_local: Holder::new(data.clone()),
			_shared: Arc::new(Holder::new(data)),
		};
	}
	
	/// get readonly content
	pub fn get(&self) -> RwLockReadGuard<'_, RawRwLock, T>
	{
		self._local.updateIfOlder(self._shared.as_ref());
		return self._local.Data.read();
	}
	
	/// update local and shared content via a guard
	/// and readonly part by cloning on drop (*beware*: dropping guard is important to get shared and local updated and sync)
	pub fn get_mut(&self) -> Guard<'_, T>
	{
		Guard{
			context: self,
			guarded: self._shared.Data.write()
		}
	}
	
	/// update local and shared content (and readonly part by cloning)
	/// this is a bit slower than get_mut, but dont need a drop.
	/// note : I is simply ignored (QOL)
	pub fn update<I>(&self, mut fnUpdate: impl FnMut(&mut T) -> I)
	{
		let tmp = &mut self._shared.Data.write();
		fnUpdate(tmp);
		let updatetime = self._shared.updateTime();
		*self._local.TimeUpdate.write() = updatetime;
		*self._local.Data.write() = tmp.clone();
	}
	
	/// if closure return "true" update local part by cloning the updated shared content
	/// *beware if you update the &mut, but returning false* : shared and local data will be desync
	pub fn updateIf(&self, mut fnUpdate: impl FnMut(&mut T) -> bool)
	{
		let tmp = &mut self._shared.Data.write();
		if (fnUpdate(tmp))
		{
			let updatetime = self._shared.updateTime();
			*self._local.TimeUpdate.write() = updatetime;
			*self._local.Data.write() = tmp.clone();
		}
	}

	/// must be regulary manually checked
	/// if true, the local storage must drop this local instance
	pub fn isWantDrop(&self) -> bool
	{
		self._local.updateIfOlder(self._shared.as_ref());
		return *self._local.WantDrop.read();
	}

	/// used to set the state of shared intance to "Want drop"
	/// and normally be used juste before dropping the local instance
	pub fn setDrop(&self)
	{
		*self._shared.WantDrop.write() = true;
		let time = self._shared.updateTime();
		
		*self._local.WantDrop.write() = true;
		*self._local.TimeUpdate.write() = time;
	}
	
	//////////////////// PRIVATE /////////////////
	
	fn update_internal(&self, tmp : T)
	{
		let updatetime = self._shared.updateTime();
		*self._local.TimeUpdate.write() = updatetime;
		*self._local.Data.write() = tmp;
	}
}

impl<T> Clone for HArcMut<T>
	where T: Clone
{
	fn clone(&self) -> Self {
		return HArcMut {
			_shared: self._shared.clone(),
			_local: self._local.clone(),
		};
	}
}


/* Hope, one day ?
impl<T> HArcMut<T>
	where T: Clone + Any
{
	pub fn get_as<I: 'static>(&self) -> Option<RwLockReadGuard<'_,RawRwLock,I>>
	{
		self._local.updateIfOlder(self._shared.as_ref());
		let tmp = &self._local.Data as &dyn Any;
		return match tmp.downcast_ref::<RwLock<I>>() {
			None => None,
			Some(x) => {
				Some(x.read())
			}
		};
	}
	
	pub fn get_mut_as<I>(&self) -> Option<Guard<'_, RwLockWriteGuard<'static,I>>>
		where I: 'static + Clone,
		RwLockWriteGuard<'static,I> : Clone
	{
		let tmp = &self._shared.Data as &dyn Any;
		return match tmp.downcast_ref::<RwLock<I>>() {
			None => None,
			Some(x) => {
				Guard::<I>{
					context: self,
					guarded: x.write()
				}
			}
		};
	}
}
*/