Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

atomic with shared_ptr

49 views
Skip to first unread message

Chris M. Thomasson

unread,
Feb 12, 2020, 7:48:30 PM2/12/20
to
Can anybody else get this to compile:
_______________________
#include <iostream>
#include <memory>
#include <atomic>


struct foo
{
int m_a;
int m_b;
};


//static std::shared_ptr<foo> g_bar;
static std::atomic<std::shared_ptr<foo>> g_bar;

int main()
{
{
std::shared_ptr<foo> local = g_bar;
std::cout << local << "\n";
}

std::cout << "\n\nFin!\n";

std::cout.flush();
std::cin.get();

return 0;
}
_______________________


;^o

Ian Collins

unread,
Feb 12, 2020, 8:01:59 PM2/12/20
to
On 13/02/2020 13:48, Chris M. Thomasson wrote:
> Can anybody else get this to compile:
> _______________________
> #include <iostream>
> #include <memory>
> #include <atomic>
>
>
> struct foo
> {
> int m_a;
> int m_b;
> };
>
>
> //static std::shared_ptr<foo> g_bar;
> static std::atomic<std::shared_ptr<foo>> g_bar;

I'm not sure if any tools support this C++20 feature yet!

--
Ian

Chris Vine

unread,
Feb 12, 2020, 8:31:42 PM2/12/20
to
std::shared_ptr atomics have been available since C++11 (but not in
this form). You can lead a horse to water, but you cannot make it
drink.

Chris M. Thomasson

unread,
Feb 12, 2020, 8:42:49 PM2/12/20
to
I have never used it before! Consider it learning. Reading 20.8.2.6 from:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf


Alf P. Steinbach

unread,
Feb 13, 2020, 9:34:42 AM2/13/20
to
That's a C++20 feature.

But depending on your use case it may not be necessary. Quoting
cppreference, <url: https://en.cppreference.com/w/cpp/memory/shared_ptr
>:

“All member functions (including copy constructor and copy assignment)
can be called by multiple threads on different instances of shared_ptr
without additional synchronization even if these instances are copies
and share ownership of the same object. If multiple threads of execution
access the same shared_ptr without synchronization and any of those
accesses uses a non-const member function of shared_ptr then a data race
will occur; the shared_ptr overloads of atomic functions can be used to
prevent the data race.”

The “overloads of atomic functions” are, from the same page,


std::atomic_is_lock_free(std::shared_ptr)
std::atomic_load(std::shared_ptr)
std::atomic_load_explicit(std::shared_ptr)
std::atomic_store(std::shared_ptr)
std::atomic_store_explicit(std::shared_ptr)
std::atomic_exchange(std::shared_ptr)
std::atomic_exchange_explicit(std::shared_ptr)
std::atomic_compare_exchange_weak(std::shared_ptr)
std::atomic_compare_exchange_strong(std::shared_ptr)
std::atomic_compare_exchange_weak_explicit(std::shared_ptr)
std::atomic_compare_exchange_strong_explicit(std::shared_ptr)

- Alf

Manfred

unread,
Feb 13, 2020, 2:43:28 PM2/13/20
to
On 2/13/2020 3:34 PM, Alf P. Steinbach wrote:
> On 13.02.2020 01:48, Chris M. Thomasson wrote:
>> Can anybody else get this to compile:
>> _______________________
>> #include <iostream>
>> #include <memory>
>> #include <atomic>
>>
>>
>> struct foo
>> {
>>      int m_a;
>>      int m_b;
>> };
>>
>>
>> //static std::shared_ptr<foo> g_bar;
>> static std::atomic<std::shared_ptr<foo>> g_bar;
>>
>> int main()
>> {
>>      {
>>          std::shared_ptr<foo> local = g_bar;
>>          std::cout << local << "\n";
>>      }
>>
>>      std::cout << "\n\nFin!\n";
>>
>>      std::cout.flush();
>>      std::cin.get();
>>
>>      return 0;
>> }
>> _______________________
>>
>>
>> ;^o
>
> That's a C++20 feature.
>
> But depending on your use case it may not be necessary. Quoting
> cppreference, <url: https://en.cppreference.com/w/cpp/memory/shared_ptr
> >:

Which means it should be changed into the following, right?

_______________________
#include <iostream>
#include <memory>
#include <atomic>

struct foo
{
int m_a;
int m_b;
};

static std::shared_ptr<foo> g_bar;
// static std::atomic<std::shared_ptr<foo>> g_bar;

int main()
{
{
std::shared_ptr<foo> local = std::atomic_load(&g_bar);
std::cout << local << "\n";
}

std::cout << "\n\nFin!\n";

std::cout.flush();
std::cin.get();

return 0;
}
_______________________

>

Chris M. Thomasson

unread,
Feb 14, 2020, 2:53:53 AM2/14/20
to
Right! Well, it sure damn should. Bingo. And it complies right up. I am
going to examine this is more detail. Thanks everybody.

