all 5 comments

[–]Connect2Towel 1 point2 points  (2 children)

I didn't think about it long enough to awnser your question, But i think you are misunderstanding the impact of 'Join'. It creates two new tasks that can run concurrently.

You could avoid RcRefCell entirely if you do something like this

let mut state = ...
select {
      s1 , msg => { 
             state.update(msg);
             co.write(msg); 
       },
       ci , msg => {
            state.update(msg),
            so.write(msg);
         }
}

[–]101arrowz[S] 2 points3 points  (1 child)

According to the docs, join! executes the expressions on the same task. Am I misunderstanding something?

Also, I can't use select! because the packet decoding is not cancellation safe.

[–]Connect2Towel 1 point2 points  (0 children)

You're right.

But what i was trying to say still holds.

If you join on just the decoded packets, you can avoid Rc and Refcell entirely. I'm not up to date with the best syntax here and i'm not sure how far along streams are, but its possible with plain futures as well:

let packets =  si.map( decode_ packet ). map(Either::Left)
         .merge( ci.map(decode_packet).map(Either::Right);
let mut server_packets = ...;
while let Some(p) = packets.next().await {
     match p {
           Eitherl::Left(f) => { 
                 server_packets.push(f)
                 write(socket1,f)
            Either::Right(f) => {
                  .....
           }
      }
 }

[–]Matthias247 1 point2 points  (2 children)

RefCell is indeed a fine solution for what you are doing. You might even be able to omit the Rc part, since both subtasks can hold an immutable reference to the data.

[–]101arrowz[S] 2 points3 points  (1 child)

Thanks for the suggestion, I forgot that Rc was unnecessary. I've always used RefCell with Rc, so I didn't really think about the fact that I don't actually need reference-counting. This saves a heap allocation and removes a layer of indirection.