I have a system that has a block of central shared_ptrs each of which is references by numerous weak_ptr's all over the place. However when there are no further weak_ptr's referencing the shared_ptr can be deleted. However there
seems to be no built in way in C++ to get the number of weak_ptr's referencing a shared as use_count() only counts other shared_ptr's.
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using weak+shared in the first place)?
On 01/06/2026 12:19, boltar@caprica.universe wrote:
I have a system that has a block of central shared_ptrs each of which is
references by numerous weak_ptr's all over the place. However when there are >> no further weak_ptr's referencing the shared_ptr can be deleted. However >there
seems to be no built in way in C++ to get the number of weak_ptr's
referencing a shared as use_count() only counts other shared_ptr's.
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using weak+shared in
the first place)?
The whole point of a weak pointer is that it is non-owning. It doesn't
own a share in the referenced object, and does not contribute to whether
the shared object can or cannot be deleted. The shared pointer's
control block should be deleted automatically when there are no more
shared pointers or weak pointers referring to it.
Can you give a little more detail of your setup? In particular, are
your shared pointers created with make_shared or are the shared objects
and their control blocks separate? When you talk about "shared pointers
referenced by weak_ptr's", do you mean that the weak objects are created >from the strong objects and thus reference the same shared objects and >control block (rather than referencing the shared pointers themselves)?
It is helpful if you are precise in what refers to what.
AFAIK there is no API way to get a count of the weak pointers
referencing a given control block, but I think that if you need such a >count, you are doing something odd.
On Mon, 1 Jun 2026 16:02:35 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 01/06/2026 12:19, boltar@caprica.universe wrote:
I have a system that has a block of central shared_ptrs each of which is >>> references by numerous weak_ptr's all over the place. However whenthere
there are
no further weak_ptr's referencing the shared_ptr can be deleted. However
seems to be no built in way in C++ to get the number of weak_ptr's
referencing a shared as use_count() only counts other shared_ptr's.
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using
weak+shared in
the first place)?
The whole point of a weak pointer is that it is non-owning.˙ It
doesn't own a share in the referenced object, and does not contribute
to whether the shared object can or cannot be deleted.˙ The shared
pointer's control block should be deleted automatically when there are
no more shared pointers or weak pointers referring to it.
I should have pointed out the shared pointers can also be deleted
regardless
of whether any weak pointers are pointing to it, otherwise I'd just use shared pointers everywhere.
Can you give a little more detail of your setup?˙ In particular, are
your shared pointers created with make_shared or are the shared
objects and their control blocks separate?˙ When you talk about
"shared pointers
Irrelevant AFAIK.
referenced by weak_ptr's", do you mean that the weak objects are
created from the strong objects and thus reference the same shared
objects and control block (rather than referencing the shared pointers
themselves)? It is helpful if you are precise in what refers to what.
Huh?
void myfunc(..., shared_ptri<st_object> &sp)
{
:
˙˙˙˙weak_ptr<st_object> wp = sp
:
}
etc.
AFAIK there is no API way to get a count of the weak pointers
referencing a given control block, but I think that if you need such a
count, you are doing something odd.
Not really. I need to delete an object held in a shared pointer if:
1) Its max lifetime has expired regardless of what references it.
2) If nothing else is referencing it.
Whichever comes sooner.
On 01/06/2026 17:57, boltar@caprica.universe wrote:
I should have pointed out the shared pointers can also be deleted
regardless
of whether any weak pointers are pointing to it, otherwise I'd just use
shared pointers everywhere.
Please try to be careful with the terminology - it will help people >understand your issues.
Weak pointers do not point at shared pointers.
Your managed objects will be deleted precisely when there are no shared >pointers referencing the control block that manages it. If you want to
On Mon, 1 Jun 2026 19:34:36 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 01/06/2026 17:57, boltar@caprica.universe wrote:
I should have pointed out the shared pointers can also be deleted
regardless
of whether any weak pointers are pointing to it, otherwise I'd just use
shared pointers everywhere.
Please try to be careful with the terminology - it will help people
understand your issues.
Weak pointers do not point at shared pointers.
Then what terminology would you use? Linked to? Associated with? Its just semantics.
Also their implementation is irrelevant, its the behaviour that matters and I'm quite well aware of how they behave.
tl;dr
Your managed objects will be deleted precisely when there are no
shared pointers referencing the control block that manages it.˙ If you
want to
No, really? Thanks for the heads up sherlock.
I think I can assume you don't know the answer to my question.
On 02/06/2026 10:18, boltar@caprica.universe wrote:
Then what terminology would you use? Linked to? Associated with? Its just
semantics.
I would prefer to use the standard terminology, because it makes things >clearer. "Semantics" is the meaning of the code - it is never "just >semantics", semantics are critical if you are writing code and not poetry.
No, really? Thanks for the heads up sherlock.
I think I can assume you don't know the answer to my question.
I don't know your question, because you haven't managed to express it.
wasting everyone's time. After all, I presume you have already figured
out there is no clean way to get the count of weak references in a
control block, as it is not part of the API for shared or weak pointers.
On Tue, 2 Jun 2026 10:39:05 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 02/06/2026 10:18, boltar@caprica.universe wrote:
Then what terminology would you use? Linked to? Associated with? Its
just
semantics.
I would prefer to use the standard terminology, because it makes
things clearer.˙ "Semantics" is the meaning of the code - it is never
"just semantics", semantics are critical if you are writing code and
not poetry.
So what is the standard terminology in this case?
No, really? Thanks for the heads up sherlock.
I think I can assume you don't know the answer to my question.
I don't know your question, because you haven't managed to express it.
I laid it out in bullet points in a previous post. I'm not going over it again.
wasting everyone's time.˙ After all, I presume you have already
figured out there is no clean way to get the count of weak references
in a control block, as it is not part of the API for shared or weak
pointers.
Yes, that would annoyingly appear to be the case which is a shame.
Internally
there must be a 2 way link between weak_ptr and shared_ptr otherwise how
can
the weak ptr know when the shared ptr has gone?
I don't imagine weak ptr
does
polling!
If you didn't have a shared_ptr -> weak_ptr link you'd end up with the C problem of how do you know if a non null pointer is still pointing to
valid memory therefor there must be a link therefore it should be possible
to get from a shared ptr how many weak pointers reference it.
On 02/06/2026 12:42, boltar@caprica.universe wrote:
I laid it out in bullet points in a previous post. I'm not going over it
again.
OK. If what you have written so far is all the information you are
going to give, then it is not easy to give more help. I can explain
Yes, that would annoyingly appear to be the case which is a shame.
I don't see how it would help you. The control block is automatically >destroyed when the last associated weak pointer is destroyed. It can't
be destroyed before that. And it is unrelated to the destruction of the >actual managed resource.
Internally
there must be a 2 way link between weak_ptr and shared_ptr otherwise how
can
the weak ptr know when the shared ptr has gone?
There are no direct links between the weak pointers and the shared
pointers. Each has a link to a common control block - and it is the
control block that holds the count of shared pointers (and the count of
weak pointers). The weak pointers know when there are no more shared
On Tue, 2 Jun 2026 13:32:58 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 02/06/2026 12:42, boltar@caprica.universe wrote:
I laid it out in bullet points in a previous post. I'm not going over it >>> again.
OK.˙ If what you have written so far is all the information you are
going to give, then it is not easy to give more help.˙ I can explain
Go back and read it again if its confusing you.
Yes, that would annoyingly appear to be the case which is a shame.
I don't see how it would help you.˙ The control block is automatically
destroyed when the last associated weak pointer is destroyed.˙ It
can't be destroyed before that.˙ And it is unrelated to the
destruction of the actual managed resource.
So what? Whats preventing there being a shared ptr method that looks at the control block and tells you whether any weak ptrs are referencing it? I don't
see the problem.
Internally
there must be a 2 way link between weak_ptr and shared_ptr otherwise
how can
the weak ptr know when the shared ptr has gone?
There are no direct links between the weak pointers and the shared
pointers.˙ Each has a link to a common control block - and it is the
control block that holds the count of shared pointers (and the count
of weak pointers).˙ The weak pointers know when there are no more shared
Right, so if it has a count of the weak ptrs there's no reason the C++ standard couldn't define a way to access it.
On 02/06/2026 16:52, boltar@caprica.universe wrote:
Right, so if it has a count of the weak ptrs there's no reason the C++
standard couldn't define a way to access it.
That does not follow.
Good APIs are small - they give access to the information that is needed
to use the types effectively. They do not give access to internal >information that might be held by the implementation. A different >implementation of the same API might do things differently (though I
can't think what). The methods of a type are based on presentations and >discussions of use cases - it would seem that no one saw any use-cases
for accessing a count of the weak pointers, or that the use-cases were
And since you won't say why you want this information, or describe your >actual problem, I guess you are stuck.
So what? I can provide the same info at the user level. I really have no
On Tue, 2 Jun 2026 17:14:36 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 02/06/2026 16:52, boltar@caprica.universe wrote:
Right, so if it has a count of the weak ptrs there's no reason the C++
standard couldn't define a way to access it.
That does not follow.
Yes, it does.
Good APIs are small - they give access to the information that is needed
Well I need the info and its not provided.
to use the types effectively. They do not give access to internal >>information that might be held by the implementation. A different >>implementation of the same API might do things differently (though I
So what? I can provide the same info at the user level. I really have no
idea what you're trying to argue here.
can't think what). The methods of a type are based on presentations and >>discussions of use cases - it would seem that no one saw any use-cases
for accessing a count of the weak pointers, or that the use-cases were
The C++ committees lack of judgement is a known issue.
I have a system that has a block of central shared_ptrs each of which is references by numerous weak_ptr's all over the place. However when there are no further weak_ptr's referencing the shared_ptr can be deleted. However there
seems to be no built in way in C++ to get the number of weak_ptr's referencing a shared as use_count() only counts other shared_ptr's.
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using weak+shared in the first place)?
On 6/1/2026 3:19 AM, boltar@caprica.universe wrote:
I have a system that has a block of central shared_ptrs each of which is
references by numerous weak_ptr's all over the place. However when
there are
no further weak_ptr's referencing the shared_ptr can be deleted.
However there
seems to be no built in way in C++ to get the number of weak_ptr's
referencing a shared as use_count() only counts other shared_ptr's.
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using
weak+shared in
the first place)?
I am not sure if there is a standard way to get the weak reference count directly from a shared_ptr, and that's by design, iirc. If they truly
need to track weak observer count, they may need a custom control block
or a wrapper.
You are using multiple threads, right?
Btw, have you ever heard about Joe Seighs atomic_ptr? Global and local counts using differential reference counting...
Do you know the difference between basic atomic ref counting, and strong atomic ref counting? Well, differential ref counting can handle both...
On 6/2/2026 1:24 PM, Chris M. Thomasson wrote:
Do you know the difference between basic atomic ref counting, and
strong atomic ref counting? Well, differential ref counting can handle
both...
Btw, does C++ an intrusive ref counting? No need for a control block.
boltar@caprica.universe writes:
On Tue, 2 Jun 2026 17:14:36 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 02/06/2026 16:52, boltar@caprica.universe wrote:
Right, so if it has a count of the weak ptrs there's no reason the C++ >>>> standard couldn't define a way to access it.
That does not follow.
Yes, it does.
Good APIs are small - they give access to the information that is needed
Well I need the info and its not provided.
You haven't concisely presented _why_ you need the info, particularly
since you claim to be able to track it yourself.
So what? I can provide the same info at the user level. I really have no >>idea what you're trying to argue here.
An implementation of the C++ standard library may not even keep
a count of weak references to a shared object, if it can track
The C++ committees lack of judgement is a known issue.
Is it? Note that shared_ptr came from Boost, so there were already
extant implementations by the time it was standardized in C++11.
And, just FYI, not all newsreaders make it easy to visit previously
read articles.
On 6/1/2026 3:19 AM, boltar@caprica.universe wrote:
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using weak+shared in
the first place)?
I am not sure if there is a standard way to get the weak reference count >directly from a shared_ptr, and that's by design, iirc. If they truly
need to track weak observer count, they may need a custom control block
or a wrapper.
You are using multiple threads, right?
Btw, have you ever heard about Joe Seighs atomic_ptr? Global and local >counts using differential reference counting...
On 02/06/2026 22:26, Chris M. Thomasson wrote:
On 6/2/2026 1:24 PM, Chris M. Thomasson wrote:
Do you know the difference between basic atomic ref counting, and
strong atomic ref counting? Well, differential ref counting can
handle both...
Btw, does C++ an intrusive ref counting? No need for a control block.
If you use "make_shared" to allocate and construct a new managed object,
the control block and the managed object are allocated adjacently in one allocation.˙ That is, in effect, intrusive reference counting.
On Tue, 2 Jun 2026 13:21:01 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/1/2026 3:19 AM, boltar@caprica.universe wrote:
Does anyone know of a clean way to get the weak reference count or will
I have to roll my own (which rather defeats the point of using
weak+shared in
the first place)?
I am not sure if there is a standard way to get the weak reference
count directly from a shared_ptr, and that's by design, iirc. If they
truly need to track weak observer count, they may need a custom
control block or a wrapper.
You are using multiple threads, right?
Nope, single threaded, buts that not a reason to revert to C pointers.
Btw, have you ever heard about Joe Seighs atomic_ptr? Global and local
counts using differential reference counting...
No I hadn't, thanks for the info, will google.
On 6/3/2026 1:15 AM, boltar@caprica.universe wrote:
On Tue, 2 Jun 2026 13:21:01 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/1/2026 3:19 AM, boltar@caprica.universe wrote:
Does anyone know of a clean way to get the weak reference count or will >>>> I have to roll my own (which rather defeats the point of using
weak+shared in
the first place)?
I am not sure if there is a standard way to get the weak reference
count directly from a shared_ptr, and that's by design, iirc. If they
truly need to track weak observer count, they may need a custom
control block or a wrapper.
You are using multiple threads, right?
Nope, single threaded, buts that not a reason to revert to C pointers.
Why are you using std::shared_ptr on a single threaded system? Are you planning to go multi threaded? std::unique_ptr? Would that work for your system?
Btw, have you ever heard about Joe Seighs atomic_ptr? Global and
local counts using differential reference counting...
No I hadn't, thanks for the info, will google.
No reason to use Joes atomic_ptr if you are not using multiple threads.
On 6/2/2026 11:47 PM, David Brown wrote:
On 02/06/2026 22:26, Chris M. Thomasson wrote:
On 6/2/2026 1:24 PM, Chris M. Thomasson wrote:
Do you know the difference between basic atomic ref counting, and
strong atomic ref counting? Well, differential ref counting can
handle both...
Btw, does C++ an intrusive ref counting? No need for a control block.
If you use "make_shared" to allocate and construct a new managed
object, the control block and the managed object are allocated
adjacently in one allocation.˙ That is, in effect, intrusive reference
counting.
What about having an existing object say... foo:
___________
struct per_object_ref
{
˙˙˙ std::atomic<unsigned long> m_refs;
};
struct foo
{
˙˙˙ per_object_ref m_per_object_ref;
˙˙˙ int m_bing;
};
___________
Then using CONTAINING_RECORD or the Linux equivalent container_of. There
is absolutely no need for any external control block. If you want one,
make one. Fair enough?
Even std::make_shared is only effectively intrusive in terms of a single allocation trick?the layout is an implementation detail you don't
control. Plus, you still can't get a shared_ptr from a raw this pointer without inheriting from std::enable_shared_from_this (which adds its own weak-count pointer overhead to the object layout anyway!).
And don't forget: if a std::weak_ptr outlives the object, that whole
single make_shared allocation stays pinned in memory, keeping your dead object's footprint hostage.
With container_of, it's easy, explicit, and you just use offsetof. The object actually owns its destiny, alignment, and lifetime. :^) Am I
wrong here?
Why are you using std::shared_ptr on a single threaded system? ...You can use it to have reference counting. Incrementing the
On 6/3/2026 1:15 AM, boltar@caprica.universe wrote:
On Tue, 2 Jun 2026 13:21:01 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/1/2026 3:19 AM, boltar@caprica.universe wrote:
Does anyone know of a clean way to get the weak reference count or will >>>> I have to roll my own (which rather defeats the point of using
weak+shared in
the first place)?
I am not sure if there is a standard way to get the weak reference
count directly from a shared_ptr, and that's by design, iirc. If they
truly need to track weak observer count, they may need a custom
control block or a wrapper.
You are using multiple threads, right?
Nope, single threaded, buts that not a reason to revert to C pointers.
Why are you using std::shared_ptr on a single threaded system? Are you >planning to go multi threaded? std::unique_ptr? Would that work for your >system?
Am 03.06.2026 um 23:42 schrieb Chris M. Thomasson:
Why are you using std::shared_ptr on a single threaded system? ...You can use it to have reference counting. Incrementing the
reference counter is only somewhat slower when done atomically.
On Wed, 3 Jun 2026 14:42:43 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/3/2026 1:15 AM, boltar@caprica.universe wrote:
On Tue, 2 Jun 2026 13:21:01 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/1/2026 3:19 AM, boltar@caprica.universe wrote:
Does anyone know of a clean way to get the weak reference count or
will
I have to roll my own (which rather defeats the point of using
weak+shared in
the first place)?
I am not sure if there is a standard way to get the weak reference
count directly from a shared_ptr, and that's by design, iirc. If
they truly need to track weak observer count, they may need a custom
control block or a wrapper.
You are using multiple threads, right?
Nope, single threaded, buts that not a reason to revert to C pointers.
Why are you using std::shared_ptr on a single threaded system? Are you
planning to go multi threaded? std::unique_ptr? Would that work for
your system?
Are you seriously saying there's no use case for shared pointers in a
single
threaded system? Sure, we'll just have multiple copies of raw C pointers floating around and hope everyone searches the main list in their code all the time to check the pointer is still there and valid! Genius!
As for unique_ptr - useless. I need multiple references to it and for [reasons]
the C++ committee in their wisdom decided that weak_ptr couldn't be used with
it.
On 6/4/2026 3:24 AM, boltar@caprica.universe wrote:
Are you seriously saying there's no use case for shared pointers in a
single
threaded system? Sure, we'll just have multiple copies of raw C pointers
floating around and hope everyone searches the main list in their code all >> the time to check the pointer is still there and valid! Genius!
As for unique_ptr - useless. I need multiple references to it and for
[reasons]
the C++ committee in their wisdom decided that weak_ptr couldn't be used
with
it.
Fair enough, shared ownership with weak observers is a legitimate >single-threaded use case
But you're paying for atomics you don't need... Every copy/destroy is an >atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you the
same semantics without the overhead
A simple intrusive counter using a plain integer ? no atomics, no hidden >control block, and you own the implementation so you can expose whatever >counts you need.
On 6/4/2026 2:00 AM, Bonita Montero wrote:
Am 03.06.2026 um 23:42 schrieb Chris M. Thomasson:
Why are you using std::shared_ptr on a single threaded system? ...You can use it to have reference counting. Incrementing the
reference counter is only somewhat slower when done atomically.
std::shared_ptr has some baggage. For a single threaded program, I would >never use it.
std::shared_ptr has some baggage.
For a single threaded program, I would never use it.
On Thu, 4 Jun 2026 13:31:50 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/4/2026 2:00 AM, Bonita Montero wrote:
Am 03.06.2026 um 23:42 schrieb Chris M. Thomasson:
Why are you using std::shared_ptr on a single threaded system? ...You can use it to have reference counting. Incrementing the
reference counter is only somewhat slower when done atomically.
std::shared_ptr has some baggage. For a single threaded program, I
would never use it.
So what would you use in a large program worked on by a number of people that
will all require references to the same group of objects that may be destroyed
before their section of code gets called again (ie keeping local copies of
C pointers or even an index into the main list is a no-no)?
On 05/06/2026 11:33, boltar@caprica.universe wrote:
On Thu, 4 Jun 2026 13:31:50 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/4/2026 2:00 AM, Bonita Montero wrote:
Am 03.06.2026 um 23:42 schrieb Chris M. Thomasson:
Why are you using std::shared_ptr on a single threaded system? ...You can use it to have reference counting. Incrementing the
reference counter is only somewhat slower when done atomically.
std::shared_ptr has some baggage. For a single threaded program, I
would never use it.
So what would you use in a large program worked on by a number of people
that
will all require references to the same group of objects that may be
destroyed
before their section of code gets called again (ie keeping local copies of >> C pointers or even an index into the main list is a no-no)?
If you are on x86 and the managed objects are not insignificant in size,
the overhead of shared_ptr is probably negligible. If you are targeting >other types of processor, or have smaller objects, then it might be
worth having a similar solution that does not need atomic counters (and >possibly does not need both strong and weak pointers).
On Fri, 5 Jun 2026 11:46:23 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 05/06/2026 11:33, boltar@caprica.universe wrote:
On Thu, 4 Jun 2026 13:31:50 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/4/2026 2:00 AM, Bonita Montero wrote:
Am 03.06.2026 um 23:42 schrieb Chris M. Thomasson:
Why are you using std::shared_ptr on a single threaded system? ...You can use it to have reference counting. Incrementing the
reference counter is only somewhat slower when done atomically.
std::shared_ptr has some baggage. For a single threaded program, I
would never use it.
So what would you use in a large program worked on by a number of
people that
will all require references to the same group of objects that may be
destroyed
before their section of code gets called again (ie keeping local
copies of
C pointers or even an index into the main list is a no-no)?
If you are on x86 and the managed objects are not insignificant in
size, the overhead of shared_ptr is probably negligible.˙ If you are
targeting other types of processor, or have smaller objects, then it
might be worth having a similar solution that does not need atomic
counters (and possibly does not need both strong and weak pointers).
If you're talking embedded then I wouldn't be writing this sort of server
in the first place.
If you're talking embedded then I wouldn't be writing this sort of server
in the first place.
Am 05.06.2026 um 13:00 schrieb boltar@caprica.universe:
If you're talking embedded then I wouldn't be writing this sort of server
in the first place.
If you have an embedded system that is that constrained there's not
much benefit of C++ vs. C.
On 05/06/2026 13:00, boltar@caprica.universe wrote:
If you're talking embedded then I wouldn't be writing this sort of server
in the first place.
First, I have no idea what your software is and what kind of a system it
is running on, other than what you have said - it is large,
single-threaded, has lots of developers and is using shared and weak >pointers.
Secondly, "embedded" does not necessarily mean small - the there are
lots of big embedded systems.
Thirdly, "servers" does not necessarily mean x86 - there are lots of ARM >servers.
anything you have written up to now. And if it did turn out that you
were using something other than x86 (or might do so in the future), the
overhead of sequentially consistent atomics can be a good deal higher on >many other processors, making it a relevant consideration as they are >unnecessary for single-threaded work.
But you're paying for atomics you don't need... Every copy/destroy is an atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you the
same semantics without the overhead
On 6/4/2026 11:41 PM, Chris M. Thomasson wrote:
But you're paying for atomics you don't need... Every copy/destroy is an
atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you the
same semantics without the overhead
I also used to think the same in the past. Then I ran some experiments
and when I discovered that the supposed overhead from atomic refcounter
(as compared to a non-atomic refcounter) was not even measurable, I
changed my mind.
This was on x86_64, in a multi-threaded app, but obviously all objects
were accessed only by a single thread at any given time (otherwise one
could not use non-atomic counters in the first place). YMMV.
Anyway, I'm sure if there were any mentionable benefits to be gained
from having a single-threaded shared pointer, it would be present in the
C++ standard by now.
C with classes is a viable subset of C++ that can be used in
any constrained environment (e.g. embedded with small memory)
or when developing low-level high performance code like operating
systems and hypervisors.
Am 04.06.2026 um 22:31 schrieb Chris M. Thomasson:
std::shared_ptr has some baggage.
For a single threaded program, I would never use it.
If you have a data structure where multiple object relate to
another object on the heap a shared_ptr in each object is the
most appropriate solution. The baggage is really minimal.
On Fri, 5 Jun 2026 18:27:52 +0300
Paavo Helde <eesnimi@osa.pri.ee> gabbled:
On 6/4/2026 11:41 PM, Chris M. Thomasson wrote:
But you're paying for atomics you don't need... Every copy/destroy is
an atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you
the same semantics without the overhead
I also used to think the same in the past. Then I ran some experiments
and when I discovered that the supposed overhead from atomic
refcounter (as compared to a non-atomic refcounter) was not even
measurable, I changed my mind.
This was on x86_64, in a multi-threaded app, but obviously all objects
were accessed only by a single thread at any given time (otherwise one
could not use non-atomic counters in the first place). YMMV.
Anyway, I'm sure if there were any mentionable benefits to be gained
from having a single-threaded shared pointer, it would be present in
the C++ standard by now.
There seem to be a lot of people on this group who don't seem to
understand the purpose of shared pointers. Its not to make life easier
when multi
threading.
On 6/4/2026 11:41 PM, Chris M. Thomasson wrote:
But you're paying for atomics you don't need... Every copy/destroy is
an atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you the
same semantics without the overhead
I also used to think the same in the past. Then I ran some experiments
and when I discovered that the supposed overhead from atomic refcounter
(as compared to a non-atomic refcounter) was not even measurable, I
changed my mind.
This was on x86_64, in a multi-threaded app, but obviously all objects
were accessed only by a single thread at any given time (otherwise one
could not use non-atomic counters in the first place). YMMV.
Anyway, I'm sure if there were any mentionable benefits to be gained
from having a single-threaded shared pointer, it would be present in the
C++ standard by now.
I seem to recall reading that x86's LOCK instructions take
hundreds of cycles. While some of this is probably from stronger
memory ordering guarantees, I get the impression that the
operation itself is not aggressively optimized.
On Fri, 5 Jun 2026 13:22:49 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 05/06/2026 13:00, boltar@caprica.universe wrote:
If you're talking embedded then I wouldn't be writing this sort of
server
in the first place.
First, I have no idea what your software is and what kind of a system
it is running on, other than what you have said - it is large, single-
threaded, has lots of developers and is using shared and weak pointers.
Secondly, "embedded" does not necessarily mean small - the there are
lots of big embedded systems.
Thirdly, "servers" does not necessarily mean x86 - there are lots of
ARM servers.
I'm talking about server in the software sense, not hardware. Given I'm not using emebedded assembler I couldn't care less what the CPU is.
anything you have written up to now.˙ And if it did turn out that you
were using something other than x86 (or might do so in the future), the
You do realise Macs have been using ARM for years now?
overhead of sequentially consistent atomics can be a good deal higher
on many other processors, making it a relevant consideration as they
are unnecessary for single-threaded work.
Feel free to show how to link C pointers with atomics to do pointer
reference counting because I have better things to do.
Am 05.06.2026 um 16:13 schrieb Scott Lurndal:
C with classes is a viable subset of C++ that can be used in
any constrained environment (e.g. embedded with small memory)
or when developing low-level high performance code like operating
systems and hypervisors.
When you have embedded with small memory the advantage of C++
is negligible.
On 6/5/2026 10:51 AM, Bonita Montero wrote:
Am 05.06.2026 um 16:13 schrieb Scott Lurndal:
C with classes is a viable subset of C++ that can be used in
any constrained environment (e.g. embedded with small memory)
or when developing low-level high performance code like operating
systems and hypervisors.
When you have embedded with small memory the advantage of C++
is negligible.
We can use POD, constexpr, inline functions, zero-overhead templates...
C++ has a perfectly viable low-overhead subset for constrained
environments. The baggage is opt-in.
Side note: Unnecessary atomic RMWs and memory barriers on every copy/ destroy in a single-threaded context is real overhead, not minimal.
On 6/5/2026 8:56 AM, boltar@caprica.universe wrote:
On Fri, 5 Jun 2026 18:27:52 +0300
Paavo Helde <eesnimi@osa.pri.ee> gabbled:
On 6/4/2026 11:41 PM, Chris M. Thomasson wrote:
But you're paying for atomics you don't need... Every copy/destroy is >>>> an atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you
the same semantics without the overhead
I also used to think the same in the past. Then I ran some experiments
and when I discovered that the supposed overhead from atomic
refcounter (as compared to a non-atomic refcounter) was not even
measurable, I changed my mind.
This was on x86_64, in a multi-threaded app, but obviously all objects
were accessed only by a single thread at any given time (otherwise one
could not use non-atomic counters in the first place). YMMV.
Anyway, I'm sure if there were any mentionable benefits to be gained
from having a single-threaded shared pointer, it would be present in
the C++ standard by now.
There seem to be a lot of people on this group who don't seem to
understand the purpose of shared pointers. Its not to make life easier
when multi
threading.
So, well, have you considered the non-atomic intrusive counter approach
for your use case?
On 6/5/2026 7:45 AM, boltar@caprica.universe wrote:
On Fri, 5 Jun 2026 13:22:49 +0200
Feel free to show how to link C pointers with atomics to do pointer
reference counting because I have better things to do.
wrt strong atomic reference counting, look at my post in comp.lang.c++: >'Some history wrt reference counting...'. basic atomic ref counting is >different from strong. std::shared_ptr is basic. If you are truly >single-threaded forever, the atomics are just waste, imvvho that is. But
you mentioned a server... Well, what kind of load are you expecting? Are
you thinking about scalability down the road?
On Fri, 5 Jun 2026 13:22:49 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 05/06/2026 13:00, boltar@caprica.universe wrote:
If you're talking embedded then I wouldn't be writing this sort of
server
in the first place.
First, I have no idea what your software is and what kind of a system
it is running on, other than what you have said - it is large, single-
threaded, has lots of developers and is using shared and weak pointers.
Secondly, "embedded" does not necessarily mean small - the there are
lots of big embedded systems.
Thirdly, "servers" does not necessarily mean x86 - there are lots of
ARM servers.
I'm talking about server in the software sense, not hardware.
Given I'm not
using emebedded assembler I couldn't care less what the CPU is.
anything you have written up to now.˙ And if it did turn out that you
were using something other than x86 (or might do so in the future), the
You do realise Macs have been using ARM for years now?
overhead of sequentially consistent atomics can be a good deal higher
on many other processors, making it a relevant consideration as they
are unnecessary for single-threaded work.
Feel free to show how to link C pointers with atomics to do pointer
reference counting because I have better things to do.
Bonita Montero <Bonita.Montero@gmail.com> writes:
Am 05.06.2026 um 13:00 schrieb boltar@caprica.universe:
If you're talking embedded then I wouldn't be writing this sort of server >>> in the first place.
If you have an embedded system that is that constrained there's not
much benefit of C++ vs. C.
That statement is incorrect.
C with classes is a viable subset of C++ that can be used in
any constrained environment (e.g. embedded with small memory)
or when developing low-level high performance code like operating
systems and hypervisors.
On Fri, 5 Jun 2026 13:58:07 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/5/2026 7:45 AM, boltar@caprica.universe wrote:
On Fri, 5 Jun 2026 13:22:49 +0200
Feel free to show how to link C pointers with atomics to do pointer
reference counting because I have better things to do.
wrt strong atomic reference counting, look at my post in comp.lang.c+
+: 'Some history wrt reference counting...'.˙ basic atomic ref
counting is different from strong. std::shared_ptr is basic. If you
are truly single-threaded forever, the atomics are just waste, imvvho
that is. But you mentioned a server... Well, what kind of load are you
expecting? Are you thinking about scalability down the road?
Not a huge load hence single threaded, but lots of objects.
Am 05.06.2026 um 23:00 schrieb Chris M. Thomasson:
On 6/5/2026 10:51 AM, Bonita Montero wrote:
Am 05.06.2026 um 16:13 schrieb Scott Lurndal:
C with classes is a viable subset of C++ that can be used in
any constrained environment (e.g. embedded with small memory)
or when developing low-level high performance code like operating
systems and hypervisors.
When you have embedded with small memory the advantage of C++
is negligible.
We can use POD, constexpr, inline functions, zero-overhead
templates... C++ has a perfectly viable low-overhead subset for
constrained environments. The baggage is opt-in.
A LOCK XADD is < 10 clock cycles on current CPUs.
Am 05.06.2026 um 21:53 schrieb Chris M. Thomasson:
Side note: Unnecessary atomic RMWs and memory barriers on every copy/
destroy in a single-threaded context is real overhead, not minimal.
A LOCK XADD is < 10 clock cycles on current CPUs.
On Fri, 5 Jun 2026 13:02:26 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/5/2026 8:56 AM, boltar@caprica.universe wrote:
On Fri, 5 Jun 2026 18:27:52 +0300
Paavo Helde <eesnimi@osa.pri.ee> gabbled:
On 6/4/2026 11:41 PM, Chris M. Thomasson wrote:
But you're paying for atomics you don't need... Every copy/destroy
is an atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you
the same semantics without the overhead
I also used to think the same in the past. Then I ran some
experiments and when I discovered that the supposed overhead from
atomic refcounter (as compared to a non-atomic refcounter) was not
even measurable, I changed my mind.
This was on x86_64, in a multi-threaded app, but obviously all
objects were accessed only by a single thread at any given time
(otherwise one could not use non-atomic counters in the first
place). YMMV.
Anyway, I'm sure if there were any mentionable benefits to be gained
from having a single-threaded shared pointer, it would be present in
the C++ standard by now.
There seem to be a lot of people on this group who don't seem to
understand the purpose of shared pointers. Its not to make life
easier when multi
threading.
So, well, have you considered the non-atomic intrusive counter
approach for your use case?
Provide some example code, I have better things to do than figure it out.
On 6/6/2026 3:45 AM, boltar@caprica.universe wrote:
On Fri, 5 Jun 2026 13:02:26 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/5/2026 8:56 AM, boltar@caprica.universe wrote:
On Fri, 5 Jun 2026 18:27:52 +0300
Paavo Helde <eesnimi@osa.pri.ee> gabbled:
On 6/4/2026 11:41 PM, Chris M. Thomasson wrote:
But you're paying for atomics you don't need... Every copy/destroy >>>>>> is an atomic RMW for no benefit
An intrusive reference counter with a plain integer would give you >>>>>> the same semantics without the overhead
I also used to think the same in the past. Then I ran some
experiments and when I discovered that the supposed overhead from
atomic refcounter (as compared to a non-atomic refcounter) was not
even measurable, I changed my mind.
This was on x86_64, in a multi-threaded app, but obviously all
objects were accessed only by a single thread at any given time
(otherwise one could not use non-atomic counters in the first
place). YMMV.
Anyway, I'm sure if there were any mentionable benefits to be
gained from having a single-threaded shared pointer, it would be
present in the C++ standard by now.
There seem to be a lot of people on this group who don't seem to
understand the purpose of shared pointers. Its not to make life
easier when multi
threading.
So, well, have you considered the non-atomic intrusive counter
approach for your use case?
Provide some example code, I have better things to do than figure it out.
Ask and you shall receive. Here is the actual header infrastructure I
use in my own engine for tracking resources. It includes both the lean intrusive smart pointer handle (iptr) and an asset database container template to show how handles move cleanly around a resource map.
Notice that there are zero atomic instructions, zero separate control
blocks on the heap, and perfect cache locality because the ref count
lives inside the base layout of the asset itself. Its not perfect at
all, just enough for me:
On 6/6/2026 3:45 AM, boltar@caprica.universe wrote:[...]
On Fri, 5 Jun 2026 13:02:26 -0700
Fwiw, I use it for my graphics engine. The little database allows me toProvide some example code, I have better things to do than figure it out.
Ask and you shall receive. Here is the actual header infrastructure I
use in my own engine for tracking resources. It includes both the lean intrusive smart pointer handle (iptr) and an asset database container template to show how handles move cleanly around a resource map.
Notice that there are zero atomic instructions, zero separate control
blocks on the heap, and perfect cache locality because the ref count
lives inside the base layout of the asset itself. Its not perfect at
all, just enough for me:
You are missing the point... Why use it anyway on a single threaded
system anyway? What is a LOCK XADD vs a RMW without any LOCK, or just
in code wrt a non-atomic RMW (aka, say, ++count)? If there is no second thread, there is no one to synchronize with. Paying a synchronization
tax when there is no concurrency is just bad engineering!
You are missing the point...? Why use it on a single threaded systemIf the price is small it's not bad engineering.
anyway? What is a LOCK XADD vs a RMW without any LOCK, or just in code
wrt a non-atomic RMW (++count)? If there is no second thread, there is
no one to synchronize with. Paying a synchronization tax when there is
no concurrency is just bad engineering?
On 05/06/2026 16:45, boltar@caprica.universe wrote:
I'm talking about server in the software sense, not hardware.
In the software sense, you can have "servers" on all sorts of things. I
Feel free to show how to link C pointers with atomics to do pointer
reference counting because I have better things to do.
Have you a rough idea how the shared pointers you are using now are >implemented? An implementation that does not use atomics, because
atomic accesses are unnecessary overhead on a single-threaded system,
are the same - except the reference counts are normal integer types, not >atomic types.
On 6/6/2026 3:45 AM, boltar@caprica.universe wrote:
Provide some example code, I have better things to do than figure it out.
Ask and you shall receive. Here is the actual header infrastructure I
use in my own engine for tracking resources. It includes both the lean
On Sat, 6 Jun 2026 20:59:03 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 05/06/2026 16:45, boltar@caprica.universe wrote:
I'm talking about server in the software sense, not hardware.
In the software sense, you can have "servers" on all sorts of things.˙ I
I guess it depends how you define server. I define it as something that has other programs connecting to it via sockets, pipes, whatever. Its not a daemon that just sits there doing its own thing.
Feel free to show how to link C pointers with atomics to do pointer
reference counting because I have better things to do.
Have you a rough idea how the shared pointers you are using now are
implemented?˙ An implementation that does not use atomics, because
atomic accesses are unnecessary overhead on a single-threaded system,
are the same - except the reference counts are normal integer types,
not atomic types.
Atomics are great if all you need to do is a single uninterruptable operation.
They're useless if you need to do a whole load of things in
sequence
which I suspect shared ptr has to do and in which case you'd use mutexes.
On Sat, 6 Jun 2026 13:11:52 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/6/2026 3:45 AM, boltar@caprica.universe wrote:
Provide some example code, I have better things to do than figure it
out.
Ask and you shall receive. Here is the actual header infrastructure I
use in my own engine for tracking resources. It includes both the lean
Are you seriously suggesting I should use that mess in my code in order
NOT to use heavily tested, optimised and debugged standard library class??
You're a comedian.
On 07/06/2026 16:40, boltar@caprica.universe wrote:
Atomics are great if all you need to do is a single uninterruptable
operation.
Yes. But the nice thing about single-threaded programming is that >everything is already uninterruptable, as you have nothing else that can
do any interrupting. (Well, you might use signals in your program.)
The cost of atomics on a multi-core system is that there needs to be
some kind of broadcast across cores and/or caches to make sure that
nothing else on a different core interrupts the operation. Simple loads
and stores are usually okay, but you have to be sure that during a >read-modify-write operation, nothing else is jumping in and modifying
the data at the address in the middle of the atomic operation.
Solutions vary by architecture, with many architectures supporting
several options, but they include system-wide bus locks, cache
broadcasts, compare-and-swap operations in loops, and load/store with >reservation. Some of these can be quite costly, though on x86 a simple >fetch-and-add atomic access is not bad.
Then there is the synchronisation. Processors, caches and bus
controllers re-order all sorts of things in different ways. It is
usually critical in the situations where atomics are used that other
memory accesses are ordered, or at least observable. That can mean
flushes of write buffers, discarding speculative execution or loads, and >more.
I don't think a shared pointer needs to do much more than some atomic >counting, and won't need a mutex - at least, not for the most common
On 6/7/2026 7:44 AM, boltar@caprica.universe wrote:
On Sat, 6 Jun 2026 13:11:52 -0700
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> gabbled:
On 6/6/2026 3:45 AM, boltar@caprica.universe wrote:
Provide some example code, I have better things to do than figure it
out.
Ask and you shall receive. Here is the actual header infrastructure I
use in my own engine for tracking resources. It includes both the lean
Are you seriously suggesting I should use that mess in my code in order
NOT to use heavily tested, optimised and debugged standard library class?? >>
You're a comedian.
Well, up to you! I accidentally posted some older code of mine. I made a
new post showing my iptr. Its crude, but it just happens to work for me
in my single threaded engine.
On Sun, 7 Jun 2026 20:02:59 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 07/06/2026 16:40, boltar@caprica.universe wrote:
Atomics are great if all you need to do is a single uninterruptable
operation.
Yes.˙ But the nice thing about single-threaded programming is that
everything is already uninterruptable, as you have nothing else that
can do any interrupting.˙ (Well, you might use signals in your program.)
IIRC signals can be all be caught in a single thread using sigwait() or something like that with all the other threads ignoring them so shouldn't
be an issue.
The cost of atomics on a multi-core system is that there needs to be
some kind of broadcast across cores and/or caches to make sure that
nothing else on a different core interrupts the operation.˙ Simple
loads and stores are usually okay, but you have to be sure that during
a read-modify-write operation, nothing else is jumping in and
modifying the data at the address in the middle of the atomic
operation. Solutions vary by architecture, with many architectures
supporting several options, but they include system-wide bus locks,
cache broadcasts, compare-and-swap operations in loops, and load/store
with reservation.˙ Some of these can be quite costly, though on x86 a
simple fetch-and-add atomic access is not bad.
Then there is the synchronisation.˙ Processors, caches and bus
controllers re-order all sorts of things in different ways.˙ It is
usually critical in the situations where atomics are used that other
memory accesses are ordered, or at least observable.˙ That can mean
flushes of write buffers, discarding speculative execution or loads,
and more.
I'm sure all the above is correct but its way too low level for me to worry about. My code isn't sitting in a tight CPU loop, it spends most of its
time
doing nothing waiting for client input with a once a second interrupt timer to update the objects.
I don't think a shared pointer needs to do much more than some atomic
counting, and won't need a mutex - at least, not for the most common
shared_ptr<myclass> sp2 = sp1
at the very least has to do 2 operations (after basic object memory has
been
allocated): Copy the raw pointer and update a reference count. You can't
do that with an atomic operation.
On 08/06/2026 10:16, boltar@caprica.universe wrote:
at the very least has to do 2 operations (after basic object memory has
been
allocated): Copy the raw pointer and update a reference count. You can't
do that with an atomic operation.
Only the count update has to be atomic. Remember, a "shared_ptr"
instance does not hold any of the important information, such as the >counters - it only holds a copy of a pointer to the original object, and
a pointer to the control block. And because you are coping an existing >shared pointer, the control block already exists and its counters are >definitely non-zero - these pointers can be happily copied without any
kind of locking. The only special thing is that the atomic counter in
the control block must be incremented atomically, in case (in another >thread) another shared pointer to the same object is being created or >destroyed.
On Mon, 8 Jun 2026 10:57:33 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 08/06/2026 10:16, boltar@caprica.universe wrote:
at the very least has to do 2 operations (after basic object memory
has been
allocated): Copy the raw pointer and update a reference count. You can't >>> do that with an atomic operation.
Only the count update has to be atomic.˙ Remember, a "shared_ptr"
instance does not hold any of the important information, such as the
counters - it only holds a copy of a pointer to the original object,
and a pointer to the control block.˙ And because you are coping an
existing shared pointer, the control block already exists and its
counters are definitely non-zero - these pointers can be happily
copied without any kind of locking.˙ The only special thing is that
the atomic counter in the control block must be incremented
atomically, in case (in another thread) another shared pointer to the
same object is being created or destroyed.
And thats the problem:
Thread 2:
˙˙˙˙shared_ptr<myclass> sp2 = sp1;
˙˙˙˙Allocate memory for sp2
Thread 1 interrupts:
˙˙˙˙sp1 is deleted
˙˙˙˙decrements reference counter which goes to 0 so deletes control block Thread 2 resumes:
˙˙˙˙Oops, control block has vanished!
On 08/06/2026 11:39, boltar@caprica.universe wrote:
Thread 2:block
˙˙˙˙shared_ptr<myclass> sp2 = sp1;
˙˙˙˙Allocate memory for sp2
Thread 1 interrupts:
˙˙˙˙sp1 is deleted
˙˙˙˙decrements reference counter which goes to 0 so deletes control
Thread 2 resumes:
˙˙˙˙Oops, control block has vanished!
If sp1 is deleted by one thread while another thread is reading from it
(to initialise sp2), that's a race condition and UB. It's the same as
any other uncontrolled mix of reads and writes from different threads.
But to make it possible to make such mistakes, you'd probably have to be >doing something weird such as using raw pointers to your shared_ptr<> >instances instead of using shared_ptr<> objects directly. At the very >least, you'd have to be sharing the same shared_ptr<> instance from >different threads without any control - which is exactly what you don't
do with shared_ptr<>'s.
share_ptr<> makes it very difficult to get things wrong, but it can't
stop all attempts at creative abuse.
On Mon, 8 Jun 2026 12:26:28 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 08/06/2026 11:39, boltar@caprica.universe wrote:
Thread 2:block
˙˙˙˙˙shared_ptr<myclass> sp2 = sp1;
˙˙˙˙˙Allocate memory for sp2
Thread 1 interrupts:
˙˙˙˙˙sp1 is deleted
˙˙˙˙˙decrements reference counter which goes to 0 so deletes control
Thread 2 resumes:
˙˙˙˙˙Oops, control block has vanished!
If sp1 is deleted by one thread while another thread is reading from
it (to initialise sp2), that's a race condition and UB.˙ It's the same
as any other uncontrolled mix of reads and writes from different threads.
But to make it possible to make such mistakes, you'd probably have to
be doing something weird such as using raw pointers to your
shared_ptr<> instances instead of using shared_ptr<> objects
directly.˙ At the very least, you'd have to be sharing the same
shared_ptr<> instance from different threads without any control -
which is exactly what you don't do with shared_ptr<>'s.
share_ptr<> makes it very difficult to get things wrong, but it can't
stop all attempts at creative abuse.
shared_ptr is thread safe.
On 08/06/2026 12:50, boltar@caprica.universe wrote:
On Mon, 8 Jun 2026 12:26:28 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 08/06/2026 11:39, boltar@caprica.universe wrote:
Thread 2:block
˙˙˙˙˙shared_ptr<myclass> sp2 = sp1;
˙˙˙˙˙Allocate memory for sp2
Thread 1 interrupts:
˙˙˙˙˙sp1 is deleted
˙˙˙˙˙decrements reference counter which goes to 0 so deletes control
Thread 2 resumes:
˙˙˙˙˙Oops, control block has vanished!
If sp1 is deleted by one thread while another thread is reading from
it (to initialise sp2), that's a race condition and UB.˙ It's the same
as any other uncontrolled mix of reads and writes from different threads. >>>
But to make it possible to make such mistakes, you'd probably have to
be doing something weird such as using raw pointers to your
shared_ptr<> instances instead of using shared_ptr<> objects
directly.˙ At the very least, you'd have to be sharing the same
shared_ptr<> instance from different threads without any control -
which is exactly what you don't do with shared_ptr<>'s.
share_ptr<> makes it very difficult to get things wrong, but it can't
stop all attempts at creative abuse.
shared_ptr is thread safe.
When used correctly, yes. Trying to delete sp1 from one thread while
trying to use sp1 as the source for an assignment constructor in another >thread is incorrect use, and will not be safe.
On Mon, 8 Jun 2026 13:20:33 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 08/06/2026 12:50, boltar@caprica.universe wrote:
On Mon, 8 Jun 2026 12:26:28 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 08/06/2026 11:39, boltar@caprica.universe wrote:
Thread 2:block
˙˙˙˙˙shared_ptr<myclass> sp2 = sp1;
˙˙˙˙˙Allocate memory for sp2
Thread 1 interrupts:
˙˙˙˙˙sp1 is deleted
˙˙˙˙˙decrements reference counter which goes to 0 so deletes control
Thread 2 resumes:
˙˙˙˙˙Oops, control block has vanished!
If sp1 is deleted by one thread while another thread is reading from
it (to initialise sp2), that's a race condition and UB.˙ It's the
same as any other uncontrolled mix of reads and writes from
different threads.
But to make it possible to make such mistakes, you'd probably have
to be doing something weird such as using raw pointers to your
shared_ptr<> instances instead of using shared_ptr<> objects
directly.˙ At the very least, you'd have to be sharing the same
shared_ptr<> instance from different threads without any control -
which is exactly what you don't do with shared_ptr<>'s.
share_ptr<> makes it very difficult to get things wrong, but it
can't stop all attempts at creative abuse.
shared_ptr is thread safe.
When used correctly, yes.˙ Trying to delete sp1 from one thread while
trying to use sp1 as the source for an assignment constructor in
another thread is incorrect use, and will not be safe.
Seems a bit of an oversight. Either a class is threadsafe or it isn't, there's no point doing only half of it because what happens if someone forgets?
Might as well not bother.
Am 06.06.2026 um 22:07 schrieb Chris M. Thomasson:
You are missing the point...? Why use it on a single threaded systemIf the price is small it's not bad engineering.
anyway? What is a LOCK XADD vs a RMW without any LOCK, or just in code
wrt a non-atomic RMW (++count)? If there is no second thread, there is
no one to synchronize with. Paying a synchronization tax when there is
no concurrency is just bad engineering?
On Mon, 8 Jun 2026 12:26:28 +0200
David Brown <david.brown@hesbynett.no> gabbled:
On 08/06/2026 11:39, boltar@caprica.universe wrote:
Thread 2:block
˙˙˙˙˙shared_ptr<myclass> sp2 = sp1;
˙˙˙˙˙Allocate memory for sp2
Thread 1 interrupts:
˙˙˙˙˙sp1 is deleted
˙˙˙˙˙decrements reference counter which goes to 0 so deletes control
Thread 2 resumes:
˙˙˙˙˙Oops, control block has vanished!
If sp1 is deleted by one thread while another thread is reading from
it (to initialise sp2), that's a race condition and UB.˙ It's the same
as any other uncontrolled mix of reads and writes from different threads.
But to make it possible to make such mistakes, you'd probably have to
be doing something weird such as using raw pointers to your
shared_ptr<> instances instead of using shared_ptr<> objects
directly.˙ At the very least, you'd have to be sharing the same
shared_ptr<> instance from different threads without any control -
which is exactly what you don't do with shared_ptr<>'s.
share_ptr<> makes it very difficult to get things wrong, but it can't
stop all attempts at creative abuse.
shared_ptr is thread safe.
shared_ptr<> lets you have thread-safe access to a shared control block
and to handle destruction of its shared managed object and associated storage.˙ It does not let you have thread-safe sharing of shared_ptr<> objects, because that would be silly - a shared_ptr<> instance is just
two pointers in size, and will (in sane code) usually be very local.˙ It
is thread-safe by method 4 above.
afaict, shared_ptr only provides _basic_ thread safety wrt ref counting.
Its not a _strong_ atomic ref counter! Meaning that a thread that does
not already own a reference cannot take a reference. I think C++ allows
for std::atomic<std::shared_ptr<T>>? That gives you strong refcounting
using whatever means necessary, crap impl or not. Fwiw, here is an
example of a strong reference counter:
https://patents.google.com/patent/US20060037026A1/en?oq=20060037026
Joe Seigh noticed that its basically a total rip off of his atomic_ptr
from back in the comp.programming.threads days, and even before that.
Read my post here:
"Some history wrt reference counting..."
Seems a bit of an oversight. Either a class is threadsafe or it isn't, there's no point doing only half of it because what happens if someone forgets?
| Sysop: | Tetrazocine |
|---|---|
| Location: | Melbourne, VIC, Australia |
| Users: | 13 |
| Nodes: | 8 (0 / 8) |
| Uptime: | 29:34:58 |
| Calls: | 218 |
| Files: | 21,503 |
| Messages: | 84,138 |