Reputation: 33
I'm unsure when to use &mut self
vs. just &self
in the Rust bindings for the libzmq C API.
A bit of background: libzmq provides socket "objects", which have an API similar to the BSD socket API, and are represented by an opaque pointer in C. This pointer is really just a handle, similar to POSIX file descriptors, and the C API is designed so that it is not possible to obtain any references to memory behind that pointer.
Under these circumstances, is it safe and good API design to expose socket methods with an immutable self
? As a concrete example, consider zmq_send()
:
int zmq_send (void *socket, void *buf, size_t len, int flags);
I think it can (and should) be exposed using immutable self, i.e.:
pub fn send(&self, data: &[u8], flags: i32) -> Result<()> { ... }
However, comparable Rust standard library methods use &mut self
, e.g. std::io::Write::write()
, as implemented by std::net::TcpStream
. On the other hand, std::net::UdpStream::write()
takes just &self
. My guess is that &mut self
is used just because it is an implementation of the Write
trait, which in turn (I guess) uses &mut self
to not constrain implementations of the trait.
I hope someone can back up or refute my speculations here -- I could not find anything specific about that topic in the Book or the Nomicon.
Upvotes: 3
Views: 596
Reputation: 14041
In this case whether the object is mutated is secondary; the main question is "is it safe for two references to be used at the same time?". Would it be ok for two threads to call zmq_send
(or other methods) on the same object at the same time, or (if the API allows that) via nested callbacks, etc?
If not, use &mut self
and let Rust enforce the safety guarantees you need.
If it is safe, then maybe &self
is appropriate, if zmq
guarantees it's ok; this would be like Mutex::lock
taking &self
.
Upvotes: 5