relm4::shared_state

Struct SharedState

source
pub struct SharedState<Data> { /* private fields */ }
Expand description

A type that allows you to share information across your application easily. Get immutable and mutable access to the data and subscribe to changes.

§Panics

SharedState uses a RwLock internally. If you use Self::read() and Self::write() in the same scope your code might be stuck in a deadlock or panic.

Implementations§

source§

impl<Data> SharedState<Data>
where Data: Default,

source

pub const fn new() -> Self

Create a new SharedState variable.

The data will be initialized lazily on the first access.

§Example
use relm4::SharedState;
static STATE: SharedState<MyData> = SharedState::new();
Examples found in repository?
examples/tab_game.rs (line 23)
23
static GAME_STATE: SharedState<GameState> = SharedState::new();
source

pub fn subscribe<Msg, F>(&self, sender: &Sender<Msg>, f: F)
where F: Fn(&Data) -> Msg + 'static + Send + Sync, Msg: Send + 'static,

Subscribe to a shared state type. Any subscriber will be notified with a message every time you modify the shared state using Self::get_mut().

use relm4::SharedState;
static STATE: SharedState<u8> = SharedState::new();

let (sender, receiver) = relm4::channel();

// Every time we modify the data, we will receive
// the updated value as a message.
STATE.subscribe(&sender, |data| *data);

{
    let mut data = STATE.write();
    *data += 1;
}

assert_eq!(receiver.recv_sync().unwrap(), 1);
Examples found in repository?
examples/tab_game.rs (line 145)
144
145
146
147
    fn init_model(value: Self::Init, _index: &DynamicIndex, sender: FactorySender<Self>) -> Self {
        GAME_STATE.subscribe(sender.input_sender(), |_| CounterMsg::Update);
        Self { id: value }
    }
source

pub fn subscribe_optional<Msg, F>(&self, sender: &Sender<Msg>, f: F)
where F: Fn(&Data) -> Option<Msg> + 'static + Send + Sync, Msg: Send + 'static,

An alternative version of subscribe() that only send a message if the closure returns Some.

source

pub fn read(&self) -> SharedStateReadGuard<'_, Data>

Get immutable access to the shared data.

Returns a RAII guard which will release this thread’s shared access once it is dropped.

The calling thread will be blocked until there are no more writers which hold the lock (see RwLock).

§Panics

This function will panic if the internal RwLock is poisoned. A RwLock is poisoned whenever a writer panics while holding an exclusive lock. The failure will occur immediately after the lock has been acquired.

Also, this function might panic when called if the lock is already held by the current thread.

Examples found in repository?
examples/tab_game.rs (line 156)
149
150
151
152
153
154
155
156
157
158
159
    fn init_widgets(
        &mut self,
        index: &DynamicIndex,
        root: Self::Root,
        returned_widget: &adw::TabPage,
        sender: FactorySender<Self>,
    ) -> Self::Widgets {
        let state = GAME_STATE.read();
        let widgets = view_output!();
        widgets
    }
source

pub fn try_read( &self, ) -> Result<SharedStateReadGuard<'_, Data>, TryLockError<RwLockReadGuard<'_, Data>>>

Get immutable access to the shared data.

Similar to read, but doesn’t block so this function simply returns an Err if the data is already locked (or poisoned).

source

pub fn write(&self) -> SharedStateWriteGuard<'_, Data>

Get mutable access to the shared data.

Returns a RAII guard which will notify all subscribers and release this thread’s shared access once it is dropped.

This function will not return while other writers or other readers currently have access to the internal lock (see RwLock).

§Panics

This function will panic if the internal RwLock is poisoned. A RwLock is poisoned whenever a writer panics while holding an exclusive lock. The failure will occur immediately after the lock has been acquired.

Also, this function might panic when called if the lock is already held by the current thread.

§Example
static STATE: SharedState<u8> = SharedState::new();

// Overwrite the current value with 1
*STATE.write() = 1;
§Panic example
static STATE: SharedState<u8> = SharedState::new();

let read_guard = STATE.read();

// This is fine
let another_read_guard = STATE.read();

// This might panic or result in a dead lock
// because you cannot read and write at the same time.
// To solve this, drop all read guards on this thread first.
let another_write_guard = STATE.write();
Examples found in repository?
examples/tab_game.rs (line 256)
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
    fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>, _root: &Self::Root) {
        match msg {
            AppMsg::StartGame(index) => {
                self.start_index = Some(index);
                sender.command(|sender, _| async move {
                    for i in (1..4).rev() {
                        *GAME_STATE.write() = GameState::Countdown(i);
                        relm4::tokio::time::sleep(Duration::from_millis(1000)).await;
                    }
                    *GAME_STATE.write() = GameState::Running;
                    for _ in 0..20 {
                        relm4::tokio::time::sleep(Duration::from_millis(500)).await;
                        sender.send(false).unwrap();
                    }
                    relm4::tokio::time::sleep(Duration::from_millis(1000)).await;
                    sender.send(true).unwrap();
                });
            }
            AppMsg::StopGame => {
                *GAME_STATE.write() = GameState::Guessing;
            }
            AppMsg::SelectedGuess(index) => {
                *GAME_STATE.write() = GameState::End(index == self.start_index.take().unwrap());
            }
        }
    }
source

pub fn try_write( &self, ) -> Result<SharedStateWriteGuard<'_, Data>, TryLockError<RwLockWriteGuard<'_, Data>>>

Get mutable access to the shared data.

Similar to write, but doesn’t block so this function simply returns an Err if the data is already locked (or poisoned).

source

pub fn get_mut(&mut self) -> &mut Data

Get mutable access to the shared data. Since this call borrows the SharedState mutably, no actual locking needs to take place, but the mutable borrow statically guarantees no locks exist.

This method will not notify any subscribers!

§Panics

This function will panic if the internal RwLock is poisoned. A RwLock is poisoned whenever a writer panics while holding an exclusive lock. The failure will occur immediately after the lock has been acquired.

source

pub fn read_inner(&self) -> RwLockReadGuard<'_, Data>

Get immutable access to the shared data.

This method will not notify any subscribers!

§Panics

This function will panic if the internal RwLock is poisoned. A RwLock is poisoned whenever a writer panics while holding an exclusive lock. The failure will occur immediately after the lock has been acquired.

Also, this function might panic when called if the lock is already held by the current thread.

source

pub fn write_inner(&self) -> RwLockWriteGuard<'_, Data>

Get mutable access to the shared data.

This method will not notify any subscribers!

§Panics

This function will panic if the internal RwLock is poisoned. A RwLock is poisoned whenever a writer panics while holding an exclusive lock. The failure will occur immediately after the lock has been acquired.

Also, this function might panic when called if the lock is already held by the current thread.

Trait Implementations§

source§

impl<Data: Debug> Debug for SharedState<Data>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<Data> Default for SharedState<Data>
where Data: Default,

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<Data> !Freeze for SharedState<Data>

§

impl<Data> RefUnwindSafe for SharedState<Data>

§

impl<Data> Send for SharedState<Data>
where Data: Send,

§

impl<Data> Sync for SharedState<Data>
where Data: Send + Sync,

§

impl<Data> Unpin for SharedState<Data>
where Data: Unpin,

§

impl<Data> UnwindSafe for SharedState<Data>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<C> AsyncPosition<()> for C

source§

fn position(_index: usize)

Returns the position. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<C, I> Position<(), I> for C

source§

fn position(&self, _index: &I)

Returns the position. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more