6 ms·
You're talking here about the second half of your previous comment. This reasoning is ok by me, though I have to wonder how often, and why, do programmers nee
by aasasd 6y ago
You're talking here about the second half of your previous comment. This reasoning is ok by me, though I have to wonder how often, and why, do programmers need to decide dynamically in mid-flight whether they want to wait instead of wake (or whatever choices futex() offers), or that they need one handle instead of a vector.
I'm talking above about the first half of your previous comment, where you say that having operation names in the function names would somehow require multiple calls and break atomicity. I can only understand this if Linux syscalls are parameterized to do one thing and then another thing and something else, in one call—which sounds horrible, but still can be expressed in function names.
- whatshisface 6y ago>I'm talking above about the first half of your previous comment, where you say that having operation names in the function names I was addressing operation names in the function names in the second half of my comment, in the first half I was addressing breaking up specification into a state machine process like OpenGL does. State machines are another way of breaking up big functions with lots of options. They have pseudo default argument support as an advantage, and ease of implementation via static globals as a historical (before multithreading) advantage. State machines are kind of like builder pattern as a way to get named arguments and default arguments in a language that doesn't have either, except instead of the builder being a class it's a singleton (with all the attendant disadvantages.)
- aasasd 6y agoAh, no, that's also contrary to my taste. I love clear function names and I hate state. Immutable return values are way better than builders, in my experience, even if that means many arguments. And static globals are a whole other level of bad.
- whatshisface 6y agoBuilders can be a huge help when you get up to a dozen arguments and above. Seriously, I never want to see foo(13,15,91,39,LIB_YES,LIB_NO,5.0,183.5) ever again haha. Good engineers would comment each argument, good languages support named arguments, but when you have neither it can be a mess unless the library author used builders to force annotation of the values. A close relative of builders are settings struct arguments, which have their own pros and cons. I think Vulkan uses settings structs.
- aasasd 6y agoI think OOP builders can work without extra state if they implement `->addThis()->addThat()` by actually doing functional `addThat(addThis(defaultObj))` and creating immutable values inside. But ultimately there's no good answer to the absence of named arguments, and by now not having them is a pure atrocity. Of course, I'm guessing C programmers would cringe at the prospect of going full COW for such use-cases.
- whatshisface 6y agoThe downside of your second syntax for builders is when you need to add arguments. People will have a hard time remembering whether it's supposed to be addFoo(1,addBar(2)), addFoo(addBar(2),1), or any of the other combinatorially exploding number of possible arrangements as the complexity of the construction is increased. With the OOP design, the values go inside the addFoo(1)->addBar(2) and it's obviously constrained to that one way of writing it. When writing function signatures that are going to be nested I try to keep one type in the arguments and I try to make them commutative (so that it works the same way in any order.) That's not always possible but it helps people remember how to write calls.
- aasasd 6y agoWell, the convention in theory is usually that `object->method(param)` is equivalent to `method_function(object, param)`, and likewise you have the signature of `method(self, param)` in languages where `self` is an explicit argument—if only because it's always present so makes sense to always have it first. Thus, translating an OOP builder would make the functions `addThis(object, param)` =) With the difference in my proposal that the object is treated as a COW.
- xiphias2 6y agoEfficient OpenGL programming was always hard for me, as I don't just need to learn the API, but also try to figure out how it's implemented, which is often undocumented and unspecified. It's actually hard to understand for me that an API that was created for efficient computing doesn't specify/guarantee the relative speed/latency of operations.
- whatshisface 6y agoYeah, there are some really interesting unexpected performance implications - for instance, it's actually a great idea to send updates to buffers in a way that implies new allocation, because most drivers will silently and automatically set up a multiple-buffering system that reuses resources efficiently and doesn't stall the pipeline. Sending partial updates looks better on the surface, but because it can stall while the driver waits for the resource you're updating to fall out of use, it can be worse unless you set up the triple buffering yourself!
- gpderetta 6y agoThere is no direct function calls into the kernel. At the end of the day a function call is an interrupt with the syscall parameters in a bunch of registers. As you do not want to use a different interrupt (as there are only so many interrupts [1]) for each function call, the syscall id is passed as a parameter in a register. On the kernel side the id is used to index in a function pointer table to find and call the actual system function. Turns out this table is actually limited in size so some related syscalls use another level of indirection with additional private tables (I think this is no longer a limitation and these syscall multiplexers are frowned upon for newer syscalls). All of this to say that FUTEX_WAIT and FUTEX_WAKE are just implementation details. A proper syscall wrapper would just expose distinct functions for each operation. But for a very long time glibc did not expose any wrapper for futexes as they were considered linux specific implementation details and one was supoosed to use the portable posix functions. So the futex man pages documented the raw kernel interface. That didn't stop anybody from using futexes of course and I think glibc now has proper wrappers. [1] yes, these days you would use sysenter or similar, but same difference.
- aasasd 6y agoThanks, this actually answers my original question in regard to the kernel's part of it. I'll take a look at what names and signatures libc has, and if they're still like that then the question is readdressed to libc—though I guess the answer then would be “because that's how it is in the kernel”. P.S. Come to think of it, I sorta knew about the interrupt business, and vaguely about the later but fundamentally similar method (but not that there are many interrupts for syscalls, though thinking about eight-bit registers clears this up quickly). Guess I just forgot that libc is kept separate from the kernel, in the Linux world.