use crate::*;
impl<T> Signal<T>
where
T: Clone + PartialEq + 'static,
{
pub fn create(value: T) -> Self {
let signal_inner: Rc<RefCell<SignalInner<T>>> =
Rc::new(RefCell::new(SignalInner::new(value, Vec::new(), true)));
let addr: usize = Rc::as_ptr(&signal_inner) as usize;
signal_inner_registry_mut().insert(addr, signal_inner as Rc<dyn Any>);
let mut signal: Signal<T> = Signal::new(0, std::marker::PhantomData);
signal.set_inner(addr);
signal
}
pub(crate) fn get_inner_addr(&self) -> usize {
self.get_inner()
}
pub fn get(&self) -> T {
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
rc.borrow().get_value().clone()
}
pub fn try_get(&self) -> Option<T> {
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
Some(rc.borrow().get_value().clone())
}
pub fn subscribe<F>(&self, callback: F)
where
F: FnMut() + 'static,
{
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
rc.borrow_mut().get_mut_listeners().push(Box::new(callback));
}
pub fn replace_subscribe<F>(&self, callback: F)
where
F: FnMut() + 'static,
{
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
let listeners: &mut Vec<Box<dyn FnMut()>> = inner.get_mut_listeners();
listeners.clear();
listeners.push(Box::new(callback));
}
pub fn clear_listeners(&self) {
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
inner.set_alive(false);
inner.get_mut_listeners().clear();
}
pub fn set(&self, value: T) {
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
let mut listeners: Vec<Box<dyn FnMut()>> = Vec::new();
{
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
if !inner.get_alive() {
return;
}
if *inner.get_value() == value {
return;
}
inner.set_value(value);
swap(inner.get_mut_listeners(), &mut listeners);
}
for listener in listeners.iter_mut() {
listener();
}
{
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
swap(inner.get_mut_listeners(), &mut listeners);
}
schedule_signal_update();
}
pub fn set_silent(&self, value: T) {
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
let mut listeners: Vec<Box<dyn FnMut()>> = Vec::new();
{
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
if !inner.get_alive() {
return;
}
if *inner.get_value() == value {
return;
}
inner.set_value(value);
swap(inner.get_mut_listeners(), &mut listeners);
}
for listener in listeners.iter_mut() {
listener();
}
{
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
swap(inner.get_mut_listeners(), &mut listeners);
}
}
pub fn try_set(&self, value: T) -> bool {
let rc: Rc<RefCell<SignalInner<T>>> = get_signal_inner_rc(self.get_inner());
let mut listeners: Vec<Box<dyn FnMut()>> = Vec::new();
{
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
if !inner.get_alive() {
return false;
}
if *inner.get_value() == value {
return false;
}
inner.set_value(value);
swap(inner.get_mut_listeners(), &mut listeners);
}
for listener in listeners.iter_mut() {
listener();
}
{
let mut inner: RefMut<SignalInner<T>> = rc.borrow_mut();
swap(inner.get_mut_listeners(), &mut listeners);
}
schedule_signal_update();
true
}
}
impl<T> Deref for Signal<T>
where
T: Clone + PartialEq + 'static,
{
type Target = T;
fn deref(&self) -> &Self::Target {
panic!("Signal does not support direct dereference; use .get() instead");
}
}
impl<T> DerefMut for Signal<T>
where
T: Clone + PartialEq + 'static,
{
fn deref_mut(&mut self) -> &mut Self::Target {
panic!("Signal does not support direct dereference; use .set() instead");
}
}
impl<T> Clone for Signal<T>
where
T: Clone + PartialEq + 'static,
{
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Signal<T> where T: Clone + PartialEq + 'static {}
unsafe impl<T> Sync for SignalCell<T> where T: Clone + PartialEq + 'static {}
impl<T> SignalCell<T>
where
T: Clone + PartialEq + 'static,
{
pub const fn empty() -> Self {
Self {
inner: UnsafeCell::new(None),
}
}
pub fn set(&self, signal: Signal<T>) {
unsafe {
let ptr: &mut Option<Signal<T>> = &mut *self.get_inner().get();
if ptr.is_some() {
panic!("SignalCell::set called on an already-initialized cell");
}
*ptr = Some(signal);
}
}
pub fn get(&self) -> Signal<T> {
unsafe {
let ptr: &Option<Signal<T>> = &*self.get_inner().get();
match ptr {
Some(signal) => *signal,
None => panic!("SignalCell::get called on an uninitialized cell"),
}
}
}
}
impl<T> Default for SignalCell<T>
where
T: Clone + PartialEq + 'static,
{
fn default() -> Self {
Self {
inner: UnsafeCell::new(None),
}
}
}
unsafe impl Sync for SignalInnerRegistryCell {}