Tuesday, February 2, 2021

Digest for comp.lang.c++@googlegroups.com - 9 updates in 4 topics

Juha Nieminen <nospam@thanks.invalid>: Feb 02 09:10PM

> different programs, for instance by using generic identifiers.
> I quickly dropped all of those bad habits as soon as I got a chance to
> use a computer where programs were stored as editable files.
 
If I'm not mistaken some of the first C compilers ever created had
really small limits to things like variable and function name length,
which might have been something as short as 8 characters, and may
explain much of why so many names in POSIX are so short.
 
Of course this is the 70's we are talking about. Not much reason to
use such short names in the 2020's.
"Öö Tiib" <ootiib@hot.ee>: Feb 01 03:28PM -0800

On Tuesday, 2 February 2021 at 00:01:34 UTC+2, Chris M. Thomasson wrote:
 
> Imvho, intrusive reference counts are very useful. They can remove the
> need to create an external object to hold the count and a pointer to the
> object it protects.
 
Indeed those are very useful. Also most popular usage of shared_ptr involves
make_shared that technically binds the control block and managed
object into single object anyway. That does not provide all the benefits
of intrusive ref-counting but some. Still to my knowledge standard
library does not have it and the boost::intrusive_ptr has couple
shortcomings (that Marcel Mueller perhaps was trying to fix?).
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Feb 01 08:39PM -0800

On 2/1/2021 3:28 PM, Öö Tiib wrote:
> make_shared that technically binds the control block and managed
> object into single object anyway. That does not provide all the benefits
> of intrusive ref-counting but some.
 
I need to study up on shared_ptr. Back when I was looking into it, was a
long time ago talking with:
 
https://www.boost.org/users/people/peter_dimov.html
 
To be quite honest, I never really used them for real work. When I had
to reference count something with basic thread safety, I would just
stick a reference counter directly into the object itself. For a lot of
cases, it would work fine. Say:
 
struct object
{
// contents
};
 
would become:
 
struct object
{
std::atomic<unsigned long> m_ref; // aligned and padded
// contents
};
 
 
> Still to my knowledge standard
> library does not have it and the boost::intrusive_ptr has couple
> shortcomings (that Marcel Mueller perhaps was trying to fix?).
 
Would love to see Marcel's intrusive counter that has strong thread
safety. Actually, think I already have, but cannot remember it at all.
If he can find his old code, well, I would be happy to port it into a
Relacy test unit. If there are any issues, I am sure they can be rather
easily cleaned right up. :^)
Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo>: Feb 02 12:51AM -0500

Chris M. Thomasson wrote:
 
> To be quite honest, I never really used them for real work. When I had to
> reference count something with basic thread safety, I would just stick a
> reference counter directly into the object itself.
 
ditto. Even better, I now prefer explicit life time management to shared ptrs
and single-threaded processes to threads. A feeling grew in me for decades that
threads and shared ptrs are dirty hacks, indicate lack design and slow down my
servers. Don't need'em stinky threads; not on Linux anyway. :-)
 
Anybody believes I am serious and do not intend to start any flames?
 
-Pavel
 
For a lot of cases, it would
Marcel Mueller <news.5.maazl@spamgourmet.org>: Feb 02 08:02PM +0100

Am 01.02.21 um 23:00 schrieb Chris M. Thomasson:
> Yeah. I think your right. Well, it might be nice for C++ to perhaps
> create a new smart pointer based on Joe's atomic_ptr. But, then they
> would get into the realm of possibly violating some patents... Humm...
 
Hmm, indeed, patents might be a show stopper here.
 
>> compilers already support this feature at all. :-/
 
> iirc, Peter Dimov tried really hard to get shared_ptr to support strong
> thread safety, but failed to do so.
 
With modifications to the shared_ptr class this should be straight forward.
- The atomic shared pointer implementation needs to be a friend to
access the internal structures.
- AFAIR some care needs to be taken when a reference is freed because
the ref counter could become negative for a short time due to threading
issues.
 
 
>> significant difference.
 
