Storing a reference to a value held in a struct in that same struct with Arc and Mutex

pub struct Emitter<'a, T> {
    emitter_id: EmitterId,
    events: Arc<Mutex<Option<Events<T>>>>,
    last_event: Arc<Mutex<Option<&'a Event<T>>>>,
}

impl<'a, T: Debug> Emitter<'a, T> {
   pub fn emit(&'a self, event_name: &str, event_data: Option<T>) {
        let new_event = Event::new(
            event_name,
            EventType::Custom,
            event_data,
            self.get_emitter_id(),
        );

        println!("{new_event:?}");

        let events = &mut *self.events.lock().unwrap();
        let last_event = &mut *self.last_event.lock().unwrap();

        match events {
            Some(e) => e.push(new_event),
            None => *events = Some(vec![new_event]),
        }

        if let Some(ref e) = events {
            let last_index = e.len() - 1;
            *last_event = Some((&e[last_index]).clone());
        }
    }
}
error[E0716]: temporary value dropped while borrowed
  --> src/emitter/mod.rs:59:28
   |
27 | impl<'a, T: Debug> Emitter<'a, T> {
   |      -- lifetime `'a` defined here
...
59 |         let events = &mut *self.events.lock().unwrap();
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
...
69 |             *last_event = Some((&e[last_index]).clone());
   |                                ------------------------ argument requires that borrow lasts for `'a`
70 |         }
71 |     }
   |     - temporary value is freed at the end of this statement

For more information about this error, try `rustc --explain E0716`.
error: could not compile `elib` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed

If you have an Arc then why store a reference? You can make last_store simply Arc<Mutex<Option<Events<T>>>>.

because I want to store the refrence

Yes, why?

because i want to send that ref to a function and keep track of the last event

You can send an Arc instead. An Arc is a reference counted reference, so would behave the same.

Yeah, but the event should be copied because event is a struct then i have to make Event derive (Clone, Copy) or copy it manualy.

No it won't be. Arc is reference-counted. So if you call Arc::clone(event) (where event is of type Arc<Mutex<Option<Events<T>>>>), then the struct is not copied. Only the reference count is increased.
You can read the docs here.

1 Like

Thank you!
but notice that Events is Vec<Event> (type Events<T> = Vec<Event<T>>) and last_count should be a refrence to one event not a vector of events.

Then you can do something like this:

struct OneEvent {
     events: Arc<Mutex<Option<Events<T>>>>
     idx: usize
}

idx will be the index of the event you want to store.
If you just have one large vector of events, then you can take this one step further - just store the indices, and when calling the function, pass the correct reference.