Borrowing mutable references

In addition to managing the lifetimes of references to variables, the Rust compiler’s borrow checker also deals with enforcing Rust’s guarantees about mutability and so helps to prevent data races. Basically, you can have any number of immutable references to a variable, but only if there are no mutable references to it at the same time, and you can only ever have a single mutable reference. This piece on aliasing in Rust By Example covers this nicely.

Lifetimes

One of the jobs of the Rust compiler’s “borrow checker” is to track the life of each reference to a variable so that it can prevent dangling references. To do this, it annotates each variable and reference with details of the scope in which it is valid. This annotation is called a lifetime. All variables have a lifetime annotation, but not all lifetime annotations need to be explicit and visible in the source code as the compiler is allowed to accept code where lifetimes have been elided in certain common circumstances.

Deadlocks

One reason that access shared data using locks is a bad idea is that, in complex code, it may be possible to deadlock. At their simplest, deadlocks are caused when one thread (thread a) obtains and holds a lock which another thread (thread b) requires whilst itself being blocked from obtaining a lock that it requires because thread b already holds it… Unfortunately, whilst Rust has eliminated data races in multithreaded code, it doesn’t prevent the possibility of deadlocks.

Accessing the Id Manager from multiple threads

Since I now understand a little about how to share data between threads I can try and use my Id Manager from multiple threads. Following the same pattern as I’ve been using with the other threading code, something like this might work… #[test] fn test_channel_thread_with_id_manager() { let id_manager = Arc::new(IdManager::<u8>::new(ReuseSlow)); let shared_manager = Arc::clone(&id_manager); let data = Arc::new(Mutex::new(HashMap::<String, Id<u8>>::new())); let shared_data = Arc::clone(&data); let mut thread = ChannelThread::new(move |message| { let id = shared_manager.

Sharing data between threads

Now that we can send messages to threads I want to see how we can access shared data from those threads. This isn’t the best design choice as shared data needs to be protected by locks so that it is accessed in an atomic fashion and the various threads involved with this data will contend with each other over the locks. It’s generally considered to be far better to pass the data between threads and only have one thread able to access the data at any one time.

Simple threading

The simplest threading is already covered by most Rust books. Starting up a thread, passing stuff to it, letting it run and waiting for it to finish. Something like this is the basic thread example in Rust. This work’s and is easy to understand and reason about. The spawned thread clearly runs for less time than the main thread as we join with it before the main thread completes but we rely on the spawned thread to decide when to shut down, this isn’t that important here as the spawned thread has a finite amount of work to do, but for threads that do a potentially infinite amount of work I will need a way to ask the thread to stop…

Thinking about threading

My threading background in C++ on Windows and Linux goes back a long way and that means that I have some set ways of doing things that may not map directly to the Rust way of doing things. I tend to use threads with the following patterns at present: A thread starts up, waits on one or more externally controlled ’events’ and, when one of these is triggered the thread does something, or shuts down.

Normal service will resume shortly

The website work with Hugo that I mentioned here is now mostly complete. I’ve managed to find a Hugo theme that worked for me and tweak it so that I could keep the shape of my sites pretty much the same. I’ve now updated this site to match as this format is more suitable to my “blundering about whilst learning” style. I’ve added some chapter categories so that I can still read the key parts of my learning experience in the correct order.

Currently reading - Rust Brain Teasers

I’m currently reading Rust Brain Teasers by Herbert Wolverson. It’s a nice book of bite-sized puzzles in Rust that are ideal for the way I like to learn (randomly jumping around from subject to subject that happen to interest me). Each puzzle presents some code, asks you what you think it does and then shows you the hidden complexity. At the end of each section are some links to further reading.