Saturday, August 25, 2018

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

woodbrian77@gmail.com: Aug 25 11:08AM -0700

On Friday, August 24, 2018 at 1:31:03 AM UTC-5, Öö Tiib wrote:
> and ridiculously useful. The union was always unsafe and usage of
> raw or unique_ptr to represent little, possibly missing value was
> so sadly inefficient.
 
I think variant is kind of useful, but am not as convinced
about optional. I've considered several times using a
vector of optional rather than a vector of unique_ptr here:
https://github.com/Ebenezer-group/onwards/blob/master/src/cmw/tiers/cmwA.cc
, but optional:
increases the size of my text segment by about 2% and
results in more expensive moves than unique_ptr.
 
The benefit of optional would be to avoid the heap allocation
and deallocation. I avoid the heap in general, but in this case
think the advantages of unique_ptr are worth it, especially if
the size of my type grows over time leading to even bigger text
segments and more expensive moves.
 
I'm not a big proponent of unique_ptr, but in this case I find
it helpful.
 
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
"Öö Tiib" <ootiib@hot.ee>: Aug 25 02:29PM -0700

> , but optional:
> increases the size of my text segment by about 2% and
> results in more expensive moves than unique_ptr.
 
I can't imagine how you measured? Optional means additional bool,
when unique_ptr means additional pointer, additional indirection
and additional dynamic allocation/deallocation. The situations may
certainly vary but can't be that by that lot.
 
> segments and more expensive moves.
 
> I'm not a big proponent of unique_ptr, but in this case I find
> it helpful.
 
The unique_ptr is useful when the component is polymorphic. Optional
can't be polymorphic. It is also easy to see how unique_ptr can
provide storage performance advantage when the component is often
missing (rarely present) but how it can provide better speed
performance? Can you provide a cite or benchmark?
 
In general what is currently pricey is not memory amount, nor throughput
but it is latency. Optionals are local and that always means less cache
misses and better latency.
Richard Damon <Richard@Damon-Family.org>: Aug 24 07:31PM -0400

On 8/24/18 3:21 PM, Daniel wrote:
 
> size_t size() const;
 
> neither you (nor the compiler) can conclude anything about whether size() const is or is not mutating. Whether the data member is stored in size_t size_ or in size_t* size_ is an implementation detail that is neither here nor there. This greatly reduces the value of the const qualifier, to the point where it's merely suggestive, nothing more.
 
> Daniel
 
const member functions are simply not allowed to modify (non-mutable)
members IN the structure. Data in affiliated structures is not protected.
 
Yes, this says that 'const' is not a total concept of the 'value' of a
structure, but doesn't make it worthless, just maybe worth less than it
could be.
 
Whether the constness of the object should pass to the things it points
to is very much dependent on context. I suppose it might be useful to
have some attribute on a pointer to make the constness of the data
pointed inherit from the constness of the object the pointer is in to
allow it to be specified on a case by case basis.
Richard Damon <Richard@Damon-Family.org>: Aug 24 07:35PM -0400

On 8/24/18 10:21 AM, bitrex wrote:
> or something.
 
> Don't see any reason intrinsically it couldn't be that way other than
> there are better reasons to have it the way it is than that way.
 
The biggest reason to not be const by default is backwards
comparability. To change the default mutability of variables would break
nearly every non-const declaration (the only ones it wouldn;t break are
those that could have been const).
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 25 01:38AM +0100

On Thu, 23 Aug 2018 05:48:38 -0000 (UTC)
> Even beyond that, in the era of C++11 and newer, the constness of
> a member function should indicate that it's thread-safe to call it
> without a locking mechanism.
 
It absolutely doesn't mean that. Locking of object (instance) data is
required in a const member function if it accesses those data at a time
when a non-const member function might concurrently mutate the data in
another thread.
 
You may have got this idea from a talk given by Herb Sutter in which he
asserted that "const means thread safe". It doesn't.
 
A const member function can also mutate static data.
Juha Nieminen <nospam@thanks.invalid>: Aug 25 08:01AM

> object. That does not mean it will not be changed from another thread.
> So the promise is not that it does not change because the function has no
> control of this.
 
What being "thread-safe" means in this case is that two threads can
safely call that function without problems. It's not a guarantee that
if one thread calls *another* function of the class then *this* function
will behave properly.
 
