Returning from macro rules

How can I write a simple macro rules while returning the value.

ie

macro_rules! unlock_or_none {
         ($var:expr) => {
          
               let strong = $var.upgrade().unwrap();
               strong.lock().ok()
         };
 }

let sender1 = unlock_or_none!(sender);

At the moment I get error: expected expression, found statement (let).

I am using to separate variable as otherwise it gets dropped before the lock.

Thanks

2 Likes

I believe that you need two sets of curly brackets. The outer one are for the macro and the inner ones are retained.

let sender1 = let strong = sender.upgrade().unwrap(); 
strong.lock().ok()

vs.

let sender1 = {
    let strong = sender.upgrade().unwrap(); 
    strong.lock().ok()
}
macro_rules! unlock_or_none {
         ($var:expr) => {{
               let strong = $var.upgrade().unwrap();
               strong.lock().ok()
         }};
 }

let sender1 = unlock_or_none!(sender);```
1 Like

Trouble is I always get

strong.lock().ok()
| ------ borrow occurs here
83 | }};
| ^ strong dropped here while still borrowed

I'm guessing this is an Arc<Mutex<...>> structure you're working with, probably the SyncSender stuff we discussed in the other thread?

You can't "take" a value out of a Mutex that you've borrowed - if you could, it defeats the purpose of the Mutex since the value would be unsynchronized.

What are you trying to do here?

Yes

Basically I will be sending Weak<Mutex<SyncSender>> and Weak<Mutex<Receiver>> to lots of functions . That way at shutdown I can drop the strong references and the channels don't hang. I just wanted a slightly more convenient way of upgrading a unlocking each receiver / sender as I will be doing it hundreds of times.

Not really a big deal. Just using the opportunity to learn a bit more.

Gotcha. Yeah, you'll need to work with the underlying values via the MutexGuard you get back from lock.

By the way, you shouldn't need to wrap the SyncSender in a Mutex. The senders are threadsafe and you just clone them and move the clone to your thread. Only the receiver needs protection if you're going to share it across threads.