johnmcfarlane / papers

9 stars 2 forks source link

contractual disappointment: determinism might be overreaching #52

Open the-real-neil opened 2 years ago

the-real-neil commented 2 years ago

These are some very big asks:

https://github.com/johnmcfarlane/papers/blob/cd83a70af4af3c111f8471d174ee354fe3cdce04/cpp/contractual-disappointment.md?plain=1#L428

https://github.com/johnmcfarlane/papers/blob/cd83a70af4af3c111f8471d174ee354fe3cdce04/cpp/contractual-disappointment.md?plain=1#L450

https://github.com/johnmcfarlane/papers/blob/cd83a70af4af3c111f8471d174ee354fe3cdce04/cpp/contractual-disappointment.md?plain=1#L515

https://github.com/johnmcfarlane/papers/blob/cd83a70af4af3c111f8471d174ee354fe3cdce04/cpp/contractual-disappointment.md?plain=1#L530

Even without considering the (very) necessary support required from the hardware, kernel, and OS API --- these are some very difficult subject areas to be tackled by any language. When a systems developer hears the words "safety", "critical", "determinism", and/or "real-time", she mentally tacks $1M onto the project. These are not things you get for free. What you do get --- after paying dearly for them --- is relatively slow SoC, a proprietary kernel, and a proprietary toolchain supporting C89 (or at least a decent subset thereof).

This not to say C++ folks should not be striving for what you lay out. I do admire your aspiration to tackle these issues as C++ language problems, but there is so much in the C++ language that is inimical (if not mutually exclusive) to any of the four referenced points.

Take, for example, the C++ language feature of virtual functions. These are usually implemented with a vtable whose size, composition, and performance are very much implementation-defined. How might such a vtable behave in a "hard" real-time system?

Consider dynamically-linked and dynamically-loaded libraries as practiced by most of us shipping shared objects. What kind of guarantees can you make about the behavior of an executable before certain functionality is loaded?

I'm sure there are other examples, but the gist of my argument should be clear: in a language like C++ --- one that supports relatively complicated run-time behaviors like dynamic dispatch and exception handling --- determinism is a lot more complicated.

johnmcfarlane commented 2 years ago

Thanks for the feedback. Sorry to hear that you don't think C++ is capable of determinism.

johnmcfarlane commented 2 years ago

@rubicks before I close this issue, did you have anything to say about the paper? It was about writing robust C++ programs.

Your comment seems to be about how it is clear that C++ is unsuitable for hard real-time systems which isn't really the subject of the paper, nor something that's clear to me. Are you saying that because a language has, e.g., virtual functions that that prevent programs from being deterministic? I'm at a loss to know how to respond to that. The short answer is: if they don't do what you need, don't use them.

the-real-neil commented 2 years ago

@johnmcfarlane if you can narrow the scope of this ticket to implementing robust C++ programs --- without mentioning determinism --- then the argument would seem to flow more naturally. Determinism is a tough nut to crack. While robust source code is often conducive for deterministic systems, it is not sufficient.

To be clear, I'm not arguing a deterministic program can't be implemented in C++. I am arguing that sacrificing some of C++ language features might be a necessary means to that end.

johnmcfarlane commented 2 years ago

While robust source code is often conducive for deterministic systems, it is not sufficient.

Does the article say otherwise? In fact, aside from discouraging exceptions in programs that require deterministic behaviour, the article doesn't discuss determinism at all.

I am arguing that sacrificing some of C++ language features might be a necessary means to that end.

Can you explain what you mean by sacrificing: avoiding use in a deterministic program, removing from the language entirely, or something else?

If you mean avoiding use then that is very true. You shouldn't use a feature when your implementer hasn't guaranteed its characteristics meet requirements.

If you mean removing from the language, then aside from exceptions and RTTI (which can usually be disabled), there are very few - and few slight - cases of features incurring a run-time cost beyond the cost when machine code is written by hand. Virtual functions are a very good example of that. If you don't use virtual functions, there is absolutely no run-time performance penalty that might affect deterministic behaviour. So I'm unsure why virtual functions are a problem here.

the-real-neil commented 2 years ago

Does the article say otherwise? In fact, aside from discouraging exceptions in programs that require deterministic behaviour, the article doesn't discuss determinism at all.

You're right --- and I only noticed that after successive readings. Sorry to second-guess you like that.

By "sacrifice" I mean "avoidance". And yes, you're spot-on to call out exceptions and RTTI as the most hazardous C++ features to avoid in a deterministic application. If dynamic linking was part of the C++ language, then I would add it to the same list.

Virtual functions are interesting in that the vtable behavior can be known (or at least empirically discovered) for a statically linked executable; i.e., a mainprog where every inheritor is known at link time. Dynamically linked executables are more complicated since the set of inheritors is only guaranteed to be known at image activation time; i.e., after the runtime linker finishes resolving all symbols. I'll concede that these are not C++ problems, but a relevant footnote might be nice.