Live data from Hacker News

Giving up on wlroots-rs

way-cooler.org

31–40 of 126 posts

Re: Giving up on wlroots-rs

#31
post #19

Earlier quoted context omitted.

I agree and was going to say the same. That there was a huge challenge in writing code to manage memory ownership, is not surprising because memory ownership is so fluid and adhoc in C and its derivatives. And when you are asked to make that ownership explicit, if the original designers hadn't been thinking about it, you get a lot of cases which they would not have considered. I would like to see a compositor written…

Not a wayland, wlroots or rust expert, but dollars to donuts says that it's not "memory" management[1] at issue, but resource allocation on the other side of the graphics driver. Vertex arrays, textures, framebuffers, shaders et. al. all need some kind of allocation strategy, can in the modern world often be shared between process contexts, and they really don't fit well into the metaphors of either C or Rust. But wh…

This is also something that causes some pain when using C++ with RAII. Logically it makes some amount of sense that you have e.g. a C++ wrapper for a texture in OpenGL, and it knows to call glDeleteTextures in its destructor.

HOWEVER, the destructor can now only be called if the OpenGL context is active, and the texture may be deleted if the context is lost (which can happen). At some point anybody who's tried to wrap an OpenGL texture with a C++ class either decides to accept that RAII doesn't completely work here, or refactors it so that you manage something like handles to textures, which is a bit silly because you are really at that point managing handles to handles to textures.

Re: Giving up on wlroots-rs

#32

A good post, thanks for sharing. > I want to make one (mildly controversial) thing clear: rewriting a library for the sake of only using Rust is not good engineering. Strong agree. > A literal rewrite of a project to Rust is not interesting, it’s not useful, it just causes churn and splits ecosystems. Time would be better spent either working with existing solutions that already have the effort put in to make them co…

I worked on projects that required complicated FFI bindings to C/C++ libraries. Creating, testing and maintaining such bindings always ends up a huge undertaking. Now I'd think twice. I imagine something like Wayland will have hundreds of functions and if one doesn't want to write C in Rust (which isn't that bad actually) then wrapping up such API is a Herculean task!

Re: Giving up on wlroots-rs

#33
post #28

How does Rust handle these problems in the context of file I/O? I'm sure there is an axiomatically idiomatic (official) implementation of it as part of the language distribution, and at the same time file handles seem conceptually very similar to display handles and should have similar failure patterns (space can run out, a disk can fail, a plug-and-play disk can be yanked out at any time...).

That is all here: https://doc.rust-lang.org/stable/std/fs/struct.File.html

These failure patterns are handled by each method, for example,

  pub fn open>(path: P) -> Result
that Result will return an error if the file can't be opened, etc. Let's say you want to write some bytes, that's

  fn write(&mut self, buf: &[u8]) -> Result
This also returns Result, so if you've opened the file, but the disk is now out of space, this will return an error, etc.

Re: Giving up on wlroots-rs

#34
post #22

Earlier quoted context omitted.

>(c) Absolutely a negative reflection, there are two ugly things going on here. The official wayland libraries use a ownership style that really only makes sense in C imho, and despite the claim that wayland is just a protocol you can't actually not use the official libraries, because the drivers only work with the official libraries. Not really sure what you're talking about here. Wayland is just a protocol, and a p…

At a glance, smithay depends on wayland-server depends on the official wayland libraries. More specifically the issue that makes this necessary is that it's the only way to get an OpenGL context (AIUI - it's been quite awhile since I worked on this). Rust is special in that's it's even worse at representing it, but the C controlled event-loop/fd-based-dispatching/ownership model wayland uses isn't idiomatic in any la…

Rust can handle event loops just fine; our entire asynchronous IO story is based on them!

Re: Giving up on wlroots-rs

#35

A good post, thanks for sharing. > I want to make one (mildly controversial) thing clear: rewriting a library for the sake of only using Rust is not good engineering. Strong agree. > A literal rewrite of a project to Rust is not interesting, it’s not useful, it just causes churn and splits ecosystems. Time would be better spent either working with existing solutions that already have the effort put in to make them co…

Author here.

>> A literal rewrite of a project to Rust is not interesting, it’s not useful, it just causes churn and splits ecosystems. Time would be better spent either working with existing solutions that already have the effort put in to make them correct or to come up with new green-field projects.

> This... I'm not so sure about. It really depends on what your objective is. For example, if your goal is to learn, you're not going to cause churn, and you're not going to split ecosystems. Working on project you already know well is a good way to learn, because you can focus on the language, not the project.

I was a little extreme with this comment, and I knew there were a bunch of footnotes like the ones you mentioned (pedagogically reinventing the wheel is great for learning!) I explicitly didn't mention those so I didn't water down my point.

Ultimately people can do what they want, and it won't really bother me. My comment was more of a critique on what is and isn't worth other's time. That is for them to decide, at the end of the day, it's just my opinion that I think they should question if all the effort they are going through is worth it. If they think it is, I wish them luck.

> The pain here isn't a re-write, it's an integration with an existing system.

I was conflating two ideas here that in retrospect I should have been clearer about.

wlroots-rs was definitely _not_ a RiiR, it was bindings. However as I came to butt against these problems it became obvious why other projects (like rlua and wayland-rs) are RiiR: because writing bindings is so difficult it is easier to start from scratch. At that point you are now rewriting a library for the sake of using Rust, which seems like a problem to me.

I don't know what Rust can do to make it easier to write these bindings. I think it's very important, but not something that has been focused on in the community because most of this work is very niche and there are other problems that are probably more interesting (async, web assembly, etc.)

Re: Giving up on wlroots-rs

#36