> I think I remember you way back on comp.programming.threads. Do you have
> any code remaining for your intrusive algorihtm?
 
The code is still online and under a BSD like license. But it is also
still designed for IBM VisualAge C++ 3 from the 90s, not even supporting
C++03.
 
https://github.com/maazl/pm123/blob/master/src/utils/cpp/smartptr.h
 
I have same newer implementations too, but not public.
 
> It would be fun to code
> it up in Relacy to check for any possible issues, if any.
 
The code needs to be rewritten to fit modern C++ standards firstly.
Secondly it uses the stolen bits hack, so it does not depend on double
word CAS. This was perfectly valid on the target platform and passed any
tests hacking on the same shared instance with several dozens of threads.
 
With generic C++ the stolen bits hack is critical although it performs
even better on 64 bit because you can safely use 3 bits. I am unsure if
it can be implemented without introducing UB - although it is likely to
work on any real hardware.
 
> It seems that
> C++ does not have std::intrusive_ptr. Iirc, it was in boost. I might be
> missing something.
 
You are absolutely right. In fact I always used my own smart pointers in
projects. I even did not use the boost implementation of intrusive_ptr
either. So I accidentally assumed that intrusive pointers made it into
the standard.
 
I mostly needed strong thread safety and, well, intrusive reference
counting is by far more efficient. And the helper functions of
boost::intrusive_ptr prevented strong thread safety. A reference counter
need to be exposed as atomic<some_integer> somehow for strong thread safety.
 
 
 
> Damn. Iirc, this is akin to what Peter was mentioning way back. Existing
> shared_ptr needs to be modified at the implementation level without
> breaking any existing use case.
 
Exactly.
 
> create a new smart pointer that has strong thread safety... If you do
> not need strong thread safety, use shared_ptr. If you do, use
> atomic_ptr. Sound Kosher?
 
No, I don't think so.
 
Only a new type for strongly thread safe instances is needed. This type
should smoothly integrate with shared_ptr. atomic<shared_ptr> might
become this type.
 
It is very important, that the overhead for strong thread safety does
not apply to all local instances and that object storage can be shared
between normal and shared instances.
 
And some operation cannot be implemented in a lock free manner at all.
E.g. swapping two shared instances atomically is not possible. It would
require transactional memory.
 
 
> Have you taken a look at my experimental proxy collector code?
 
No, I do not even know what code you refer here.
 
> don't think it can be used to make shared_ptr strongly thread safe.
> Well, perhaps it can, but it would have to be an internal mutation of an
> existing implementation f shared_ptr. Oh well...
 
Indeed.
 
 
Marcel
"Öö Tiib" <ootiib@hot.ee>: Feb 02 11:13AM -0800

On Tuesday, 2 February 2021 at 06:39:49 UTC+2, Chris M. Thomasson wrote:
> to reference count something with basic thread safety, I would just
> stick a reference counter directly into the object itself. For a lot of
> cases, it would work fine.
 
Yes. Benefit of shared_ptr is not shared ownership but weak
horizontal references. With active objects it works kind of like real
life: X requested something from Y giving its own weak_ptr but died
soon after that. Y produced what was requested saw that X is gone
and threw the product away. No problems.
 
The concept is quite handy as same with intrusive pointers
takes to manually implement some kind of "shut down" state
and then to check and handle it explicitly.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Feb 02 12:58PM -0800

On 2/2/2021 11:02 AM, Marcel Mueller wrote:
>> create a new smart pointer based on Joe's atomic_ptr. But, then they
>> would get into the realm of possibly violating some patents... Humm...
 
> Hmm, indeed, patents might be a show stopper here.
 
Shit.
 
 
> still designed for IBM VisualAge C++ 3 from the 90s, not even supporting
> C++03.
 
> https://github.com/maazl/pm123/blob/master/src/utils/cpp/smartptr.h
 
