質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

解決済

Rustでライフタイムを解決したい。

I_am_
I_am_

総合スコア23

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

1回答

0リアクション

1クリップ

608閲覧

投稿2022/03/09 11:49

前提・実現したいこと

Rustのライフタイムで解決の仕方が分からないところがあります。
何か、知っていることや考え方を知っていたら教えてほしいです。

該当コード

以下のパターンの解決をしたいです。

rust

// use anyhow::Result; use std::{collections::HashMap, vec}; use std::string::ToString; use std::ops::{Deref, DerefMut}; use strum::IntoEnumIterator; use strum_macros::{EnumIter, ToString}; use std::sync::Arc; use tokio::sync::RwLock; #[derive(Debug, Default, Clone)] struct Data { id: String, name: String, value: i32, } #[derive(EnumIter, ToString, Debug, Hash, PartialEq, Eq, Clone)] enum Index { PatternA, PatternB, PatternC, PatternD, } #[derive(Debug, Default, Clone)] struct Helper { up: Vec<Data>, down: Vec<Data>, } impl Helper { pub fn new() -> Self { Self { up: vec![], down: vec![], } } } #[derive(Debug, Default, Clone)] pub struct Target { store: HashMap<Index, Helper>, } impl Deref for Target { type Target = HashMap<Index, Helper>; fn deref(&self) -> &Self::Target { &self.store } } impl DerefMut for Target { fn deref_mut(&mut self) -> &mut HashMap<Index, Helper> { &mut self.store } } impl Target { pub fn new() -> Self { Self { store: HashMap::new(), } } pub fn init(&mut self) -> Result<()> { Index::iter().for_each(|i| { self.store.insert( i, Helper::new(), ); }); Ok(()) } pub async fn update<'a>(&'a mut self) -> Result<()> { let multi_ref = Arc::new(RwLock::new(&self.store)); let mut executor = vec![]; for index in Index::iter() { let key= format!("{}:id", index.to_string()); let clone_ref = Arc::clone(&multi_ref); let mut wt = clone_ref.write().await; let mut data_store = wt.deref_mut().clone(); if let Some(data_vec) = data_store.get_mut(&index) { data_vec.up.sort_by(|a, b| b.value.cmp(&a.value)); data_vec.down.sort_by(|a, b| a.value.cmp(&b.value)); let up_task = insert_db(&data_vec.up, &key); let down_taks = insert_db(&data_vec.down, &key); executor.push(up_task); executor.push(down_taks); } } futures::future::join_all(executor).await; Ok(()) } } pub async fn insert_db(data: &[Data], key: &str) -> Result<()> { Ok(()) }

具体的な説明。

  • 実現したいことは、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

let key= format!("{}:id", index.to_string()); ↓こちらをこのようにしてもだめでした。 let key: &'a str = &format!("{}", index.to_string());

また、その他にも問題があり。

rust

if let Some(data_vec) = self.store.get_mut(&index) { data_vec.up.sort_by(|a, b| b.value.cmp(&a.value)) data_vec.down.sort_by(|a, b| a.value.cmp(&b.value)); /////省略。 }
  • get_mut()で取得したSome(data_vec)が1度に複数の可変参照を取ることができないと問題が出ました。なので、こちらをArc::Mutexでlockすることで実現しようとしました。

  • コンパイラからdrefが欲しいと言われたのでその通りに実装して現在に至ります。そしてまた、ライフタイムの問題に戻ってきました。

error

`data_store` does not live long enough values in a scope are dropped in the opposite order they are defined
  • 'aのライフタイム宣言をどのように実装すれば解決するか分からなくて詰まってます。

何か知っていましたら教えてほしいです。
また、他にももっとこのような実装の方がいいとかありましたら教えてください。

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。