> Way Cooler is a Wayland compositor that was written in Rust using wlc I know it is not easy, but I wish the author could have started with a paragraph that could help someone like me know whether or not the rest of the article would be something I would like to read. How about something like this (and of course I may some of the facts wrong, but I want to be as constructive as I can): "Wayland is a Windows manager…

You weren't the audience of this article. Since he wrote it as a blog post on way-cooler.com he surely was expecting his audience to be people familiar with Way Cooler, Wayland and Rust. He doesn't have a responsibility to dumb it down for you. And anyway it only takes a few minutes for you to get the context. Which you did, good job.

Re: Giving up on wlroots-rs

#37
post #19

Earlier quoted context omitted.

Not a wayland, wlroots or rust expert, but dollars to donuts says that it's not "memory" management[1] at issue, but resource allocation on the other side of the graphics driver. Vertex arrays, textures, framebuffers, shaders et. al. all need some kind of allocation strategy, can in the modern world often be shared between process contexts, and they really don't fit well into the metaphors of either C or Rust. But wh…

This is also something that causes some pain when using C++ with RAII. Logically it makes some amount of sense that you have e.g. a C++ wrapper for a texture in OpenGL, and it knows to call glDeleteTextures in its destructor. HOWEVER, the destructor can now only be called if the OpenGL context is active, and the texture may be deleted if the context is lost (which can happen). At some point anybody who's tried to wra…

re: the handles to handles stuff ... I don't think that's so silly really, when you are talking about a resource that in some fundamental sense belongs to a different system (in this case OpenGL). Sure, that system gave you a handle, but if the semantics of managing that handle aren't 1:1 matched with your languages model of things, another level of indirection is a clean way to handle it.

Re: Giving up on wlroots-rs

#38
post #20
post #11

Earlier quoted context omitted.

Picture a pointer to video memory. Or, simpler, picture a pointer to an SHM section that either side of the SHM IPC conversation can deallocate. From both sides’ perspective, that pointer is probably implemented as both an SHM section, but also an SHM pointer to the section, such that either side can set the SHM pointer to NULL, and then (if they managed to do that) proceed to tell the SHM infrastructure to unmap all…

Quick answer, without understanding all the details: a weak-pointer-like structure that performed all the necessary locking and checking before giving out access to the underlying SHM. Rust's borrow checking is more or less a formalization of C++'s RAII style; in my experience, solutions for that translate relatively simply.

Rust's borrow checking does not correspond to RAII. A simplified explanation is that borrow checking gives you the guarantee that mutable references are unique and immutable references do not change.

Rust's lifetime system is vaguely like RAII, but the C++ type system gives you no way to create an object with lifetimes that don't correspond to some scope. In Rust this is done by moving values, but in C++ this is not possible, you have to fake it by using std::move(), which really just creates an rvalue reference.

One of the big things that causes problems in C++ is iterator invalidation. This is not solved with RAII, but it is solved in Rust with the borrow checker. The price you pay is that iterators in Rust are strictly less powerful than iterators in C++, because the way C++ iterators work cannot really be expressed in the Rust type system. (In short, C++ lets you have as many iterators as you like into the same container, and defines ranges as pairs of iterators. Some algorithms are more naturally expressed this way.)

Re: Giving up on wlroots-rs

#39

A good post, thanks for sharing. > I want to make one (mildly controversial) thing clear: rewriting a library for the sake of only using Rust is not good engineering. Strong agree. > A literal rewrite of a project to Rust is not interesting, it’s not useful, it just causes churn and splits ecosystems. Time would be better spent either working with existing solutions that already have the effort put in to make them co…

Author here. >> A literal rewrite of a project to Rust is not interesting, it’s not useful, it just causes churn and splits ecosystems. Time would be better spent either working with existing solutions that already have the effort put in to make them correct or to come up with new green-field projects. > This... I'm not so sure about. It really depends on what your objective is. For example, if your goal is to learn,…

btw, wayland-rs is both RiiR and bindings currently (native_lib cargo feature), and I've used it with libweston for custom protocols!

My project https://github.com/myfreeweb/weston-rs was also abandoned though. For a much simpler reason — I realized that I didn't need to reinvent the wheel — https://wayfire.org is everything I could possibly want from a compositor :)

Re: Giving up on wlroots-rs

#40
post #13

I can't speak to every issue which the author might have encountered, but there is a better solution to the lifetime management problem than the two mentioned in the article. Instead of this: fn some_wlroots_callback(output_handle: OutputHandle, surface_handle: SurfaceHandle) { output_handle.run(|output| { surface_handle.run(|surface| { // maybe some more nested layers... }).unwrap() }).unwrap() } One can do this: fn…

Author here. The problem with that design (which is a great design given what I presented in the article by the way!) is that it doesn't allow you to share handles across callbacks, which is mandatory to do anything interesting. I'm assuming here that you can't use the handles except for that callback context. If you can, then that presents a different problem. https://play.rust-lang.org/?version=stable&mode=debug&ed…

>If you can own a context, even with a lifetime parameter it's possible to leak it using the Box api.

The `std::pin::Pin` API prevents you from doing this (callbacks would receive `Pin`).

>The problem with that design (which is a great design given what I presented in the article by the way!) is that it doesn't allow you to share handles across callbacks

But how does sharing handles between callbacks look like? Is it something like "callback FooCreated provided me a Foo handle" and "callback BarCreated requires me to have the Foo from the FooCreated callback" ? So your FooCreated callback needs to save the Foo handle somewhere that it can be reused later?

If so, why is it not enough to have a `fn CallbackContext::set_foo_handle(&mut self, Foo)` (or `Pin` based on the above suggestion) ?

Post reply on HN