I'm trying to use Arc in my code, but as i read the document, there is 2 places Arc is defined: std crate and alloc crate. So, what is the different between alloc::sync::Arc and std::sync::Arc?
From the alloc crate documentation:
This library provides smart pointers and collections for managing heap-allocated values.
This library, like libcore, normally doesn’t need to be used directly since its contents are re-exported in the std crate. Crates that use the #![no_std] attribute however will typically not depend on std, so they’d use this crate instead.
So there's no difference between std::sync::Arc and alloc::sync::Arc.
alloc also provides Box, Vec, String, the collections module, and basically anything in the standard library that requires allocations (hence alloc) but not an underlying OS (filesystem, networking, etc). alloc is there if you want to write bare-metal (unhosted) software that still gets to use the nice standard library data structures.
Related
These two traits (std::ops::Add, core::ops::Add) provide the same functionality, and they both use the same example (both utilize std::ops::Add). Their set of implementors differ somewhat.
Should one default to using std::ops::Add? Why do both, as opposed to one, of them exist?
There aren't two traits. There is one trait which is exported under several interchangeable names. This is far from unique. Virtually everything in core is also exported from std, and virtually always under exactly the same path (i.e., you can just replace the "core" prefix with "std").
As for which one you should use: If you have a reason to not link to the standard library (#![no_std]), then the std::* one isn't available so obviously you use core::*. If on the other hand you do use the standard library, you should use the std::* re-export. It is more customary and requires less typing.
They're in fact exactly the same, despite the set of implementors being listed as slightly different.
The core library is designed for bare-metal/low-level tasks, and is thus more barebones than what std can provide by assuming an operating system exists. However, people using std will want the stuff that's in core too (e.g. Add or Option or whatever), and so to avoid having to load both std and core, std reexports everything from core, via pub use. That is, std provides aliases/import paths for the things in core.
There are some unfortunate error messages where the compiler points to the original source of an item, not the reexport, which might not be in a crate you're extern crateing.
I'm currently in the progress of learning Rust. I'm mainly using The Rust Programming Language book and this nice reference which relates Rust features/syntax to C++ equivalents.
I'm having a hard time understanding where the core language stops and the standard library starts. I've encountered a lot of operators and/or traits which seems to have a special relationship with the compiler. For example, Rust has a trait (which from what I understand is like an interface) called Deref which let's a type implementing it be de-referenced using the * operator:
fn main() {
let x = 5;
let y = Box::new(x);
assert_eq!(5, x);
assert_eq!(5, *y);
}
Another example is the ? operator, which seems to depend on the Result and Option types.
Can code that uses those operators can be compiled without the standard library? And if not, what parts of the Rust language are depending on the standard library? Is it even possible to compile any Rust code without it?
The Rust standard library is in fact separated into three distinct crates:
core, which is the glue between the language and the standard library. All types, traits and functions required by the language are found in this crate. This includes operator traits (found in core::ops), the Future trait (used by async fn), and compiler intrinsics. The core crate does not have any dependencies, so you can always use it.
alloc, which contains types and traits related to or requiring dynamic memory allocation. This includes dynamically allocated types such as Box<T>, Vec<T> and String.
std, which contains the whole standard library, including things from core and alloc but also things with further requirements, such as file system access, networking, etc.
If your environment does not provide the functionality required by the std crate, you can choose to compile without it. If your environment also does not provide dynamic memory allocation, you can choose to compile without the alloc crate as well. This option is useful for targets such as embedded systems or writing operating systems, where you usually won't have all of the things that the standard library usually requires.
You can use the #![no_std] attribute in the root of your crate to tell the compiler to compile without the standard library (only core). Many libraries also usually support "no-std" compilation (e.g. base64 and futures), where functionality may be restricted but it will work when compiling without the std crate.
DISCLAIMER: This is likely not the answer you're looking for. Consider reading the other answers about no_std, if you're trying to solve a problem. I suggest you only read on, if you're interested in trivia about the inner workings of Rust.
If you really want full control over the environment you use, it is possible to use Rust without the core library using the no_core attribute.
If you decide to do so, you will run into some problems, because the compiler is integrated with some items defined in core.
This integration works by applying the #[lang = "..."] attribute to those items, making them so called "lang items".
If you use no_core, you'll have to define your own lang items for the parts of the language you'll actually use.
For more information I suggest the following blog posts, which go into more detail on the topic of lang items and no_core:
Rust Tidbits: What Is a Lang Item?
Oxidizing the technical interview
So yes, in theory it is possible to run Rust code without any sort of standard library and supplied types, but only if you then supply the required types yourself.
Also this is not stable and will likely never be stabilized and it is generally not a recommended way of using Rust.
When you're not using std, you rely on core, which is a subset of the std library which is always (?) available. This is what's called a no_std environment, which is commonly used for some types of "embedded" programming. You can find more about no_std in the Rust Embedded book, including some guidance on how to get started with no_std programming.
Usually one should be wary of transmuting (or casting) pointers to a higher alignment. Yet the interface to the above functions require *const _m128i and *mut _m128i pointers, respectively. Both are SIMD-aligned, which means I'd need to keep my arrays SIMD-aligned, too. On the other hand, the intrinsics are explicitly designed to load/store unaligned data.
Is this safe? Shouldn't we change the interface? Or at least document this fact?
I think this is a cross-language duplicate of Is `reinterpret_cast`ing between hardware vector pointer and the corresponding type an undefined behavior?.
As I explained over there, Intel defined the C/C++ intrinsics API such that loadu / storeu can safely dereference an under-aligned pointer, and that it's safe to create such pointers, even though it's UB in ISO C++ even to create under-aligned pointers. (Thus implementations that provide the intrinsics API must define the behaviour).
The Rust version should work identically. Implementations that provide it must make it safe to create under-aligned __m128i* pointers, as long as you don't dereference them "manually".
The other API-design option would be to have another version of the type that doesn't imply 16-byte alignment, like a __m128i_u or something. GNU C does this with their native vector syntax, but that's way off topic for Rust.
I'm essentially looking for malloc/free in Rust.
I found alloc::heap, but when I try to use it I get the following error:
main.rs:1:1: 1:19 error: unstable feature
main.rs:1 ![feature(alloc)]
note: this feature may not be used in the stable release channel
If you want to do it in high-level Rust (RAII, memory safety, bounds checking), you should allocate by creating a Vec. You can optionally use into_boxed_slice to disable resizing the container. See the book's FFI example (specifically the uncompress function) for an example of using Vec as an allocator.
Either use a nightly Rust or you will have to use libc::funcs::c95::stdlib::malloc(size: size_t) from the libc crate. You'll have to transmute the result of course.
I am looking for a way to implement something like a memory pool in Rust.
I want to allocate a set of related small objects in chunks, and delete the set of objects at once. The objects won't be freed separately. There are several benefits to this approach:
It reduces fragmentation.
It saves memory.
Is there any way to create a allocator like this in Rust?
It sounds like you want the typed arena crate, which is stable and can be used in Rust 1.0.
extern crate typed_arena;
#[derive(Debug)]
struct Foo {
a: u8,
b: u8,
}
fn main() {
let allocator = typed_arena::Arena::new();
let f = allocator.alloc(Foo { a: 42, b: 101 });
println!("{:?}", f)
}
This does have limitations - all the objects must be the same. In my usage, I have a very small set of types that I wish to have, so I have just created a set of Arenas, one for each type.
If that isn't suitable, you can look to arena::Arena, which is unstable and slower than a typed arena.
The basic premise of both allocators is simple - you allow the arena to consume an item and it moves the bits around to its own memory allocation.
Another meaning for the word "allocator" is what is used when you box a value. It is planned that Rust will gain support for "placement new" at some point, and the box syntax is reserved for that.
In unstable versions of Rust, you can do something like box Foo(42), and a (hypothetical) enhancement to that would allow you to say something like box my_arena Foo(42), which would use the specified allocator. This capability is a few versions away from existing it seems.
Funny thing is, the allocator you want is already available in arena crate. It is unstable, so you have to use nightlies to use this crate. You can look at its sources if you want to know how it is implemented.
You may want to look at arena::TypedArena in the standard library (Note: this is not stable and, as a result, is only available in nightly builds).
If this doesn't fit your needs, you can always examine the source code (you can click the [src] link in the top right of the documentation) to see how it's done.