Live data from Hacker News

Giving up on wlroots-rs

way-cooler.org

101–110 of 126 posts

Re: Giving up on wlroots-rs

#101
I only skimmed the article, but the description of outputs and their asynchronous lifecycle making things complicated just made me think of what's become known as the ECS pattern in game development.

Your outputs sound just like entities in a game. They come and go as they please, and you often have multiple references to them from myriad places since entities may interact with many parts of the game.

I suspect if you investigated the established techniques for implementing ECS-style games in rust, you might find some simpler and established solutions for your troubles.

Re: Giving up on wlroots-rs

#102

Earlier quoted context omitted.

That's really not what I'm talking about. In your example you are using multiple iterators to iterate over the same structure multiple times, but in C++ you can use pairs of iterators to represent ranges. For example, I can have three iterators i, j, and k, which represent two ranges: i..j and j..k. Even if i, j, k are const iterators, it's not pleasant to translate this to Rust. So it's not an issue of whether Rust…

Is that different from something like this? fn main() { let list = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; let i = 0; let j = 4; let k = 8; let iter_ij = list[i ..= j].iter(); let iter_jk = list[j ..= k].iter(); let pairs = Iterator::zip(iter_ij, iter_jk); for (a, b) in pairs { println!("{}, {}", a, b); } }

Yes, that is different, because in C++ you can move j forward and backwards.

Re: Giving up on wlroots-rs

#103

Earlier quoted context omitted.

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…

> but the C++ type system gives you no way to create an object with lifetimes that don't correspond to some scope. Counterexample: a data member of a class has a lifetime tied to the lifetime of the containing object instance, rather than to a lexical scope.

You are just using the same storage duration as the containing object instance, and the C++ type system only gives you any guarantees for automatic, static, and thread storage duration. These all correspond directly to lexical scopes. The type system does not have a way to express dynamic storage duration, but Rust does because Rust has move semantics in the type system. C++ has move semantics, but they are runtime semantics built into the implementation of the library and not part of the type system, so you get no compile-time checking that you used move semantics correctly.

Phrased another way, I'm just saying that the C++ type system only expresses two types of storage durations: those tied to lexical scopes and dynamic storage durations, and provides no checks for dynamic storage durations.

Re: Giving up on wlroots-rs

#104

Earlier quoted context omitted.

Is that different from something like this? fn main() { let list = &[0, 1, 2, 3, 4, 5, 6, 7, 8]; let i = 0; let j = 4; let k = 8; let iter_ij = list[i ..= j].iter(); let iter_jk = list[j ..= k].iter(); let pairs = Iterator::zip(iter_ij, iter_jk); for (a, b) in pairs { println!("{}, {}", a, b); } }

Yes, that is different, because in C++ you can move j forward and backwards.

Ahh, I see, thanks for clarifying. Rust's Iterators are similar to C++ ForwardIterators. It seems C++'s default is BidirectionalIterator.

Re: Giving up on wlroots-rs

#105
post #98
post #36

Earlier quoted context omitted.

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.

So it's way-cooler.com's fault for not explaining what their library/website is about. Which unfortunately is par for the course on 99% of company blogs, which never explain what the company does without going onto the homepage (which even then is often confusing).

It's not a company blog. It's a some guy's open source side project. Ya' know... free... open source... side project... that's he's voluntarily sharing technical information on.

Really, it's not the guy's responsibility to over-inflate the article because some people need their hand held. It's a blog about about Rust, Wayland, and window managers. If you don't know what those things are then, like, Wikipedia is there for you, man.

It's like going to a programming languages website and going "well, gee, these guys suck for not explaining what a programming language is on their homepage what is with everyone being so discourteous!?"

And it's not like a paragraph of context would have mattered anyways; if you don't know what Rust is, what Wayland is, or what tiling window managers are then you'll need a lot more background knowledge before the article's content begins to be assailable.

Re: Giving up on wlroots-rs

#106
post #56

Earlier quoted context omitted.

And just think about what most file and I/O wrappers, that are part of the standard library in most higher level languages, e.g. file objects in python, streams in C++ etc., naturally do: They also just wrap (for example) POSIX file descriptors, which are handles, with their own handles, i.e. the file object/Stream/whatever.

Maybe I didn't explain what's happening in OpenGL properly, because that comparison doesn't work at all. With e.g. std::ofstream, you are wrapping a handle, such as a POSIX file descriptor. So that part of your description is accurate. However, this is different from what happens with OpenGL. The problem is that if you wrap an OpenGL texture (which is a handle), you end up with some problems because you can only free…

