Earlier quoted context omitted.
> Really, "lock free" programming is just locking critical sections with lower level hardware primitives Can fence instructions really be seen as locking mechanism? While a lock generally is bound to some data, memory fences are bound to relationships between data or a piece of code. I don't know if Rust or any other language can help you with that. Isn't the actual bad practice to expose locks at all? If the locking…
The fences aren't a locking mechanism, at least not on their own. The lower (hardware) level locks are the steps in the cache coherency protocols (potentially including explicit cache line locking signals) that allow an execution unit to, eg, perform a correct atomic compare-exchange operation on a 32/64/128-bit piece of data. See also, eg, the LOCK prefix on x86 instructions. (disclaimer: I only have approximate kno…
Discipline Doesn’t Scale
141–150 of 173 posts
Re: Discipline Doesn’t Scale
#142TLDR: Humans make mistakes, use better tools/languages that prevent this, since discipline can't enforced. Wasted few minutes reading this blog post.
Re: Discipline Doesn’t Scale
#143Earlier quoted context omitted.
The feature backlog is rarely more important than performance but you often see it being pushed ahead of nonfunctional concerns for presentational reasons.
That’s... something. For the most part users or companies buy features, not performance. You can have the fastest software ever but if it doesn’t have the features I actually need to use it then, sorry, no dice. If performance is one of your features then fair enough, but it’s not for a lot of software.
This is NOT true. There is almost always an expectation that your application have a reasonable performance profile. It's often not a captured requirement, but I guarantee you once things slow to a crawl you WILL get an escalation.
Do you know what happens when escalations become too frequent? Progress grinds to a halt as developers have to churn out of what they're doing to address non-functional issues.
Somebody operating at a product owner level rarely has any concept of this stuff. It's up to the engineering team to be the bad guy and tell him or her that they're not going to get their laundry list satisfied in the time that's available and actually deliver usable software.
Re: Discipline Doesn’t Scale
#144Earlier quoted context omitted.
The feature backlog is rarely more important than performance but you often see it being pushed ahead of nonfunctional concerns for presentational reasons.
I am actually interested in your context. Usually the return on investment analysis favors features over performance especially in a B2B environment.
- If your product does not work it does not work, regardless of what you have in your requirements.
Re: Discipline Doesn’t Scale
#145Earlier quoted context omitted.
I suppose it depends on what you would consider being “serious” about memory safety. I view move semantics as not a memory safety thing at all (in fact, use-after-move can be exactly as ugly as use-after-delete), and smart pointers as a “let’s just make things marginally better than raw raw new/delete” thing. Smart pointers in C++ can still be null, after all. Calling C++ not serious about seems a reasonable take to…
When I think about C++ "smart" pointers, I often think about easy to provoke / difficult to spot fatal edge cases. E.g. - C++ code where some method calls std::shared_from_this(), and that method ends up being called indirectly during the object's construction, leading to a 0-pointer dereference [1] - accidentally creating two shared-pointers to the same object leading to an eventual double-free (that may just silent…
OTOH, C++ needs the ability to support old code bases because of its age. Of course a new language can forego this.
As for cycles, for GC language using ref-counting under the hood, the same problem applies. I've also seen memory leak from accidental keeping of pointers in fully GC languages. I've seen it happens in Java multiple times. Of course, two wrongs don't make right, but in this case GC is only solving one case.
But the more fundamental issue at play is that pointer cycles usually means a lack of up-front design and thought about how a program will work. As such, it is bad, but only a symptom of a lack of proper initial design which can manifest itself in all kind of places.
Re: Discipline Doesn’t Scale
#146Over a decade ago I used to argue this with the C++ committee people. Back then, they were not concerned about memory safety; they were off trying to do too much with templates. The C++ people didn't get serious about safety until Rust came along and started looking like a threat. Now they're trying to kludge Rust features into C++ by papering over the unsafe stuff with templates, with some success. But the rot under…
Rust is not a good example of a language which doesn't require discipline: on the contrary, it requires very much discipline and thinking deeply about lifetimes and resources. The difference to C++ (since that's what you've mentioned) is that the compiler double-checks everything at the end. The advance in programming language usability will not come from arcane tools like Rust, but from tools like Java, Python or Go…
This is exactly what makes it so that the programmer doesn't have to be disciplined. The Rust compiler will correct the lazy Rust programmer, while the C++ compiler will blithely do its best.
Re: Discipline Doesn’t Scale
#147Earlier quoted context omitted.
Smart pointers + static analysis + sanitizers is the best options I am aware of for improving the correctness of C++ programs, and I don't think Rust really had much to do with them. The picture painted that Rust made the C++ standards committee scramble to start addressing safety seems wrong; it feels more like there's been a mostly steady increase in safety over time without need for any outside influence.
> Smart pointers + static analysis + sanitizers I feel like you just defeated your point; those are bolted on instead of a natural part of the language.
Re: Discipline Doesn’t Scale
#148Over a decade ago I used to argue this with the C++ committee people. Back then, they were not concerned about memory safety; they were off trying to do too much with templates. The C++ people didn't get serious about safety until Rust came along and started looking like a threat. Now they're trying to kludge Rust features into C++ by papering over the unsafe stuff with templates, with some success. But the rot under…
IMHO, types for function parameters depends on the use case. If you have a function in a standard library, types are obviously helpful, albeit it can be convoluted if they are templated. On the other end of the scale, if you have a little helper function used to reduce duplication/increase readability in another function, explicit typing easily becomes busywork. This is where duck typing/templates shines. I once sent…
Similarly, you can use auto as a return type if the function implementation is immediately given and the compiler with infer the return type. The new starship operator () typical usage is pretty much declaring it with an auto return type and "= default" implementation.
Re: Discipline Doesn’t Scale
#149Earlier quoted context omitted.
When I say lock free, im suggesting concurrency that doesn't assume shared memory. I think the notion of multiple cores working on nearby memory blocks just is a bad way to do this, and so threaded models are not great. More along the lines of an actor model or how gpus subdivide work.
> [...] how gpus subdivide work. That's a bad example: GPUs are all about shared memory, concurrently accessed by many threads. It's up to the programmer to make sure that there are no read/write or write/write data races.
Re: Discipline Doesn’t Scale
#150Earlier quoted context omitted.
When I think about C++ "smart" pointers, I often think about easy to provoke / difficult to spot fatal edge cases. E.g. - C++ code where some method calls std::shared_from_this(), and that method ends up being called indirectly during the object's construction, leading to a 0-pointer dereference [1] - accidentally creating two shared-pointers to the same object leading to an eventual double-free (that may just silent…
Both of your first two cases exist when people convert code bases that used raw pointers to shared_ptr. The normal intended usage of shared_ptr is to use make_shared and never have a raw pointer ever exist. The need to us shared_from this (or create a new independent shared ptr) happens only because some part of the code base is still using raw pointers for that particular class. OTOH, C++ needs the ability to suppor…
auto self = shared_from_this();
document.onclick([self](){self->doit(); } );
I'm not sure there is a way to express that in C++ without use of enable_shared_from_this.It is very easy to accidentally run this kind of code from a constructor where shared_from_this() is a 0-ptr.
make_shared also only helps in 95% of cases. E.g. it does not allow specifying a custom deleter, which is a use-case that is allowed by the shared_ptr constructor. It also won't fix any of the problems WRT shared_from_this() being called in the constructor.