Strategies to deal with `!Send`

#1

Context

I have a Read + !Send type (a git object reader obtained from git2::Odb::reader) that I need to pass to a method wrapping a Hyper request that requires Read + Send + 'static (ipfs_api::IpfsClient::add).

Problem

!Send and Send don’t mix well, but I need to somehow pass a Read + !Send for a streaming approach to conserve RAM in my use case (see above; think big git blobs).

Questions

  • Is there a standard way to wrap Read + !Send types to get Read + Send?
  • If not, what else could I try to implement myself?
#2

I’ve noticed that a good amount of FFI code ends up being !Send simply because raw ptrs are !Send by default, and unless the author is paying attention to the Send-ness of their API, they may not notice.

So, the first question about a !Send type, particularly if it’s auto-derived to be such and uses raw ptrs, is whether it is actually !Send or that’s merely an artifact of how the compiler treats such types. If it’s just an omission by the author, then it’s best for the code (git2, in this case) to be updated to explicitly mark the type(s) as Send.

I’m unfamiliar with git2 so can’t really say whether its types should or should not be Send.

You can wrap a !Send type in your own type, and then impl Send for the wrapper. Of course, this is dangerous because even if today the inner type is sendable, it may not be tomorrow.

1 Like
#3

Thanks! I guess I’ll try to contribute there then

#4

It is not per se possible to convert it. But you could wrap your T in any container of https://doc.rust-lang.org/std/sync/index.html, e.g. a Arc<Mutex<T>> which will make it Send + Sync, but of course you have to clone your arc and lock your mutex every time you want to access your inner T.

I think what @vitalyd said was very good, escpecially in this context. My solution is just a more general approach.

1 Like
#5

That’s pretty cool advice too, thank you!

#6

To be clear, Mutex<T> is not Send if T isn’t so it doesn’t do anything for this particular case. Mutex<T> is about adding the Sync capability, but it requires that T: Send to begin with.

1 Like
#7

@vitalyd Yes, you’re right, that’s why I wrote Arc<Mutex<T>> which will provide both for you. Maybe I skipped a few steps, sorry :slight_smile:

#8

So my point, which perhaps I didn’t express clearly enough, was that if T: !Send, no type in std will magically make it Send. Perhaps you weren’t actually suggesting that, and I simply misinterpreted, but wanted to clarify that since the OP’s starting point is having a !Send type.

1 Like