This is in contrast with non-const member functions: Two threads cannot
safely call said function without a locking mechanism (unless the
description of the function guarantees that it's thread-safe, of course).
 
In general, from C++11 forward you should design your const member
functions in this manner. 'const' ought to be a promise that it can
be safely called from multiple threads.
Juha Nieminen <nospam@thanks.invalid>: Aug 25 08:06AM

> required in a const member function if it accesses those data at a time
> when a non-const member function might concurrently mutate the data in
> another thread.
 
Thread-safety in this case means that two threads can call *that* function
in question without problems. It does *not* refer to on thread calling
const function A, and another thread calling a non-const function B at
the same time.
 
> You may have got this idea from a talk given by Herb Sutter in which he
> asserted that "const means thread safe". It doesn't.
 
I don't usually resort to argument for authority, but in this case I'm
making an exception.
 
> A const member function can also mutate static data.
 
And it really shouldn't. That's the point.
 
(Why does nodoby understand the difference between the words "should"
and "does"? Read my original text again, which you quoted above.)
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 25 04:29PM +0100

On Sat, 25 Aug 2018 08:06:47 -0000 (UTC)
> in question without problems. It does *not* refer to on thread calling
> const function A, and another thread calling a non-const function B at
> the same time.
 
What you said was:
 
"Even beyond that, in the era of C++11 and newer, the constness of a
member function should indicate that it's thread-safe to call it
without a locking mechanism."
 
That is just plain wrong. The only way of finding that out is to
inspect the code and its documentation. It is not sufficient to
examine the signatures of the const functions to check that they are
indeed marked 'const'. You have to see if any of the data accessed by
the const function(s) can be concurrently mutated by other threads.
 
 
> And it really shouldn't. That's the point.
 
> (Why does nodoby understand the difference between the words "should"
> and "does"? Read my original text again, which you quoted above.)
 
I wasn't discussing whether a const member function _should_ be able to
mutate global and static data. My point was that according to the C++
standard it _can_, which is another reason why calling const member
functions is NOT automatically thread safe by virtue of the fact that
they are marked const.
Juha Nieminen <nospam@thanks.invalid>: Aug 25 05:47PM

> examine the signatures of the const functions to check that they are
> indeed marked 'const'. You have to see if any of the data accessed by
> the const function(s) can be concurrently mutated by other threads.
 
Do you have trouble understanding what the word "should" means?
 
The constness of a member function SHOULD indicate that it's thread-safe.
SHOULD. Not "does". As in, you ought to implement the method so that
it's thread-safe to call it, as a good programming practice.
 
What other word can I use to make it clearer?
 
> I wasn't discussing whether a const member function _should_ be able to
> mutate global and static data.
 
But I was.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 25 07:14PM +0100

On Sat, 25 Aug 2018 17:47:46 -0000 (UTC)
> SHOULD. Not "does". As in, you ought to implement the method so that
> it's thread-safe to call it, as a good programming practice.
 
> What other word can I use to make it clearer?
 
So what you are really proposing is a coding standard. You propose that
any member function which is labeled 'const' "should", in order to
comply with your standard, also be thread safe, so that if the object
concerned can be mutated concurrently in another thread, it should also
be protected by an internal mutex or similar internal synchronisation.
 
The standard library doesn't guarantee that, so I think you are onto a
loser. It would also be unnecessarily inefficient. All that the C++
standard guarantees is that a const member function can safely be
called concurrently with another thread calling that or another const
member function on the same object, provided that no non-const member
function is called concurrently on the object. Otherwise "a locking
mechanism" (your words) is required when invoking the const member
functions (and any non-const member function).
 
In order to describe a function as "thread safe" you must be able to
call it safely in one thread irrespective of what another thread is
doing. What "thread safe" means is that you do not have to provide
external synchronisation.
 
The fact is that no code that I know of complies with your coding
standard for 'const'. So it may be true that in your opinion "the
constness of a member function should indicate that it's thread-safe to
call it without a locking mechanism", in the real world the standard
library doesn't do so, so it doesn't.
"Öö Tiib" <ootiib@hot.ee>: Aug 25 12:12AM -0700

On Friday, 24 August 2018 11:04:09 UTC+3, Alf P. Steinbach wrote:
> cout << boolalpha;
> cout << noexcept( true? 0 : throw 0 ) << endl;
> }
 
That does not work because compiler does not evaluate it as
constexpr. Also constexpr casts do not exist so got to put it into
constexpr function at least.
 
That seems to work on gcc:
 
#include <iostream>
 
bool constexpr is42(int i) {return i == 42? true : throw 0;}
 
int main()
{
int a = 42;
int const b = 42;
int constexpr c = 3;
std::cout << std::boolalpha;
std::cout << "is42(a) " << noexcept(is42(a)) << "\n";
std::cout << "is42(b) " << noexcept(is42(b)) << "\n";
std::cout << "is42(c) " << noexcept(is42(c)) << "\n";
}
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: