Lifetime bound in thread

I have a problem I don't understand. I tried to read but really, I cannot make it.

I have a nested struct like
struct A { B : struct { C : struct { amp: a float ! }}}}
and so on...

I'm trying to set the float inside C.
I receive a string like "A B C 43" which tells me to set the float inside C at 43. (of course for other objects, other paths can be chosen)

OK. To me, the idea is
I know that in A, B can be get, so if i have B, i get it
I know that in B, C can be get, so if i have C, i get it
I know that in C, amp can be set

every node are Iterator, every leaf are Scalar.

I was thinking doing something like

    pub trait Parameter {
        type Param = Iterator<Item = f32>;
        fn parse(&mut self, msg: &mut Message) -> Option<Self::Param>;
    }

But of course, you cannot return a impl Trait into a trait
So, I was thinking returning a &mut ref, which made sense, and doing something like

impl<'a, T: Iterator<Item = f32> + 'a> Parameter<'a> for Sin<T, Scalar> {
    type Param = &'a mut T;

    fn parse(&'a mut self, mut msg: Message) -> Option<Self::Param> {
        match msg.param {
            "phasor" => Some(&mut self.phasor),
            "amp" => {
                set_param!(msg, self.amp); return None;
            }
            _ => None,
        }
    }
}

Of course, I'm listening to messages, so my main struct is moved into a thread.
Here self is bounded with Parameter trait

 std::thread::spawn(move || loop {
            while let Ok(msg) = rx_message.try_recv() {
                if let Ok(msg) = Message::parse(&msg) {
                    while let Some(thing) = self.parse(msg) {}
                }
            }
        });

and bim
I have

error[E0499]: cannot borrow `self` as mutable more than once at a time
  --> src\back\synth.rs:29:45
   |
17 |         'a: 'static,
   |         -- lifetime `'a` defined here
...
29 |                     while let Some(thing) = self.parse(&mut msg) {}
   |                                             ^^^^----------------
   |                                             |
   |                                             mutable borrow starts here in previous iteration of loop
   |                                             argument requires that `self` is borrowed for `'a`

error[E0597]: `self` does not live long enough
  --> src\back\synth.rs:29:45
   |
17 |         'a: 'static,
   |         -- lifetime `'a` defined here
...
29 |                     while let Some(thing) = self.parse(&mut msg) {}
   |                                             ^^^^----------------
   |                                             |
   |                                             borrowed value does not live long enough
   |                                             argument requires that `self` is borrowed for `'a`
...
37 |         });
   |         - `self` dropped here while still borrowed

After that I changed 'a for 'static, since self, being borrowed in a thread is 'static, but this change nothing
I'm really sorry for the length of the post, but reaaaaaally I completely lost......

I understand that the lifetime should express the simple lifetime inside the {} loop in my while let ....

Maybe I could give my function under the trait [called parse] a lifetime ???

Can you give a more complete example? For the thread spawning function you only give the std::thread::spawn call. You don't give the rest of the method.

Thanks,

impl<'a, 
        U: Default + Send + 'static,
        T: Parameter<'a> + Serialize + Iterator<Item = U> + Send + 'static,
    > Spawner<U, T> for T
{
    fn spawn(mut self, size: usize) -> Synth<U> {
        let json = serde_json::to_string(&self).unwrap();
        let (tx_audio, rx_audio) = sync_channel(size);
        let (tx_message, rx_message) = channel::<String>();
        std::thread::spawn(move || loop {
            while let Ok(msg) = rx_message.try_recv() {
                if let Ok(mut msg) = Message::parse(&msg) {
                    while let Some(thing) = self.parse(&mut msg) {}
                }
            }
            for _ in 0..256 {
                tx_audio
                    .send(self.next().or(Some(U::default())).unwrap())
                    .expect("rx is dead");
            }
        });
        Synth {
            params: tx_message,
            out: rx_audio,
            json,
        }
    }
}

But I think I have to change my Parameter trait to something like

  pub trait Parameter {
        type Param<'b> = &'b mut Iterator<Item = f32>;
        fn parse<'a>(&'a mut self, msg: &mut Message) -> Option<Self::Param<'a>>;
    }

The signature appears important here. The 'a: 'static part looks very suspicious. I would like to see the definition of Sin too.

Ok, I think we just have to forget my code, which is obviously hideous.

The question is so, how could I traverse a nested struct so that I can get any value inside in Rust, knowing that it's always differents type but always Iterator trait ?

This doesn't seem valid. You can't say that an associated type will always have a specific value in the trait definition, you can only say that it must implement some trait.

type Param<'b> = &'b mut Iterator<Item = f32>;

