Unique caller using &mut self

I was thinking about a function I've written which does some multithreaded magic in its implementation. The main logic of this function can be implemented in two ways:

  • By initializing new data structures for each call
  • By reusing cached data in self

The benefit of the latter is that it is slightly faster. The downside, which the first design doesn't have, is that I need to protect against multiple simultaneous calls on the same object.

... or do I?

I think I came to a realization: A method which has &mut self has an an interesting side effect that it can not be called simultaneously. Even if someone puts the object in an Arc and passes it to another thread and tries to call it it won't work because it violates the mut constraint. And if one puts it in an Mutex .. well, locking etc.

So assuming:

impl Foo {
  pub fn send(&mut self, blah: Blah) {
  }
}

.. is it conceptually correct to read the &mut self as "will never be called reentrantly"? (Sans unsafe hackery). I really want this to hold true for all non-unsafe cases, because it greatly simplifies one method I'm currently working on.

How future proof would an "&mut self => never reentrant" invariant assumption be?

Yes, being unique is the definition of a mutable reference. The only way two calls to send can overlap is if it calls itself:

impl Foo {
  pub fn send(&mut self, blah: Blah) {
    self.send(blah);
  }
}

It holds true even with unsafe. To produce two overlapping mutable references is undefined behaviour.

1 Like