Oh that's great. Will study up on it for sure. Thanks for the link
Marcel. Its been a while since I used the stolen bits hack: They can do
some magical things, indeed... ;^)
 
 
> Secondly it uses the stolen bits hack, so it does not depend on double
> word CAS. This was perfectly valid on the target platform and passed any
> tests hacking on the same shared instance with several dozens of threads.
 
Okay, nice. Humm... Iirc, I think Relacy might have some issues
simulating the stolen bits. Need to dig back into it. For me personally,
running the code through a race detector is always fun. I probably just
have to talk to Dmitry Vyukov. Its been a while since we discussed
Relacy. I have found some issues with it over the years, and he promptly
corrected them. He is working on the Go language, and ThreadSanitizer.
Iirc, ThreadSanitizer uses a lot of Relacy concepts. Also, I think he is
working on TensorFlow as well.
 
 
> even better on 64 bit because you can safely use 3 bits. I am unsure if
> it can be implemented without introducing UB - although it is likely to
> work on any real hardware.
 
Yeah... It probably does have a UB issue. However, like you said, its
going to work on a vast majority of hardware.
 
 
> boost::intrusive_ptr prevented strong thread safety. A reference counter
> need to be exposed as atomic<some_integer> somehow for strong thread
> safety.
 
Thanks for that info wrt boost::intrusive_ptr. I vaguely remember way
back on comp.programming.threads where somebody was trying to convince
me that strong thread safety is hardly ever needed. Iirc, my response
was that its not needed, until it is needed. ;^)
 
 
 
> Only a new type for strongly thread safe instances is needed. This type
> should smoothly integrate with shared_ptr. atomic<shared_ptr> might
> become this type.
 
Ahhhh. Agreed. It sure seems to be the prime candidate.
atomic<shared_ptr> would be, or sure seems to be, the perfect place for it.
 
 
> It is very important, that the overhead for strong thread safety does
> not apply to all local instances and that object storage can be shared
> between normal and shared instances.
 
Big time! The separation of the use cases is essential. Joe did that
with atomic_ptr and local_ptr.
 
 
> require transactional memory.
 
>> Have you taken a look at my experimental proxy collector code?
 
> No, I do not even know what code you refer here.
 
Ahhh, okay. Well here is a link to a crude C++ port. When you get some
free time to kill, can you give it a go?
 
C++11 version:
 
https://pastebin.com/raw/p1E9WN5i
 
Read this thread for context:
 
https://groups.google.com/g/comp.lang.c++/c/KwreljoeJ0k/m/KdQVJocuCQAJ
 
(oh shit! a google group link... The google might ban comp.lang.c++
next... shit)
 
It has some issues I need to clean up with negating unsigned. Just need
to get on that and get rid of some nasty casts. Fwiw, here is the
original thread where I posted it into the wild in the form of a Relacy
test unit:
 
https://groups.google.com/g/lock-free/c/X3fuuXknQF0/m/0VF_u-7shrsJ?pli=1
 
The Relacy Test Unit code:
 
https://pastebin.com/raw/f71480694
 
Passes all tests.
 
 
>> safe. Well, perhaps it can, but it would have to be an internal
>> mutation of an existing implementation f shared_ptr. Oh well...
 
> Indeed.
 
Yeah, agreed. In closing, I will deeply read your code! Thanks again.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 29 02:40PM -0800

On 1/29/2021 2:25 PM, Mr Flibble wrote:
 
>> Better integrate/wrap some existing engine like SQLite In-
>> Memory.
 
> No. I am making my own.
 
Nice! Is this multi-process? If so, how are you dealing with process
failures in the middle of a db transaction?
Ian Collins <ian-news@hotmail.com>: Jan 30 11:31AM +1300

On 30/01/2021 11:16, Scott Lurndal wrote:
 
> We generally extract the text/data/rodata portions of the codefile into a flat
> image for storage in flash, sometimes it is compressed for really small
> non-volatile storage devices.
 
Even on embedded Linux targets such as outs, there are hard limits to
FLASH segments for things like squashfs images. I have wasted/spent
much time fiddling with speed and performance optimisations to get
things to be fit and meet performance targets!
 
--
Ian
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: