3

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
rotty
  • 33
  • 5
  • Related: [Why is it possible to implement Read on an immutable reference to File?](http://stackoverflow.com/q/31503488/155423). In that case, the OS handles multiple uses of the underlying file descriptor, so there's no reason to enforce that in Rust. – Shepmaster Nov 18 '16 at 15:37

1 Answers1

5

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.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Chris Emerson
  • 13,041
  • 3
  • 44
  • 66
  • I should have added that the socket options in question are not thread-safe, but sharing across threads should be forbidden by the type system if the binding not implementing the `Sync` thread, right? And the libzmq C API does not employ callbacks at all, AFAIK. – rotty Nov 18 '16 at 18:10