kishoredbn
kishoredbn

Reputation: 2087

How to pass an object by reference inside Rust Warp callback?

I am pretty new to Rust programming and still trying to understand the concepts around memory and ownership.

I have this code.

#[tokio::main]
async fn main() {

    let file_root = String::from("test_dir/");
    let content_dir = String::from("posts_");
    let obj = msgnode::MsgNode::new(file_root.clone(), content_dir.clone());

    let node_filter = warp::any().map(move || obj.clone());

    // GET /hello/warp => 200 OK with body "Hello, warp!"
    let hello = warp::get()
        .and(warp::path("waservice"))
        .and(warp::path::end())
        .and(msg_body())
        .and(node_filter.clone())
        .and_then(store_wamsg);

    warp::serve(hello)
        .run(([127, 0, 0, 1], 3030))
        .await;
}

mod msgnode;

Everything is fine with that, except that I cannot work with cloned instance of MsgNode object. Inside the store_wamsg I am using the MsgNode object as following:

async fn store_wamsg(item: MsgItem, node : &msgnode::MsgNode) -> Result<impl warp::Reply, warp::Rejection> {
    
    let mut node2 = node.clone();

    node2.create_file(item.msg_content);
    
    Ok(warp::reply::with_status(
        "All good",
        http::StatusCode::OK,
    ))
}

My question is, if there is a way that I don't need to use multiple cloned instances of MsgNode object inside the main function, every time a new request is made to the service?

To be more precise I want to do something like this:

let node_filter = warp::any().map(move || &obj);

And somehow pass the reference inside the store_wamsg function. Right now when I do this I run into the following error:

116 |     let node_filter = warp::any().map(move || &obj);
    |                                       ------- ^^^^ returning this value requires that `'1` must outlive `'2`  
    |                                       |     |
    |                                       |     return type of closure is &'2 MsgNode
    |                                       lifetime `'1` represents this closure's body
    |
    = note: closure implements `Fn`, so references to captured variables can't escape the closure

Upvotes: 0

Views: 889

Answers (1)

You can enacapsulate msgnode in Arc Mutex to sync access:

use std::sync::{Arc, Mutex};

let obj = Arc::new(Mutex::new(msgnode::MsgNode::new(
    file_root.clone(),
    content_dir.clone(),
)));

let node_filter = warp::any().map(move || obj.clone());

Here, obj.clone() clones the atomic resouce counter, not msgnode. So that there is only one instance of MsgNode and threads coordinate their access to it with the help of Arc and Mutex.

Upvotes: 2

Related Questions