Wednesday, October 16, 2019

Digest for comp.lang.c++@googlegroups.com - 10 updates in 3 topics

Jorgen Grahn <grahn+nntp@snipabacken.se>: Oct 16 07:02PM

On Wed, 2019-10-16, Öö Tiib wrote:
 
>> Bad input data isn't a logic error.
 
> The logic_error means that the error is because of possibly
> preventable logical inconsistency in input.
 
No; as I understand it it means faulty program logic, i.e. a
detectable bug, same as what the assert() macro is supposed to
be used for.
 
So since std::out_of_range is a std::logic_error, I guess you're not
supposed to use array::at() "speculatively".
 
Possibly I missed some context.
 
[snip]
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Ian Collins <ian-news@hotmail.com>: Oct 17 08:15AM +1300

On 16/10/2019 21:16, David Brown wrote:
> indirect references (via unique_ptr, for example), simply to ensure
> cleanup in case functions throw an exception. That will make the code
> safe and correct - but can be of significant readability cost.
 
The same set of conditions also apply to code that uses early returns.
Throwing an exception is just a special case of an early return.
 
> as "this function could throw anything, or pass on any exception" rather
> than the more sensible "this function won't throw - it will do what it
> says it will do".
 
This is true, but we are already there when we use the standard library
unless we build with exceptions disabled.
 
--
Ian.
David Brown <david.brown@hesbynett.no>: Oct 16 11:00PM +0200

On 16/10/2019 21:15, Ian Collins wrote:
>> safe and correct - but can be of significant readability cost.
 
> The same set of conditions also apply to code that uses early returns.
> Throwing an exception is just a special case of an early return.
 
There are two big differences. One is that with an early return,
everything is clear in the code - you know /exactly/ when the return
happens, without having to consider whether functions may or may not
throw. The second is that you have control of the return - you can
choose if it is early, or if other things are done first.
 
>> says it will do".
 
> This is true, but we are already there when we use the standard library
> unless we build with exceptions disabled.
 
Correct me if I am wrong, but for the most part the only exception that
will be thrown by the standard library is for failed memory allocations.
On many platforms, it is highly unlikely ever to happen - and for many
programs, the situation is so unexpected and critical that a dead crash
and error message is probably an acceptable way to handle it.
Ian Collins <ian-news@hotmail.com>: Oct 17 10:36AM +1300

On 17/10/2019 10:00, David Brown wrote:
> happens, without having to consider whether functions may or may not
> throw. The second is that you have control of the return - you can
> choose if it is early, or if other things are done first.
 
I was mainly responding to more of the "This can mean making more RAII
classes" section. Once you have early returns, objects instantiated in a
function have to be, for lack of a better term, self managing. This is
what applies equally to code with early returns and throws. Early
return safe and exception safe are pretty much synonymous.
 
>> unless we build with exceptions disabled.
 
> Correct me if I am wrong, but for the most part the only exception that
> will be thrown by the standard library is for failed memory allocations.
 
That is true, but even innocuous operations such as insertions can throw
if a constructor of the type being inserted throws. That's why I said
we have to build (every component of an application) with exceptions
disabled to truly grantee something won't throw.
 
--
Ian
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 16 02:43PM -0700

On 10/15/2019 3:54 AM, Paavo Helde wrote:
>> the closest
 
> A buffer overrun should be considered a bug in the program and should be
> dealt with by abort() or similar, not by an exception.
 
Fwiw, I remember creating a plug in system where a user defined program
could crash. The watchdog process detected this, and tried to recover,
restart or label as dead. An interesting method to do this is via robust
mutexes.
 
 
 
 
 
 
If an exception
"Öö Tiib" <ootiib@hot.ee>: Oct 16 03:22PM -0700

On Wednesday, 16 October 2019 22:02:46 UTC+3, Jorgen Grahn wrote:
 
> No; as I understand it it means faulty program logic, i.e. a
> detectable bug, same as what the assert() macro is supposed to
> be used for.
 
"The class logic_error defines the type of objects thrown as
exceptions to report errors presumably detectable before the
program executes, such as violations of logical preconditions
or class invariants."
Seems they assume that something can detect coherency of all
input data before program is ran.
 
> So since std::out_of_range is a std::logic_error, I guess you're not
> supposed to use array::at() "speculatively".
 
> Possibly I missed some context.
 
No, you snipped it. ;) You wanted to see only first sentence and
not to read the context. See:
 
> [snip]
 
"But how can std::stoi() know that the out of range or illegal
input is coming from corrupt input data? Also for preventing
the inconsistency its caller has possibly to do most of what
stoi does itself."
 
The std::out_of_range and std::invalid_argument are other
std::logic_errors that std::vector does not throw but
std::stoi throws. And indeed these are guarding logical
preconditions that the text in the string is really number
and that it does fit into int. However converting strings
whose contents I know before program run into ints run-time
using std::stoi feels even worse logic error. I can instead
write those ints directly into code.
Keith Thompson <kst-u@mib.org>: Oct 16 03:34PM -0700

>> One thing I really can't stand is the way C used to share a single
>> variable (errno) to store status, that may be overwritten unpredictably
 
> It's not a single variable, it's a single variable per thread.
 
Right. The standard says errno is a macro "which expands to a
modifiable lvalue that has type int and thread local storage duration,
the value of which is set to a positive error number by several library
functions".
 
On my system, the errno macro expands to
(*__errno_location ())
where the __errno_location function presumably returns a pointer to a
thread-local int object.
 
This was introduced in C11. In C90 and C99, thread local storage did
not exist, but implementations could do something equivalent.
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 16 02:49PM -0700

On 10/13/2019 11:27 PM, Chris M. Thomasson wrote:
>>> guarantee of an actual race condition.
 
> Well, if the simulation was using a single thread, then there is no race
> condition wrt the foobare'd impl of fetch-and-add.
 
As soon as multiple threads are involved, one must assume a race
condition wrt the standard. Even if the implementation has some strange
thread scheduler that keeps things in order.
 
 
 
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 16 02:54PM -0700

On 10/16/2019 2:49 PM, Chris M. Thomasson wrote:
>> race condition wrt the foobare'd impl of fetch-and-add.
 
> As soon as multiple threads are involved, one must assume a race
> condition wrt the standard.
 
Well, to clarify, not with the standard, but with the correct impl of an
atomic fetch-and-add. My code as is, has no racers wrt the std in any
conceivable scenario. Now, there can be special host systems that
schedule threads in a way where things can appear to work wrt the
fetch-and-add. The freedom of C++! :^)
 
Imvho, one must assume out-of-order counts in my busted fetch-and-add
when using more than one thread in pure standard C++.
 
 
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Oct 16 02:16PM -0700

On 10/16/2019 6:40 AM, Bonita Montero wrote:
>> https://groups.google.com/d/msg/comp.arch/8Y0C8zGjtqI/bwg-hBLRAQAJ
 
> A lock-free stack is the simplest kind of lock-free algorithm.
 
Humm... Actually mutating a counter with fetch-and-add is very simple.
Vs locking and unlocking a mutex to perform the same mutation. The lock
free LIFO is way more complex. Its not the simplest. Btw, do you take
membars into account? Updating the counter can be a single liner and use
relaxed memory order. Simple. Going for LIFO, well, you need to get the
membars right wrt push and pop. Unless you are using some really exotic
methods. Epoch periods and such.
 
 
 
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: