前提・実現したいこと
Rustのライフタイムで解決の仕方が分からないところがあります。
何か、知っていることや考え方を知っていたら教えてほしいです。
該当コード
以下のパターンの解決をしたいです。
rust
1// 2use anyhow::Result; 3use std::{collections::HashMap, vec}; 4use std::string::ToString; 5use std::ops::{Deref, DerefMut}; 6use strum::IntoEnumIterator; 7use strum_macros::{EnumIter, ToString}; 8use std::sync::Arc; 9use tokio::sync::RwLock; 10 11#[derive(Debug, Default, Clone)] 12struct Data { 13 id: String, 14 name: String, 15 value: i32, 16} 17 18#[derive(EnumIter, ToString, Debug, Hash, PartialEq, Eq, Clone)] 19enum Index { 20 PatternA, 21 PatternB, 22 PatternC, 23 PatternD, 24} 25 26#[derive(Debug, Default, Clone)] 27struct Helper { 28 up: Vec<Data>, 29 down: Vec<Data>, 30} 31impl Helper { 32 pub fn new() -> Self { 33 Self { 34 up: vec![], 35 down: vec![], 36 } 37 } 38} 39 40#[derive(Debug, Default, Clone)] 41pub struct Target { 42 store: HashMap<Index, Helper>, 43} 44 45impl Deref for Target { 46 type Target = HashMap<Index, Helper>; 47 48 fn deref(&self) -> &Self::Target { 49 &self.store 50 } 51} 52 53impl DerefMut for Target { 54 fn deref_mut(&mut self) -> &mut HashMap<Index, Helper> { 55 &mut self.store 56 } 57} 58 59impl Target { 60 pub fn new() -> Self { 61 Self { 62 store: HashMap::new(), 63 } 64 } 65 66 pub fn init(&mut self) -> Result<()> { 67 Index::iter().for_each(|i| { 68 self.store.insert( 69 i, 70 Helper::new(), 71 ); 72 }); 73 74 Ok(()) 75 } 76 77 pub async fn update<'a>(&'a mut self) -> Result<()> { 78 79 let multi_ref = Arc::new(RwLock::new(&self.store)); 80 let mut executor = vec![]; 81 82 for index in Index::iter() { 83 let key= format!("{}:id", index.to_string()); 84 85 let clone_ref = Arc::clone(&multi_ref); 86 let mut wt = clone_ref.write().await; 87 let mut data_store = wt.deref_mut().clone(); 88 89 if let Some(data_vec) = data_store.get_mut(&index) { 90 data_vec.up.sort_by(|a, b| b.value.cmp(&a.value)); 91 92 data_vec.down.sort_by(|a, b| a.value.cmp(&b.value)); 93 94 let up_task = insert_db(&data_vec.up, &key); 95 let down_taks = insert_db(&data_vec.down, &key); 96 97 executor.push(up_task); 98 executor.push(down_taks); 99 } 100 } 101 102 futures::future::join_all(executor).await; 103 Ok(()) 104 } 105} 106 107 108pub async fn insert_db(data: &[Data], key: &str) -> Result<()> { 109 110 Ok(()) 111}
具体的な説明。
-
実現したいことは、
store: HashMap<Index, HelperData>,
に格納されているデータに対して非同期で処理を回したいです。 -
Index * 2つのvector (up sort, down sort)をjoin_allもしくはもっといい方法で非同期処理をしたいです。
-
起きているエラーはjoin_allしている部分
futures::future::join_all(executor).await;
であり,
ここで全てのタスクをjoin_allしているので、for分のスコープ外までlife timeが生きていないかもしれないとのエラーだと思います。
例えば、以下のformat!
のアロケートがスコープ外になります。。
rust
1let key= format!("{}:id", index.to_string()); 2↓こちらをこのようにしてもだめでした。 3let key: &'a str = &format!("{}", index.to_string());
また、その他にも問題があり。
rust
1if let Some(data_vec) = self.store.get_mut(&index) { 2 data_vec.up.sort_by(|a, b| b.value.cmp(&a.value)) 3 data_vec.down.sort_by(|a, b| a.value.cmp(&b.value)); 4/////省略。 5}
-
get_mut()で取得したSome(data_vec)が1度に複数の可変参照を取ることができないと問題が出ました。なので、こちらをArc::Mutexでlockすることで実現しようとしました。
-
コンパイラからdrefが欲しいと言われたのでその通りに実装して現在に至ります。そしてまた、ライフタイムの問題に戻ってきました。
error
1`data_store` does not live long enough 2values in a scope are dropped in the opposite order they are defined
- 'aのライフタイム宣言をどのように実装すれば解決するか分からなくて詰まってます。
何か知っていましたら教えてほしいです。
また、他にももっとこのような実装の方がいいとかありましたら教えてください。

回答1件
あなたの回答
tips
プレビュー
下記のような回答は推奨されていません。
このような回答には修正を依頼しましょう。
また依頼した内容が修正された場合は、修正依頼を取り消すようにしましょう。
2022/03/10 12:28