Programming language Rust 1.63 gets threads that are allowed to borrow data
In addition to the scoped threads, version 1.63 of the programming language brings wrappers for file handles or descriptors to clarify ownership.
Rust 1.63 was released every six weeks as planned. The release brings two changes related to Rust’s ownership concept. On the one hand, scoped threads allow a more flexible handling of the data for a thread and on the other hand, file descriptors or handles can now be provided with a wrapper that determines whether they are owned or borrowed.
Threads in the application context
Even though Rust only introduced the async-await pattern at the end of 2019, the programming language has known threads for concurrent programming since its inception. Previously, the closure for creating a thread using the standard library was over std::thread::spawn
With 'static
marked. The static lifetime marked with this specifies that the thread must have ownership of all parameters in its closure. It is therefore not possible to transfer borrowed data to a thread.
The API std::thread::scope
now create an execution context (scope) to spawn so-called scoped threads. The context guarantees that all threads in it end up either manually via join
or automatically merged before exiting the function. Therefore, borrows from non-'static
-Data allowed on scoped threads. The following example from the Rust blog illustrates the scoped threads in the first part with immutable borrows and in the second with mutable borrows:
let mut a = vec![1, 2, 3];
let mut x = 0;
std::thread::scope(|s| {
s.spawn(|| {
println!("hello from the first scoped thread");
// We can borrow `a` here.
dbg!(&a);
});
s.spawn(|| {
println!("hello from the second scoped thread");
// We can even mutably borrow `x` here,
// because no other threads are using it.
x += a[0] + a[2];
});
println!("hello from the main thread");
});
// After the scope, we can modify and access our variables again:
a.push(4);
assert_eq!(x, a.len());
Borrowed file handles
Another innovation concerns the handling of files and also relates to the ownership concept. So far, Rust has adopted a platform-specific representation for file descriptors taken from the operating system on Unix and handles on Windows. at RawFd
but it wasn’t clear if the API owns the descriptor or just borrows it.
Rust 1.63 introduces additional wrappers that explicitly set ownership: a BorrowedFd
is gliding while OwnedFd
marked ownership. For the latter, the program closes the descriptor when it is released.
Extended blockade
In addition, the release expands the handling of mutexes and constructs for managing locks in asynchronous programming. Since version 1.62, Rust on Linux uses a futex-based implementation instead of POSIX threads as before. The call of Condvar::new
, Mutex::new
and RwLock::new
is recently in const
-Context allowed.
Finally, the non-lexical lifetimes (NLL) for borrows are now considered stable. Although they were already part of Rust 2018, they only applied to the 2018 and 2021 editions, not to Rust 2015. This is changing with the current release. Details can be found in a blog post from early August.
One of Rust’s strengths is memory security: the programming language’s ownership concept sets strict rules that prevent typical memory errors that occur in languages like C or C++. Rust has three ownership rules: Each stat has an owner. There can only be one owner at a time. And when the owner is no longer in the execution context, the value is dropped.
The required memory is reserved when the variable is initialized. Because there can only be one owner, assigning one variable to another requires a different approach than in other programming languages. One way is to clone values, which means they exist twice, take up twice as much memory, and a change only applies to the owner.
With references it is possible to pass the actual value, which by default is unmutable (read-only). Such references may exist more than once. Finally exist with &mut
marked mutable references that have exclusive rights for both writing and reading. You borrow (borrow) the right to access from the owner. This means that no other references to the same memory area, including read-only ones, are allowed to exist.
More details about Rust 1.63 can be found on the Rust blog. As usual, developers who already have Rust installed can update the current release rustup update stable
download. For those not yet using Rust, this is rustup
tool available separately on the download page.