Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
225 views
in Technique[技术] by (71.8m points)

rust - Does actix_web's App::register_data create a single instance or one instance per thread?

I am trying to set up a global state for my actix_web::HttpServer, and it seems like register_data is the proper API (I could be wrong).

From the documentation, it is not clear to me how to create a single instance of application data shared by all HttpServer threads. Here is my code piece:

HttpServer::new(|| {
    App::new()
        .register_data(web::Data::new(Mutex::new(MyServer::new())))
        .service(web::resource("/myservice").route(web::post().to(my_service)))
        .service(web::resource("/list").to(list_service))
})

In the POST handler my_service, I update the state of MyServer and in the GET handler list_service, it will print out the state.

While my_service is successful in storing the state, the list_service only prints empty output. How do I know if HttpServer created a single instance of MyServer or not? If not, how can I ensure it creates a single instance? The documentation of register_data states:

Application data does not need to be Send or Sync. Internally Data type uses Arc. if your data implements Send + Sync traits you can use web::Data::new() and avoid double Arc.

I'm confused by that. What should the user do so that register_data will register a single instance of the data object? Does this following line in the example from the documentation create a single instance, or one instance per thread?

.register_data(data.clone())

I'm using actix-web 1.0.9.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After playing with Rust code a bit more, I understand better now. web::Data is an Arc, hence it's okay to call data.clone() which creates a new instance of Arc but still points to the single shared instance of MyServer. That will allow HttpServer threads to share a global state.

So to fix my problem, I just followed the example in the documentation, i.e, moved the data creation out of HttpServer::new and call clone() inside it:

    let my_data = web::Data::new(Mutex::new(MyServer::new()));
    HttpServer::new(move || {
        App::new()
            .register_data(my_data.clone())  // only Arc is cloned
            .service(web::resource("/myservice").route(web::post().to(my_service)))
            .service(web::resource("/list").to(list_service))    
    })

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...