🏡 index : ~doyle/shalom.git

author Jordan Doyle <jordan@doyle.la> 2023-11-04 0:53:25.0 +00:00:00
committer Jordan Doyle <jordan@doyle.la> 2023-11-04 0:53:25.0 +00:00:00
commit
d9478009a2677b101b9134b5011b4e5d2c529adc [patch]
tree
f330fc785bf80adc96fa7f039a37430768328ae4
parent
cb5e286540280e450a57780d952f146eed84c904
download
d9478009a2677b101b9134b5011b4e5d2c529adc.tar.gz

Use parking_lot for mutexes



Diff

 Cargo.lock                          | 12 +++++++++-
 shalom/Cargo.toml                   |  3 ++-
 shalom/src/hass_client.rs           |  5 ++--
 shalom/src/oracle.rs                | 53 ++++++++++++++++++--------------------
 shalom/src/subscriptions.rs         |  7 ++---
 shalom/src/widgets/cards/weather.rs |  6 ++--
 6 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index fe776a8..5361944 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -137,6 +137,15 @@ dependencies = [
]

[[package]]
name = "atomic"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
dependencies = [
 "bytemuck",
]

[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2896,6 +2905,8 @@ dependencies = [
name = "shalom"
version = "0.1.0"
dependencies = [
 "atomic",
 "bytemuck",
 "iced",
 "image",
 "internment",
@@ -2904,6 +2915,7 @@ dependencies = [
 "lru 0.12.0",
 "once_cell",
 "palette",
 "parking_lot 0.12.1",
 "reqwest",
 "serde",
 "serde_json",
diff --git a/shalom/Cargo.toml b/shalom/Cargo.toml
index 83eace2..694d855 100644
--- a/shalom/Cargo.toml
+++ b/shalom/Cargo.toml
@@ -6,9 +6,12 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
atomic = "0.6"
bytemuck = "1.14"
iced = { version = "0.10", features = ["tokio", "svg", "lazy", "advanced", "image", "canvas"] }
image = "0.24"
once_cell = "1.18"
parking_lot = "0.12"
internment = "0.7.4"
itertools = "0.11"
keyframe = "1.1"
diff --git a/shalom/src/hass_client.rs b/shalom/src/hass_client.rs
index ea9997d..1d837f5 100644
--- a/shalom/src/hass_client.rs
+++ b/shalom/src/hass_client.rs
@@ -372,7 +372,7 @@ pub mod responses {
        Deserialize, Deserializer,
    };
    use serde_json::value::RawValue;
    use strum::EnumString;
    use strum::{EnumString, FromRepr};
    use yoke::Yokeable;

    use crate::theme::Icon;
@@ -639,7 +639,8 @@ pub mod responses {
        entity_picture: Cow<'a, str>,
    }

    #[derive(Default, Deserialize, Debug, EnumString, Copy, Clone)]
    #[derive(Default, Deserialize, Debug, EnumString, Copy, Clone, FromRepr)]
    #[repr(u16)]
    #[serde(rename_all = "kebab-case")]
    #[strum(serialize_all = "kebab-case")]
    pub enum WeatherCondition {
diff --git a/shalom/src/oracle.rs b/shalom/src/oracle.rs
index 9013b0e..a847601 100644
--- a/shalom/src/oracle.rs
+++ b/shalom/src/oracle.rs
@@ -2,13 +2,16 @@ use std::{
    borrow::Cow,
    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
    str::FromStr,
    sync::{Arc, Mutex},
    sync::{atomic::Ordering, Arc},
    time::Duration,
};

use atomic::Atomic;
use bytemuck::NoUninit;
use iced::futures::{future, Stream, StreamExt};
use internment::Intern;
use itertools::Itertools;
use parking_lot::Mutex;
use time::OffsetDateTime;
use tokio::{
    sync::{broadcast, broadcast::error::RecvError},
@@ -39,7 +42,7 @@ use crate::{
pub struct Oracle {
    client: crate::hass_client::Client,
    rooms: BTreeMap<&'static str, Room>,
    weather: Mutex<Weather>,
    weather: Atomic<Weather>,
    media_players: Mutex<BTreeMap<&'static str, MediaPlayer>>,
    lights: Mutex<BTreeMap<&'static str, Light>>,
    entity_updates: broadcast::Sender<Arc<str>>,
@@ -102,7 +105,7 @@ impl Oracle {
        let this = Arc::new(Self {
            client: hass_client,
            rooms,
            weather: Mutex::new(Weather::parse_from_states(states)),
            weather: Atomic::new(Weather::parse_from_states(states)),
            media_players: Mutex::new(media_players),
            lights: Mutex::new(lights),
            entity_updates: entity_updates.clone(),
@@ -122,7 +125,7 @@ impl Oracle {
    }

    pub fn current_weather(&self) -> Weather {
        *self.weather.lock().unwrap()
        self.weather.load(Ordering::Acquire)
    }

    pub fn subscribe_weather(&self) -> impl Stream<Item = ()> {
@@ -140,7 +143,7 @@ impl Oracle {
    }

    pub fn fetch_light(&self, entity_id: &'static str) -> Option<Light> {
        self.lights.lock().unwrap().get(entity_id).cloned()
        self.lights.lock().get(entity_id).cloned()
    }

    pub fn speaker(&self, speaker_id: &'static str) -> EloquentSpeaker<'_> {
@@ -197,7 +200,6 @@ impl Oracle {
            let mut active_media_players = self
                .media_players
                .lock()
                .unwrap()
                .iter()
                .filter(|(_k, v)| v.is_playing())
                .map(|(k, _v)| *k)
@@ -219,7 +221,7 @@ impl Oracle {
    }

    fn update_media_player_positions(&self, active_media_players: &HashSet<&'static str>) {
        let mut media_players = self.media_players.lock().unwrap();
        let mut media_players = self.media_players.lock();

        for entity_id in active_media_players {
            let Some(MediaPlayer::Speaker(speaker)) = media_players.get_mut(entity_id) else {
@@ -258,19 +260,19 @@ impl Oracle {
                            active_media_players.remove(entity_id);
                        }

                        self.media_players
                            .lock()
                            .unwrap()
                            .insert(entity_id, new_state);
                        self.media_players.lock().insert(entity_id, new_state);
                    }
                    StateAttributes::Weather(attrs) => {
                        *self.weather.lock().unwrap() = Weather::parse_from_state_and_attributes(
                            state_changed.new_state.state.as_ref(),
                            attrs,
                        self.weather.store(
                            Weather::parse_from_state_and_attributes(
                                state_changed.new_state.state.as_ref(),
                                attrs,
                            ),
                            Ordering::Release,
                        );
                    }
                    StateAttributes::Light(attrs) => {
                        self.lights.lock().unwrap().insert(
                        self.lights.lock().insert(
                            Intern::<str>::from(state_changed.entity_id.as_ref()).as_ref(),
                            Light::from((attrs.clone(), state_changed.new_state.state.as_ref())),
                        );
@@ -309,7 +311,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -327,7 +328,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -345,7 +345,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -367,7 +366,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -385,7 +383,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -403,7 +400,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -418,7 +414,6 @@ impl EloquentSpeaker<'_> {
            .oracle
            .media_players
            .lock()
            .unwrap()
            .get_mut(self.speaker_id)
            .unwrap()
        {
@@ -649,7 +644,6 @@ impl Room {
            oracle
                .media_players
                .lock()
                .unwrap()
                .get(v.as_ref())
                .cloned()
                .zip(Some(v))
@@ -660,7 +654,7 @@ impl Room {
    }

    pub fn lights(&self, oracle: &Oracle) -> BTreeMap<&'static str, Light> {
        let lights = oracle.lights.lock().unwrap();
        let lights = oracle.lights.lock();

        self.lights
            .iter()
@@ -669,15 +663,20 @@ impl Room {
    }
}

#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, NoUninit)]
#[repr(C)]
pub struct Weather {
    pub temperature: i16,
    pub high: i16,
    pub low: i16,
    pub condition: WeatherCondition,
    pub condition: u16,
}

impl Weather {
    pub fn weather_condition(self) -> WeatherCondition {
        WeatherCondition::from_repr(self.condition).unwrap_or_default()
    }

    #[allow(clippy::cast_possible_truncation)]
    fn parse_from_state_and_attributes(state: &str, attributes: &StateWeatherAttributes) -> Self {
        let condition = WeatherCondition::from_str(state).unwrap_or_default();
@@ -694,7 +693,7 @@ impl Weather {

        Self {
            temperature: attributes.temperature.round() as i16,
            condition,
            condition: condition as u16,
            high,
            low,
        }
diff --git a/shalom/src/subscriptions.rs b/shalom/src/subscriptions.rs
index 79ba7aa..c6867de 100644
--- a/shalom/src/subscriptions.rs
+++ b/shalom/src/subscriptions.rs
@@ -1,8 +1,9 @@
use std::{hash::Hash, num::NonZeroUsize, sync::Mutex};
use std::{hash::Hash, num::NonZeroUsize};

use iced::{futures::stream, subscription, widget::image, Subscription};
use lru::LruCache;
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use url::Url;

pub fn download_image<I: Hash + 'static, M: 'static>(
@@ -16,7 +17,7 @@ pub fn download_image<I: Hash + 'static, M: 'static>(
    subscription::run_with_id(
        id,
        stream::once(async move {
            if let Some(handle) = CACHE.lock().unwrap().get(&url) {
            if let Some(handle) = CACHE.lock().get(&url) {
                return (resp)(url, handle.clone());
            }

@@ -28,7 +29,7 @@ pub fn download_image<I: Hash + 'static, M: 'static>(
                .unwrap();
            let handle = image::Handle::from_memory(bytes);

            CACHE.lock().unwrap().push(url.clone(), handle.clone());
            CACHE.lock().push(url.clone(), handle.clone());

            (resp)(url, handle)
        }),
diff --git a/shalom/src/widgets/cards/weather.rs b/shalom/src/widgets/cards/weather.rs
index 5d8302b..ee359aa 100644
--- a/shalom/src/widgets/cards/weather.rs
+++ b/shalom/src/widgets/cards/weather.rs
@@ -39,7 +39,9 @@ impl<M> WeatherCard<M> {
    fn build_conditions(&self) -> String {
        format!(
            "{}\nH:{}° L:{}°",
            self.current_weather.condition, self.current_weather.high, self.current_weather.low,
            self.current_weather.weather_condition(),
            self.current_weather.high,
            self.current_weather.low,
        )
    }
}
@@ -151,7 +153,7 @@ impl<M: Clone> Widget<M, Renderer> for WeatherCard<M> {
        });

        let icon_bounds = children.next().unwrap().bounds();
        if let Some(icon) = self.current_weather.condition.icon(day_time) {
        if let Some(icon) = self.current_weather.weather_condition().icon(day_time) {
            renderer.draw(icon.handle(), None, icon_bounds);
        }