From 66f8a83dec7c5ad4d1c490928be535bfd0854e1b Mon Sep 17 00:00:00 2001 From: Mikhail Mitrofanov Date: Thu, 20 Aug 2026 00:07:09 +0300 Subject: [PATCH] Migrate to parking_lot --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/dictionary.rs | 47 +++++++++++++++++++------------------- src/history.rs | 5 ++-- src/import.rs | 11 +++++---- src/lang.rs | 7 +++--- src/navigation.rs | 9 ++++---- src/repetition.rs | 5 ++-- src/repetition_settings.rs | 16 +++++++------ src/repetitions.rs | 21 +++++++++-------- src/selector.rs | 3 ++- src/sync.rs | 23 ++++++++++--------- src/word.rs | 7 +++--- 13 files changed, 85 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 379a3a1..edff5b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2319,6 +2319,7 @@ dependencies = [ "iced", "iced_core", "mimalloc", + "parking_lot", "rand", "rayon", "reqwest", @@ -2326,7 +2327,6 @@ dependencies = [ "rhai", "rodio", "rusqlite", - "serde", "serde_json", "sha2", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 2f57537..b0d03b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ iced = { version = "0.14.0", features = ["tokio", "svg", "lazy"]} iced_core = "0.14.0" rand = "0.10.2" dirs = "6.0.0" -serde = { version = "1.0.229", features = ["derive"] } serde_json = "1.0.151" rhai = { version = "1.25.1", features = ["sync"] } chrono = "0.4.45" @@ -24,6 +23,7 @@ rfd = "0.17.2" mimalloc = "0.1.52" hashbrown = "0.17.1" rayon = "1.12.0" +parking_lot = "0.12.5" [profile.super-release] inherits = "release" diff --git a/src/dictionary.rs b/src/dictionary.rs index 3c3c5a3..4b065b5 100644 --- a/src/dictionary.rs +++ b/src/dictionary.rs @@ -22,7 +22,8 @@ use rand::random_range; use std::fs; use std::ops::Add; use std::path::PathBuf; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use std::time::{Duration, Instant}; #[derive(Clone)] @@ -73,7 +74,7 @@ impl NavigatedPage for DictionaryState { && self.include_map.iter().any(|x| *x) { let mut words = vec![]; - let dict = &self.state.lock().unwrap().dictionary; + let dict = &self.state.lock().dictionary; words = self .include_map @@ -92,7 +93,7 @@ impl NavigatedPage for DictionaryState { if let WordAction(index) = message { let word: WordData; { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let dict = &state.dictionary; word = dict[*index].clone(); } @@ -107,7 +108,7 @@ impl NavigatedPage for DictionaryState { } fn navigated(&mut self) { - let len = self.state.lock().unwrap().dictionary.len(); + let len = self.state.lock().dictionary.len(); self.include_map = vec![false; len]; self.tag_map = Default::default(); @@ -117,7 +118,7 @@ impl NavigatedPage for DictionaryState { fn update(&mut self, message: DictionaryMessage) -> Task { match message { NewWord => { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); let mut word = WordData::new(); word.group_id = state.word_groups[self.selected_group_index].id; @@ -128,21 +129,21 @@ impl NavigatedPage for DictionaryState { SetKey(i, v) => { { - let dict = &mut self.state.lock().unwrap().dictionary; + let dict = &mut self.state.lock().dictionary; dict[i].key = v; } return self.launch_auto_save_offset(i); } SetValue(i, v) => { { - let dict = &mut self.state.lock().unwrap().dictionary; + let dict = &mut self.state.lock().dictionary; dict[i].value = v } return self.launch_auto_save_offset(i); } SetTags(i, mut v) => { { - let dict = &mut self.state.lock().unwrap().dictionary; + let dict = &mut self.state.lock().dictionary; let current_tags_value = dict[i].tags.clone(); @@ -162,7 +163,7 @@ impl NavigatedPage for DictionaryState { } WordAction(i) => { - let state = &mut self.state.lock().unwrap(); + let state = &mut self.state.lock(); let dict = &mut state.dictionary; let word = dict.remove(i); self.include_map.remove(i); @@ -173,7 +174,7 @@ impl NavigatedPage for DictionaryState { IncludeTag(t, v) => { let index; { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); index = state.word_groups[self.selected_group_index].id; } self.tag_map.insert(t, v); @@ -193,7 +194,7 @@ impl NavigatedPage for DictionaryState { Back => {} Test => {} CreateGroup => { - let state = &mut self.state.lock().unwrap(); + let state = &mut self.state.lock(); state.word_groups.push(WordGroup { id: 0.into(), @@ -201,14 +202,14 @@ impl NavigatedPage for DictionaryState { }); } EditGroup(new) => { - let state = &mut self.state.lock().unwrap(); + let state = &mut self.state.lock(); let group = state.word_groups.get_mut(self.selected_group_index); if let Some(group) = group { group.name = new.clone(); } } SaveGroup => { - let state = &mut self.state.lock().unwrap(); + let state = &mut self.state.lock(); let connection = &state.connection; let mut group = state.word_groups[self.selected_group_index].clone(); @@ -219,7 +220,7 @@ impl NavigatedPage for DictionaryState { self.selected_group_index = i; let index; { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); index = state.word_groups[i].id; } self.update_words_include(index) @@ -229,7 +230,7 @@ impl NavigatedPage for DictionaryState { return Task::none(); } { - let state = &mut self.state.lock().unwrap(); + let state = &mut self.state.lock(); if let Some(group) = state.word_groups.get(self.selected_group_index) { let remove_group_id = group.id; @@ -289,7 +290,7 @@ impl NavigatedPage for DictionaryState { impl DictionaryState { pub fn new(state: Arc>) -> Self { - let len = state.lock().unwrap().dictionary.len(); + let len = state.lock().dictionary.len(); let mut result = DictionaryState { include_map: vec![false; len], @@ -309,7 +310,7 @@ impl DictionaryState { } fn save_word(&mut self, i: usize) { - let state = &mut self.state.lock().unwrap(); + let state = &mut self.state.lock(); let connection = &state.connection; let word = &mut state.dictionary[i].clone(); @@ -331,7 +332,7 @@ impl DictionaryState { let time = Instant::now(); let mut col = Column::new().width(Fill); - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let group_id = state.word_groups[self.selected_group_index].id; let dict = &state.dictionary; @@ -443,7 +444,7 @@ impl DictionaryState { } fn filters(&self) -> iced::Element<'_, DictionaryMessage> { - let dict = &self.state.lock().unwrap().dictionary; + let dict = &self.state.lock().dictionary; iced::widget::column![ text_input("Поиск", &self.search) @@ -499,7 +500,7 @@ impl DictionaryState { fn update_tags(&mut self) { let mut tags_list: HashSet = HashSet::new(); - let dict = &self.state.lock().unwrap().dictionary; + let dict = &self.state.lock().dictionary; dict.iter().for_each(|element| { split_with_coma(element.tags.as_str()) @@ -540,7 +541,7 @@ impl DictionaryState { return; } - let dict = &self.state.lock().unwrap().dictionary; + let dict = &self.state.lock().dictionary; let time = Instant::now(); self.include_map = dict @@ -560,7 +561,7 @@ impl DictionaryState { let mut row = Row::new(); row = row.push(button("+").style(text).on_press(CreateGroup)); - let state = &self.state.lock().unwrap(); + let state = &self.state.lock(); let groups = &state.word_groups; for (index, group) in groups.iter().enumerate() { @@ -598,7 +599,7 @@ impl DictionaryState { } fn add_word_button(&self) -> iced::Element<'_, DictionaryMessage> { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let group_id = state.word_groups[self.selected_group_index].id; let button = button("Добавить слово").style(jl_button); diff --git a/src/history.rs b/src/history.rs index d055d2f..7e17885 100644 --- a/src/history.rs +++ b/src/history.rs @@ -9,7 +9,8 @@ use iced::alignment::Horizontal::Center; use iced::widget::space::horizontal; use iced::widget::*; use iced::{Element, Fill, FillPortion, Task}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; #[derive(Clone)] pub struct HistoryState { @@ -47,7 +48,7 @@ impl NavigatedPage for HistoryState { impl HistoryState { pub fn new(id: crate::lang::Id, state: Arc>) -> Self { - let state = state.lock().unwrap(); + let state = state.lock(); let history = get_history_of_set(id); let words = history .iter() diff --git a/src/import.rs b/src/import.rs index 3ead526..c2aeb04 100644 --- a/src/import.rs +++ b/src/import.rs @@ -21,7 +21,8 @@ use rusqlite::Connection; use std::fs::{File, OpenOptions}; use std::io::BufReader; use std::path::PathBuf; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use tokio::task::spawn_blocking; use zip::ZipArchive; @@ -141,7 +142,7 @@ impl NavigatedPage for ImportState { back_overlay( { if let Some(value) = &self.progress { - column![progress_bar(0f32..=1f32, *value.lock().unwrap()),] + column![progress_bar(0f32..=1f32, *value.lock()),] .spacing(QUARTER_SPACING) .into() } else { @@ -444,7 +445,7 @@ impl ImportState { name: group.name.clone(), }; { - let state = state.lock().unwrap(); + let state = state.lock(); add_group(&mut group_entity, &state.connection); } @@ -480,14 +481,14 @@ impl ImportState { words_list.push(word); } - let mut state = state.lock().unwrap(); + let mut state = state.lock(); let connection = &mut state.connection; let mut index = 0; let total_len = words_list.len() as f32 / 1024.0; for word in &mut words_list.chunks_mut(1024) { add_words(word, connection); index += 1; - let mut progress = progress.lock().unwrap(); + let mut progress = progress.lock(); *progress = index as f32 / total_len; } diff --git a/src/lang.rs b/src/lang.rs index 14cb7b6..f842e8e 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -18,7 +18,8 @@ use std::collections::HashMap; use std::fmt::{Display, Formatter}; use std::num::ParseIntError; use std::str::FromStr; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use std::time::Instant; const MAX_HISTORY_LEN: usize = 20; @@ -354,7 +355,7 @@ pub struct DeckData { impl DeckData { pub fn new(settings: &DeckSettings, state: Arc>) -> Self { let state_for = state.clone(); - let state_locked = state.lock().unwrap(); + let state_locked = state.lock(); let mut current_set = load_stats_of_deck(settings, &state_locked.connection); let last_list: Vec<_> = settings @@ -446,7 +447,7 @@ impl DeckData { self.order_module = OrderModule::WorstWordsSRS(module); } } - update_stat_score(word, &self.state.lock().unwrap().connection); + update_stat_score(word, &self.state.lock().connection); push_note( self.settings.id, HistoryItem { diff --git a/src/navigation.rs b/src/navigation.rs index 92d1f56..4709400 100644 --- a/src/navigation.rs +++ b/src/navigation.rs @@ -30,7 +30,8 @@ use iced::keyboard::Event; use iced::{Element, Task}; use reqwest::Error; use rusqlite::Connection; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use std::time::Instant; impl Default for ScreenState { @@ -97,7 +98,7 @@ impl ScreenState { let reading_additional_task = Task::perform(Self::load_additional_data(), |data| data); let final_task; - let state_guard = state.app_state.lock().unwrap(); + let state_guard = state.app_state.lock(); if state_guard.sync_data.auto_web_fetch { let key = state_guard.sync_data.key.clone().unwrap(); final_task = Task::batch([ @@ -169,13 +170,13 @@ impl ScreenState { } if let DataLoaded(data) = message { - self.app_state.lock().unwrap().activity = data; + self.app_state.lock().activity = data; return Task::none(); } if let UpdateData = message { println!("Loading data"); - let mut state = self.app_state.lock().unwrap(); + let mut state = self.app_state.lock(); if cfg!(windows) { state.connection = Connection::open_in_memory().unwrap(); } diff --git a/src/repetition.rs b/src/repetition.rs index 7d24a08..20ce8b0 100644 --- a/src/repetition.rs +++ b/src/repetition.rs @@ -13,7 +13,8 @@ use iced::widget::{Column, button, column, container, row, rule, space, text, to use iced::{Element, Fill, Task, Theme, alignment, keyboard}; use rodio::MixerDeviceSink; use std::collections::HashSet; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use tokio::task::spawn_blocking; pub struct RepetitionState { @@ -148,7 +149,7 @@ impl RepetitionState { } fn increment_counter(&mut self) { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); let id = self.settings.id; let activity = state.activity.get_mut(&id); diff --git a/src/repetition_settings.rs b/src/repetition_settings.rs index 9ccad7d..f7a3a96 100644 --- a/src/repetition_settings.rs +++ b/src/repetition_settings.rs @@ -11,9 +11,11 @@ use iced::widget::{button, column, row, scrollable, space, text, text_input}; use iced::{Element, Task}; use iced_core::Length::Fill; use iced_core::{Padding, Theme, color}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use std::time::Duration; + pub struct RepetitionSettingsState { set: DeckSettings, index: usize, @@ -23,10 +25,10 @@ pub struct RepetitionSettingsState { } impl RepetitionSettingsState { - pub(crate) fn new(index: usize, p1: Arc>) -> RepetitionSettingsState { + pub(crate) fn new(index: usize, state: Arc>) -> RepetitionSettingsState { let set; { - let local_state = p1.lock().unwrap(); + let local_state = state.lock(); set = local_state.decks[index].clone(); } let filter_state = set.check_filter(); @@ -34,7 +36,7 @@ impl RepetitionSettingsState { RepetitionSettingsState { index, set, - state: p1, + state, real_delete: false, correct_filter: filter_state, } @@ -55,7 +57,7 @@ impl NavigatedPage for RepetitionSettingsState { match message { Back => {} Save => { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); update_deck(&mut self.set, &state.connection); state.decks[self.index] = self.set.clone(); } @@ -73,7 +75,7 @@ impl NavigatedPage for RepetitionSettingsState { self.correct_filter = self.set.check_filter(); } TryFilter => { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let count = self.set.get_word_list(&state).len(); self.set.count = Some(count); } @@ -85,7 +87,7 @@ impl NavigatedPage for RepetitionSettingsState { RootMessage::RepetitionSettings(RevertDeleteSet) }); } - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); delete_set(&self.set, &state.connection); state.decks.remove(self.index); return Task::done(RootMessage::RepetitionSettings(Back)); diff --git a/src/repetitions.rs b/src/repetitions.rs index 67f009f..3d3c106 100644 --- a/src/repetitions.rs +++ b/src/repetitions.rs @@ -23,7 +23,8 @@ use iced_core::Padding; use iced_core::border::Radius; use iced_core::svg::Handle; use std::ops::Deref; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; #[derive(Clone)] pub struct RepetitionsState { @@ -47,7 +48,7 @@ impl NavigatedPage for RepetitionsState { let selected_set = self.selected_deck_mut().unwrap(); if selected_set.append_mode == AppendMode::Full { - Self::append_all_words(&mut clone.lock().unwrap(), selected_set); + Self::append_all_words(&mut clone.lock(), selected_set); selected_set.existing_words_indices = selected_set.available_words_indices.clone(); } else { if selected_set @@ -80,7 +81,7 @@ impl NavigatedPage for RepetitionsState { } fn navigated(&mut self) { let index = self.selected_deck_index.unwrap(); - let state = self.state.lock().unwrap(); + let state = self.state.lock(); if let Some(global_deck) = state.decks.get(index) { if global_deck.id != self.selected_deck().unwrap().id { drop(state); @@ -116,7 +117,7 @@ impl NavigatedPage for RepetitionsState { self.clear_selection(); let deck = self.decks.remove(index); if deck.id.is_valid() { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.decks.remove(index); self.decks = self .decks @@ -137,7 +138,7 @@ impl NavigatedPage for RepetitionsState { self.select_deck(index); let deck = self.selected_deck().unwrap(); if deck.existing_words_indices.is_none() { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let added: Vec<_> = load_stats_of_deck(deck, &state.connection) .iter() .map(|c| self.word_id_index_map[&c.word_id]) @@ -151,7 +152,7 @@ impl NavigatedPage for RepetitionsState { } Save => { let mut deck = self.selected_deck().unwrap().clone(); - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); { update_deck(&mut deck.general_settings, &state.connection); if let Some(index) = deck.index { @@ -176,7 +177,7 @@ impl NavigatedPage for RepetitionsState { deck.general_settings.filter = value; } TryFilter => { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let deck = self.selected_deck().unwrap(); let count = deck.get_word_list(&state).len(); drop(state); @@ -220,7 +221,7 @@ impl NavigatedPage for RepetitionsState { } let deck = self.selected_deck().unwrap(); - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); Self::append_words(&mut state, &deck.general_settings, adding.into_iter()); } } @@ -253,7 +254,7 @@ impl NavigatedPage for RepetitionsState { impl RepetitionsState { pub(crate) fn new(state: Arc>) -> RepetitionsState { - let state_ = state.lock().unwrap(); + let state_ = state.lock(); let mut map = HashMap::with_capacity(state_.dictionary.len()); state_ @@ -408,7 +409,7 @@ impl RepetitionsState { fn activity_bar(&self, deck: &DeckSettings) -> Element<'_, RepetitionsMessage> { const MAX_DAY_COUNT: f32 = 128.0; - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let history = state.activity.get(&deck.id); let mut counts: Vec = vec![0; 30 * 7]; let now = Local::now().date_naive(); diff --git a/src/selector.rs b/src/selector.rs index 8eae3db..3156a77 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -15,7 +15,8 @@ use iced::{Element, Task, alignment}; use iced_core::Alignment::Center; use iced_core::Background; use iced_core::Color; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; pub struct SelectorState { pub set: KanaSet, diff --git a/src/sync.rs b/src/sync.rs index a3aa52b..7c2e4fb 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -9,7 +9,8 @@ use iced::widget::button::danger; use iced::widget::container::rounded_box; use iced::widget::{button, column, container, progress_bar, row, space, text, toggler}; use iced::{Center, Element, Fill, Font, Length, Task}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; use std::time::Duration; #[derive(Clone)] @@ -52,7 +53,7 @@ impl NavigatedPage for SyncState { match message { Back => {} CopyKey => { - let state = self.state.lock().unwrap(); + let state = self.state.lock(); let key = state.sync_data.key.clone().unwrap(); return iced::clipboard::write(key) .map(|_val: String| RootMessage::Sync(KeyCopied)); @@ -69,14 +70,14 @@ impl NavigatedPage for SyncState { if !validate_id(&new_id) { return Task::none(); } - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.sync_data.key = Some(new_id.clone()); set_setting("SYNC_KEY".to_string(), new_id, &state.connection); } Send => { self.prepare_to_db_interaction(); - let id = self.state.lock().unwrap().sync_data.key.clone().unwrap(); + let id = self.state.lock().sync_data.key.clone().unwrap(); let tasks = Task::batch([ Task::perform( async { tokio::time::sleep(Duration::from_millis(200)).await }, @@ -88,7 +89,7 @@ impl NavigatedPage for SyncState { return tasks; } GetLast => { - let id = self.state.lock().unwrap().sync_data.key.clone().unwrap(); + let id = self.state.lock().sync_data.key.clone().unwrap(); let tasks = Task::batch([ Task::perform( async { tokio::time::sleep(Duration::from_millis(200)).await }, @@ -116,7 +117,7 @@ impl NavigatedPage for SyncState { let mut updated_state = AppState::new(); fill_state(&mut updated_state); - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.sync_data = updated_state.sync_data; state.connection = updated_state.connection; state.decks = updated_state.decks; @@ -125,14 +126,14 @@ impl NavigatedPage for SyncState { } Disable => {} DisableSync => { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.sync_data.key = None; delete_settings("SYNC_KEY".to_string(), &state.connection); delete_settings("AUTO_WEB_FETCH".to_string(), &state.connection); } SwitchAutoSync => { self.auto_fetch = !self.auto_fetch; - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.sync_data.auto_web_fetch = self.auto_fetch; set_setting( "AUTO_WEB_FETCH".to_string(), @@ -159,7 +160,7 @@ impl SyncState { pub fn new(state: Arc>) -> SyncState { let auto_fetch; { - auto_fetch = state.lock().unwrap().sync_data.auto_web_fetch; + auto_fetch = state.lock().sync_data.auto_web_fetch; } Self { auto_fetch, @@ -176,7 +177,7 @@ impl SyncState { space().into() }; { - if let Some(key) = self.state.lock().unwrap().sync_data.key.clone() { + if let Some(key) = self.state.lock().sync_data.key.clone() { column![ text!("Ваш ключ синхронизации"), container( @@ -233,7 +234,7 @@ impl SyncState { } self.frozen = true; self.progress = 0.0; - let state = self.state.lock().unwrap(); + let state = self.state.lock(); state .connection .query_row("PRAGMA wal_checkpoint(TRUNCATE)", [], |_| Ok(())) diff --git a/src/word.rs b/src/word.rs index 84cc90e..8de98e2 100644 --- a/src/word.rs +++ b/src/word.rs @@ -8,7 +8,8 @@ use crate::{AppState, RootMessage}; use iced::widget::button::danger; use iced::widget::{button, column, row, rule, scrollable, text, text_input}; use iced::{Element, Fill, Task}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; +use parking_lot::Mutex; #[derive(Clone)] pub struct WordState { @@ -31,13 +32,13 @@ impl NavigatedPage for WordState { match message { Back => {} Save => { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.dictionary[self.index] = self.word.clone(); update_word(&mut self.word, &state.connection); return Task::done(RootMessage::Word(Back)); } Delete => { - let mut state = self.state.lock().unwrap(); + let mut state = self.state.lock(); state.dictionary.remove(self.index); delete_word(&self.word, &state.connection); return Task::done(RootMessage::Word(Back));