They don't behave like file handles - but at a certain distance if you squint at it looks like the same problem. The real issue isn't that OpenGL textures don't behave like file handles, but that neither of them behave quite like objects in your language, which can lead to problems. The specifics of how the behavior differs is I think less important that the fact that it differs. Of course, file handles are not the best example because the language designers often had to put some thought into it early on; less true of something like OpenGL textures.

Re: Giving up on wlroots-rs

#107
post #14

Earlier quoted context omitted.

Speaking as someone who dabbled in Wayland in Rust before (but a few years ago so my knowledge might be outdated), has not tried wl-roots, and uses Rust a lot (a) Only when talking about interacting with C libraries written in a certain style. So not in general, and not with most C libraries, but yes for implementing wayland compositors. (b) Don't know (c) Absolutely a negative reflection , there are two ugly things…

>(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…

> Wayland is just a protocol, and a pretty simple one to boot.

For a Wayland client to render using hardware acceleration, it has to link to an OpenGL library (typically mesa, specifically EGL to set up the OpenGL context). Mesa (a library written in C) links to libwayland-client (also written in C). The problem is that mesa is expecting a pointer to a C struct that is defined in libwayland-client. It will cast that pointer and call libwayland-client functions.

Mesa could have been written to use a different level of abstraction (e.g. take a struct of function pointers) it would be possible to wire it up with your own wayland library.

It doesn't help that libwayland-client was designed to be stateful (since the protocol itself it stateful).

So, while technically you can write a wayland client without using libwayland-client, you cannot create an OpenGL context without rewriting mesa. You also cannot link directly or indirectly with ANY libraries that use libwayland-client.

So people give in, use C, and move their abstraction layers higher up in the stack.

Edit: grammar.

Re: Giving up on wlroots-rs

#108

Earlier quoted context omitted.

Yes, that is different, because in C++ you can move j forward and backwards.

Ahh, I see, thanks for clarifying. Rust's Iterators are similar to C++ ForwardIterators. It seems C++'s default is BidirectionalIterator.

Even C++ ForwardIterators are more powerful, because you can move them independently. Rust lets you move the beginning of the range forwards, and maybe the end of the range backwards. With ForwardIterator you would be able to move the end of the range forwards, making the range longer.

Re: Giving up on wlroots-rs

#109
post #106

Earlier quoted context omitted.

Maybe I didn't explain what's happening in OpenGL properly, because that comparison doesn't work at all. With e.g. std::ofstream, you are wrapping a handle, such as a POSIX file descriptor. So that part of your description is accurate. However, this is different from what happens with OpenGL. The problem is that if you wrap an OpenGL texture (which is a handle), you end up with some problems because you can only free…

They don't behave like file handles - but at a certain distance if you squint at it looks like the same problem. The real issue isn't that OpenGL textures don't behave like file handles, but that neither of them behave quite like objects in your language, which can lead to problems. The specifics of how the behavior differs is I think less important that the fact that it differs. Of course, file handles are not the b…

> …but at a certain distance if you squint at it looks like the same problem…

The whole discussion here is about how these things differ in subtle ways. The problem with “squinting” at the problem is you end up e.g. using RAII and then having to redesign your system because RAII doesn’t match, and the problems weren’t obvious when you started out.

Not to make too fine a point about it here, but file handles are perfect matches for RAII / Rust lifetimes, unlike OpenGL textures. You just close the handle at end of object lifetime. You can get errors when you close but current recommendation is to ignore errors when cleaning up and have a separate path for closing/committing data on close when writing, so on most paths the destructor will nop. This works well.

An example of a mismatch with the language semantics and file handles is with GC. If you close a file handle in a C++ destructor or Rust drop(), it’s fine, those are run deterministically. If you use a JVM finalizer to close your file handle that might not happen soon enough (cue EMFILE).

Again, the reason why textures don’t work this way is because you have to release them in a certain context and they might be released outside your control.

Re: Giving up on wlroots-rs

#110
post #107

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…

> Wayland is just a protocol, and a pretty simple one to boot. For a Wayland client to render using hardware acceleration, it has to link to an OpenGL library (typically mesa, specifically EGL to set up the OpenGL context). Mesa (a library written in C) links to libwayland-client (also written in C). The problem is that mesa is expecting a pointer to a C struct that is defined in libwayland-client. It will cast that…

Thank you for spelling out the details, I knew the issue existed but forgot the details.
Post reply on HN