= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Rust Standard Library – Chinese version, welcome to join us!!

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

The Rust standard library is the foundation for portable Rust software, a set of minimal and tested shared abstractions for the broader Rust ecosystem. It provides core types such as Vec

and Option

, library definition operations on language primitives, standard macros, I/O and multithreading, and much more.

Std is available for all Rust libraries by default. Therefore, the library can be accessed through the STD path in the USE statement, just as use STD ::env is

The Rust Library Tour

  1. Containers and collections The option and result modules define types of optional and error handling: option

    and result

    . The iter module defines Rust’s Iterator trait Iterator, which is used with the for loop to access collections.
    ,>
The library exposes three common ways of dealing with contiguous areas of memory:

  • Vec

    – A heap allocation vector /vector that is resizable at run time
  • [T; n] – An inline array of fixed size at compile time
  • [T] – Any type of continuous storage that holds dynamically sized slices, regardless of heap allocation
Slicing can only be processed by some kind of pointer, so there are many forms, such as:

  • &[T] – Share slices
  • &muT [T] – Variable slice
  • Box<[T]> – Owns slices
STR, UTF-8 string slicing is a primitive type for which the library defines many methods. Rust STR is usually accessed as an immutable reference: & STR. Use owned /owned String to construct and mutable strings

To convert to a string, use format! Macro; To convert from a string, use the FromStr attribute.

Data can be shared by placing it in a reference-counting box or Rc type, and mutated and shared if it is further included in a Cell or RefCell. Likewise, in a concurrent setting it is common to pair an atomically-reference-counted box, Arc, with a Mutex to get the same effect.

The Collections module defines maps, sets, Linked Lists, and other typical collection types, including HashMap

.
,>

2. Platform abstractions and I/O In addition to basic data types, the library focuses on abstractions that differ from common platforms, especially Windows and Unix derivations

Common types of I/O, including files, TCP, UDP, are defined in IO, FS, and NET modules.

Sync further contains other raw shared memory types, including Atomic and MPSC, which contain channel types for messaging.

Module STD: : thread

Threading model

The executing Rust program contains a set of native OS threads, each with its own stack and local state. You can name threads and have some built-in support for low-level synchronization.

Communication between threads can be accomplished through channels, the messaging types of Rust, and other forms of thread synchronization and shared memory data structures. In particular, the container type Arc, which uses atomic reference counting, can be easily shared between threads and is thread-safe.

A fatal logical error in Rust causes a thread to crash, during which the thread unwinds the stack, runs the destructor, and frees the resources it owns. Although this is not a ‘try/catch’ mechanism, the panic of Rust can still be caught by catch_unwind (except for compilation using ‘panic=abort’) or recovered from it by resume_unwind. Panic exits if it does not catch the thread, but panic can optionally be detected from other threads via join. If the main thread panics and is not caught, the application exits with a non-zero exit code.

When the main thread of a Rust program terminates, the entire program shuts down even if other threads are still running. However, this module provides the convenience of automatically waiting for a child thread to terminate (that is, join).

Produce thread

We can use the thread::spawn function to generate a new thread:

use std::thread;

thread::spawn(move|| {
    // some work here
});Copy the code
In this example, the generated thread is “detached” from the current thread. This means that it can live outside of its parent thread (the thread that produced it), unless that parent thread is the main thread.

The parent thread can also wait for the child thread to complete and call the JoinHandle created by the spawn thread.

use std::thread;

let child = thread::spawn(move|| {
// some work here
});
// some work here

let res = child.join();Copy the code
The join method returns a thread::Result containing the contents of the final value produced by the child thread Ok, or the child thread panic! To call Panic! .

Configuration of the thread

A new thread can be configured before it is generated using the Builder type, which currently allows you to set the name and stack size of the child thread:

use std::thread;
			
thread::Builder::new().name("child1".to_string()).spawn(move|| { println! ("Hello, world!");
});Copy the code

The Thread type

Threads are represented by Thread type, which you can obtain in one of two ways:

  • Call Thread in JoinHandle by generating a new thread, for example, using the Thread ::spawn function.
  • By requesting the current thread, use the thread::current function.
The Thread ::current function applies even to threads that are not generated by the module API

Thread-local storage

The module also provides an implementation of thread-local storage for Rust programs. Thread-local storage is a method of storing data in global variables, with each thread in the program having its own copy. Threads do not share this data, so synchronous access is not required.

A thread-local key has a value that it contains, and that value is destroyed when the thread exits. It uses thread_local! Macro creation that can contain any ‘static ‘value. It provides an accessor function that produces a shared reference to the value of the specified closure. Thread-local keys only allow shared access values, because uniqueness cannot be guaranteed if variable borrowing is allowed. Most values are expected to take advantage of some form of internal variability through Cell or RefCell types.

Named after the thread

Threads can have associated names for identification. By default, the generated thread is unnamed. To specify a name for a thread, build the thread using Builder and pass the desired thread name to Builder::name. To retrieve a Thread name from within a Thread, use Thread::name. A few examples of places where thread names are used:

  • If panic occurs on named threads, the thread name is displayed in the Panic message
  • Provide thread names to the OS where applicable (for example, pthread_setname_NP on Unix-like platforms).

Stack size

The default stack size for a generated thread is 2 MiB, although this specific stack size may change in the future. There are two ways to manually specify the stack size of the generated thread:

  • Build the thread with Builder and pass the desired stack size to Builder::stack_size.
  • Set the RUST_MIN_STACK environment variable to an integer representing the desired stack size in bytes. Note that setting Builder::stack_size overrides this setting.
Note that the stack size of the main thread is not determined by Rust