Additionally it appears to use nightly-only features. It's also missing a dyn on the reference.

Ok, I think we just have to forget my code, which is obviously hideous.
The question is so, how could I traverse a nested struct so that I can get any value inside, knowing that it's always different types but always Iterator trait ?

Consider posting some example structs?

concretly, I have just that


#[derive(Default, Debug, Deserialize, Serialize)]
pub struct Line<T: Iterator, U: Iterator> {
    pub freq: T,
    pub phase: U,
    #[serde(skip_serializing)]
    pub sr: u32,
    #[serde(skip_serializing)]
    pub i: usize,
}

and

#[derive(debug, deserialize, serialize)]
pub struct sin<t: iterator, u: iterator> {
    pub phasor: t,
    pub amp: u,
}

and let's say i build something like

let ugen = Sin {
        phasor: Line {
            sr: 48000,
            freq: Sin {
                phasor: Line {
                    sr: 48000,
                    freq: Scalar(10.0),
                    phase: Scalar(0.0),
                    i: 0,
                },
                amp: Scalar(0.5),
            },
            phase: Scalar(0.0),
            i: 0,
        },
        amp: Scalar(0.1),
    };

I want to change the
freq into the phasor
in the first freq of the first phasor,

and I want to implement this into a trait like Parameter, like
ugen.set("phasor freq phasor freq 880" )
which should only be somthing like
ugen.phasor.freq.phasor.freq = 880 [in fact Scalar(880)]

The iterator trait doesn't seem suitable for this.

I think I have a complete example here

playground : Rust Playground

#[derive(Debug, Deserialize, Serialize)]
pub struct Sin<T: Iterator, U: Iterator> {
    pub phasor: T,
    pub amp: U,
}

#[derive(Debug)]
pub enum Params<'a, T: Iterator, U: Iterator> {
    phasor(&'a T),
    amp(&'a U),
}

pub trait Getter<'b> {
    type Return;
    fn get(&'b self, msg: &str) -> Option<Self::Return>;
}

impl<'b, T: Iterator + 'b, U: Iterator + 'b> Getter<'b> for Sin<T, U> {
    type Return = Params<'b, T, U>;
    fn get(&'b self, msg: &str) -> Option<Self::Return> {
        match msg {
            "amp" => Some(Params::amp(&self.amp)),
            "phasor" => Some(Params::phasor(&self.phasor)),
            _ => None,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    extern crate crossbeam;

    fn launch<T: Getter<'_> + Send + Sync + 'static>(mut a: T) {
        std::thread::spawn(move || loop {
            a.get("phasor");
            // println!("{:?}", a.get("phasor"));
            std::thread::sleep(Duration::from_secs(1));
        });
    }
    #[test]
    fn test() {
        let a = Sin {
            phasor: Scalar(1.0),
            amp: Scalar(1.0),
        };
        std::thread::spawn(move || loop {
            println!("{:?}", a.get("phasor"));
            std::thread::sleep(Duration::from_secs(1));
        });
        std::thread::sleep(Duration::from_secs(5));
    }
    #[test]
    fn test2() {
        let a = Sin {
            phasor: Scalar(1.0),
            amp: Scalar(1.0),
        };
        launch(a);
        std::thread::sleep(Duration::from_secs(5));
    }
}

The test2 dont compile, because of the lifetime.
Maybe the point should be to pass the lifetime to the function inside the trait and not the trait itself, but i cannot no more specialize the Return type of the Getter trait, which require the lifetime

If I do something like this

pub trait Getter {
    type Return<'a>;
    fn get<'b>(&'b self, msg: &str) -> Option<Self::Return<'b>>;
}

impl<T: Iterator, U: Iterator> Getter for Sin<T, U> {
    type Return<'a> = Params<'a, T, U>;
    fn get<'b>(&'b self, msg: &str) -> Option<Self::Return<'b>> {
        match msg {
            "amp" => Some(Params::amp(&self.amp)),
            "phasor" => Some(Params::phasor(&self.phasor)),
            _ => None,
        }
    }
}

I have


error[E0309]: the parameter type `T` may not live long enough
  --> ugens\src\sin.rs:23:5
   |
22 | impl<T: Iterator, U: Iterator> Getter for Sin<T, U> {
   |      -- help: consider adding an explicit lifetime bound...: `T: 'a +`
23 |     type Return<'a> = Params<'a, T, U>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: ...so that the type `T` will meet its required lifetime bounds
  --> ugens\src\sin.rs:23:5
   |
23 |     type Return<'a> = Params<'a, T, U>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

which I don't know how to resolve

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.