:^)

Chris M. Thomasson

unread,
Feb 14, 2020, 3:15:19 AM2/14/20
to
On 2/13/2020 11:43 AM, Manfred wrote:
> On 2/13/2020 3:34 PM, Alf P. Steinbach wrote:
>> On 13.02.2020 01:48, Chris M. Thomasson wrote:
>>> Can anybody else get this to compile:
[...]
> Which means it should be changed into the following, right?
[...]

Indeed. However, its funny to get the following output from:
___________________________
#include <iostream>
#include <memory>
#include <atomic>

struct foo
{
int m_a;
int m_b;
};

static std::shared_ptr<foo> g_bar;
// static std::atomic<std::shared_ptr<foo>> g_bar;

int main()
{
{
std::shared_ptr<foo> local = std::atomic_load(&g_bar);

std::cout << "local = " << local << "\n";

std::cout << "std::atomic_is_lock_free(&g_bar) = "
<< std::atomic_is_lock_free(&g_bar) << "\n";
}

return 0;
}
___________________________


On some online compilers:
___________________________
local = 0


std::atomic_is_lock_free(&g_bar) = 1
___________________________


1 is sometimes lock free wrt std::atomic_is_lock_free... I can see this
for a smart pointer. Others give 0. Well, there are ways to make it
always lock-free wrt grabbing a reference. Say, from that global g_bar.

The memory_order is nice for this as well:

std::atomic_load_explicit(&g_bar, std::memory_order_acquire);

or even:

std::shared_ptr<foo> local = std::atomic_load_explicit(&g_bar,
std::memory_order_relaxed);

It's using the C API, with is fine. It would be fun to use it with the
std::atomic<> in C++20. :^)

Chris M. Thomasson

unread,
Feb 14, 2020, 3:16:02 AM2/14/20
to
Speaking of C++20... I am existed to see:

https://en.cppreference.com/w/cpp/atomic/atomic_wait

I need to dig into it more, but it sure looks like some sort of futex,
or eventcount.

Chris M. Thomasson

unread,
Feb 14, 2020, 3:23:43 AM2/14/20
to
On 2/12/2020 4:48 PM, Chris M. Thomasson wrote:
[...]

Afaict, _if_ the following program indicates that shared_ptr is always
lock-free, then we can use it to build proxy collectors. Which can be an
interesting way to get a RCU like setup. Poor mans RCU, but very
scalable nonetheless. Great for read mostly scenarios.
__________________________
#include <iostream>
#include <memory>
#include <atomic>

struct foo
{
int m_a;
int m_b;
};

static std::shared_ptr<foo> g_bar;
// static std::atomic<std::shared_ptr<foo>> g_bar;

int main()
{
{
std::shared_ptr<foo> local = std::atomic_load(&g_bar);

std::cout << "local = " << local << "\n";

std::cout << "std::atomic_is_lock_free(&g_bar) = "
<< std::atomic_is_lock_free(&g_bar) << "\n";
}

return 0;
}
__________________________


If this gives:
__________________________
local = 0


std::atomic_is_lock_free(&g_bar) = 2
__________________________


we are in business!

Öö Tiib

unread,
Feb 14, 2020, 5:17:10 AM2/14/20
to

Chris M. Thomasson

unread,
Feb 14, 2020, 1:39:26 PM2/14/20
to
So far, I have only managed to get an output of
std::atomic_is_lock_free(&g_bar) = 1 on:

https://www.onlinegdb.com/online_c++_compiler

We need to get a return value of 2 in order to use shared_ptr to create
a lock-free proxy collector.

>
> http://coliru.stacked-crooked.com/a/ce4932794eb8edd0
> http://coliru.stacked-crooked.com/a/4d6f517ea0d1e888
>

Chris M. Thomasson

unread,
Feb 14, 2020, 1:43:45 PM2/14/20
to
On 2/14/2020 10:39 AM, Chris M. Thomasson wrote:
> On 2/14/2020 2:16 AM, Öö Tiib wrote:
>> On Friday, 14 February 2020 10:23:43 UTC+2, Chris M. Thomasson  wrote:
>>> On 2/12/2020 4:48 PM, Chris M. Thomasson wrote:
[...]
> So far, I have only managed to get an output of
> std::atomic_is_lock_free(&g_bar) = 1 on:
>
> https://www.onlinegdb.com/online_c++_compiler

I forgot to give a direct link to the code:

https://onlinegdb.com/SyU-5vV7U

[...]

James Kuyper

unread,
Feb 15, 2020, 9:12:38 AM2/15/20
to
On 2/14/20 3:15 AM, Chris M. Thomasson wrote:
...
> Speaking of C++20... I am existed to see:
^^^^^^...
> https://en.cppreference.com/w/cpp/atomic/atomic_wait

Seeing that brought you into existence? Wow! ;-)

0 new messages