When building async futures, it's common to implement the ArcWake trait in wakers. I understand this is done to avoid writing boilerplate, creating vtables and writing unsafe code (according to the tokio tutorial).
Now, (and this feels like a silly question) what I don't understand is how does implementing a trait avoid writing that other code? When I check the source of the trait, it contains practically nothing: only the declaration of one small function that needs to be implemented to fulfil the trait and the instantiation of another function that calls that one. So, where are all those things we're avoiding writing coming from? Where's the boilerplate, vtables, unsafe code and all that and how does it get executed just because we implemented a trait on a waker?
OK, I think I got it now. The code I couldn't find is here (thanks for the comment on the question that pointed this out!). That code is all called on the tutorial when the future is polled, specifically on the line
let waker = task::waker(self.clone());
On this line, we're obtaining a waker from an ArcWake by calling the task::waker function which deals with all the complexity for us.
Related
I'm pretty new to Rust and have been working on some mathematical problems. For one of these problems I needed ceilf32 and sqrtf32. I was surprised to find that these functions are unsafe; both are fairly simple mathematical functions and my understanding is that unsafe Rust is used only as necessary to work around either the conservatism of the compiler or to allow inherently unsafe OS operations. I can't see any reason either function would run into either issue, thus I can't understand what would stop them being implemented with memory safety.
Could someone please enlighten me?
The functions you're looking at are in core::intrinsics, which are low-level compiler instructions. I don't see any official documentation on why they're marked unsafe, but my guess is that all of the compiler intrinsics were marked that way as a rule, since they're lower-level than most of Rust proper.
Regardless, for normal operation, you're looking for the inherent methods f32::ceil and f32::sqrt. These are the Rust standard library implementations that presumably[1] call the intrinsics as a course of action, and these methods are not marked unsafe.
Since they're inherent methods, you can either call them on f32 objects (my_number.sqrt()) or directly with the namespace (f32::sqrt(my_number)).
[1] In fact, a look at the source code for the current implementations indicates that both of these simply delegate to their intrinsic counterpart, wrapping it in an unsafe block to guarantee safety.
The documentation at https://doc.rust-lang.org/std/convert/trait.From.html states
Note: This trait must not fail. If the conversion can fail, use TryFrom.
Suppose I have a From implementation thus:
impl From<SomeStruct> for http::Uri {
fn from(item: SomeStruct) -> http::Uri {
item.uri.parse::<http::Uri>() // can fail
}
}
Further suppose I am completely certain that item.uri.parse will succeed. Is it idiomatic to panic in this scenario? Say, with:
item.uri.parse::<http::Uri>().unwrap()
In this particular case, it appears there's no way to construct an HTTP URI at compile time: https://docs.rs/http/0.2.5/src/http/uri/mod.rs.html#117. In the real scenario .uri is an associated const, so I can test all used values parse. But it seems to me there could be other scenarios when the author is confident in the infallibility of a piece of code, particularly when that confidence can be encoded in tests, and would therefore prefer the ergonomics of From over TryFrom. The Rust compiler, typically quite strict, doesn't prevent this behaviour, though it seems it perhaps could. This makes me think this is a decision the author has been deliberately allowed to make. So the question is asking: what do people tend to do in this situation?
So in general, traits only enforce that the implementors adhere to the signatures and types as laid out in the trait. At least that's what the compiler enforces.
On top of that, there are certain contracts that traits are expected to adhere to just so that there's no weird surprises by those who work with these traits. These contracts aren't checked by the compiler; that would be quite difficult.
Nothing prevents you from implementing all a trait's methods but in way that's totally unrelated to what the trait is all about, like implementing the Display trait but then in the fmt method not actually bothering to use write! and instead, I don't know, delete the user's home directory.
Now back to your specific case. If your from method will not fail, provably so, then of course you can use .unwrap. The point of the cannot fail contract for the From trait is that those who rely on the From trait want to be able to assume that the conversion will go through every time. If you actually panic in your own implementation of from, it means the conversion sometimes doesn't go through, counter to the ideas and contracts in the From trait.
When I am experimenting with a new language that I'm unfamiliar with, my hello world is listing all IPv4 found in a mixed file (for example a log file). I think it is a good exercise because it gets me to practice with IO, packages, functions, regexes and iterators.
I tried for 2-3 hours to accomplish that in Rust, I still haven't found any elegant way to do it. I'm obviously doing it wrong.
Can anyone show me their solution to achieve this? It will help my brain to unlock by seeing the most efficient/elegant way. Or do you recommend me to continue to bash on the pile until I have it right?
Passing a file name to a function, which returns iterator of all IPv4 in that file.
I saw that Rust support iterators as well as generators/yield. I would like to see solutions for both if possible.
For the simplicity I avoid error handling (with unwrap and expect), since it may harm readability. For that kind of task you don't need an external crates (e.g. regexes), because some parsing already implemented in standard library with FromStr. For the per-line reading a BufRead trait with BufReader wrapper might do the thing. And composed it becomes (playground):
fn iterate_over_ips(filename: impl AsRef<Path>) -> impl Iterator<Item = Ipv4Addr> {
let file = File::open(filename).unwrap();
io::BufReader::new(file)
.lines()
.map(|line| line.expect("line read").parse().expect("ip invalid format"))
}
Generator is an unstable feature (so its API may change anytime) and for now mostly used internally by a compiler for asynchronous code. Iterators are way better for this particular task.
When providing callbacks to JavaScript using Closures, what's a better way to deal with avoiding freeing them? The wasm-bindgen guide suggests using .forget, but admits that that is essentially leaking memory.
Normally we'd store the handle to later get dropped at an appropriate time but for now we want it to be a global handler so we use the forget method to drop it without invalidating the closure. Note that this is leaking memory in Rust, so this should be done judiciously!
It hints at storing the closure until a time when it's appropriate to be dropped. In alexcrichton's answer to a previous question, he mentions...
[...] if it's [...] only invoked once, then you can use Rc/RefCell to drop the Closure inside the the closure itself (using some interior mutability shenanigans)
But he doesn't provide an example of this method.
The Closure documentation also gives an example of returning the reference to the closure to the JavaScript context to let it handle when to free the reference.
If we were to drop cb here it would cause an exception to be raised whenever the interval elapses. Instead we return our handle back to JS so JS can decide when to cancel the interval and deallocate the closure.
I'd also imagine there are ways to use features like lifetimes or the #[wasm_bindgen] macro on a public function to avoid this issue as well, but I'm having trouble figuring out how to do it that way.
My question is, what are the alternatives to using .forget with closures that are being passed back to JavaScript from Rust, and can I please see some simple examples of each option in use?
I recently built a small commercial app and was stuck on this for weeks and was really excited when I got this working. I ended up using Closure.once_into_js. However, that also has the caveat that "The only way the FnOnce is deallocated is by calling the JavaScript function. If the JavaScript function is never called then the FnOnce and everything it closes over will leak." So if the callback is called, everything should be fine, but if not, there is still a memory leak. I found the programming style to be pretty nice. I mapped the JavaScript functions to Rust like this:
#[wasm_bindgen]
fn getSomething(details: &JsValue, callback: JsValue);
pub fn get_something(details: &Details, callback: impl Fn(Option<String>) + 'static){
getSomething(&serde_wasm_bindgen::to_value(details).unwrap(), Closure::once_into_js(move |v: JsValue|
callback(serde_wasm_bindgen::from_value(v).unwrap())
));
}
And then I'm able to use it from Rust in my app like so:
let callback = move |id| {
};
get_something(&details, callback);
I defined the callbacks as static impl functions and then move the values in.
Learning Rust (yay!) and I'm trying to understand the intended idiomatic programming required for certain iterator patterns, while scoring top performance. Note: not Rust's Iterator trait, just a method I've written accepting a closure and applying it to some data I'm pulling off of disk / out of memory.
I was delighted to see that Rust (+LLVM?) took an iterator I had written for sparse matrix entries, and a closure for doing sparse matrix vector multiplication, written as
iterator.map_edges({ |x, y| dst[y] += src[x] });
and inlined the closure's body in the generated code. It went quite fast. :D
If I create two of these iterators, or use the first a second time (not a correctness issue) each instance slows down quite a lot (about 2x in this case), presumably because the optimizer no longer chooses to do specialization because of the multiple call sites, and you end up doing a function call for each element.
I'm trying to understand if there are idiomatic patterns that keep the pleasant experience above (I like it, at least) without sacrificing the performance. My options seem to be (none satisfying this constraint):
Accept dodgy performance (2x slower is not fatal, but no prizes either).
Ask the user to supply a batch-oriented closure, so acting on an iterator over a small batch of data. This exposes a bit much of the internals of the iterator (the data are compressed nicely, and the user needs to know how to unwrap them, or the iterator needs to stage an unwrapped batch in memory).
Make map_edges generic in a type implementing a hypothetical EdgeMapClosure trait, and ask the user to implement such a type for each closure they want to inline. Not tested, but I would guess this exposes distinct methods to LLVM, each of which get nicely inlined. Downside is that the user has to write their own closure (packing relevant state up, etc).
Horrible hacks, like make distinct methods map_edges0, map_edges1, ... . Or add a generic parameter the programmer can use to make the methods distinct, but which is otherwise ignored.
Non-solutions include "just use for pair in iterator.iter() { /* */ }"; this is prep work for a data/task-parallel platform, and I would like to be able to capture/move these closures to work threads rather than capturing the main thread's execution. Maybe the pattern I should be using is to write the above, put it in a lambda/closure, and ship it around instead?
In a perfect world, it would be great to have a pattern which causes each occurrence of map_edges in the source file to result in different specialized methods in the binary, without forcing the entire project to be optimized at some scary level. I'm coming out of an unpleasant relationship with managed languages and JITs where generics would be the only way (I know of) to get this to happen, but Rust and LLVM seem magical enough that I thought there might be a good way. How do Rust's iterators handle this to inline their closure bodies? Or don't they (they should!)?
It seems that the problem is resolved by Rust's new approach to closures outlined at
http://smallcultfollowing.com/babysteps/blog/2014/11/26/purging-proc/
In short, Option 3 above (make functions generic with respect to a new closure type) is now transparently implemented when you make an implementation generic using the new closure traits. Rust produces the type behind the scenes for you.