Best pattern for async update of self object?

I have got a struct (Adapter for reference purposes).

struct Adapter {
    field: i32
}

It's methods issue async requests using hyper client. Sometimes, I need to update internal fields of the Adapter depending on responses received for the issued by itself requests. It means I need to access self in one of the closures on futures::then(). This is not allowed as self may not live long enough, unless the Adapter instance is static. I do not have it static, because it is created after some validation and interaction on start.

I have found another option is to do something like the following:

struct AdapterImpl {
    field: i32
}
struct Adapter {
    internal: Rc<RefCell<AdapterImpl>>
}

This way I can obtained Rc pointer to the implementation of self before constructing future chain and move it to the closure, where I do borrow or borrow_mut on the RefCell self object to access or mutate it in async code. I heard that RefCell is a sign of code smell, but I can not think of another way of solving the problem.

Is the approach, I am taking, the best practice? Or am I doing something wrong?

This is a good and common approach for this. I cringe a bit whenever I use RefCell but the Rc<RefCell<...>> duo is virtually required when using futures.

Another approach is to move self itself into the future, and then get it back when the future resolves.

2 Likes

Could you please post a sketch of code how to do this.? I do not understand how to get it back.

A good example is the StreamFuture in the futures crate. This is a future that's returned when you call some_stream.into_future(), and into_future() consumes self. The Future impl for StreamFuture yields the underlying stream back in success and error cases: futures::stream::StreamFuture - Rust.

So this approach works well if you own (or can take ownership) of a value that you intend to move into a future. That future should then yield back the value via its Item and Error associated types, which will allow the caller/user to get ownership back.

2 Likes

Very nice! Thanks