From answers to my previous question: Pointers in c++ after delete
從我上一個問題的答案:刪除后的c ++中的指針
it's become clear, that using the values of pointers, that point to "deleted" memory (in particular, copying them) lead to undef behaviour in c++11, and implementation-defined behaviour in c++14.
很明顯,使用指針的值,指向“刪除”的內存(特別是復制它們)會導致c ++ 11中的undef行為,以及c ++ 14中的實現定義行為。
Antomy Williams in his book "C++ concurrency in action" suggests the next lock-free stack with reference counting:
Antomy Williams在他的書“C ++並發行動”中建議使用引用計數的下一個無鎖堆棧:
#include <atomic>
#include <memory>
template<typename T>
class lock_free_stack
{
private:
struct node;
struct counted_node_ptr
{
int external_count;
node* ptr;
};
struct node
{
std::shared_ptr<T> data;
std::atomic<int> internal_count;
counted_node_ptr next;
node(T const& data_):
data(std::make_shared<T>(data_)),
internal_count(0)
{}
};
std::atomic<counted_node_ptr> head;
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter=old_counter;
++new_counter.external_count;
}
while(!head.compare_exchange_strong(
old_counter,new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
old_counter.external_count=new_counter.external_count;
}
public:
~lock_free_stack()
{
while(pop());
}
void push(T const& data)
{
counted_node_ptr new_node;
new_node.ptr=new node(data);
new_node.external_count=1;
new_node.ptr->next=head.load(std::memory_order_relaxed)
while(!head.compare_exchange_weak(
new_node.ptr->next,new_node,
std::memory_order_release,
std::memory_order_relaxed));
}
std::shared_ptr<T> pop()
{
counted_node_ptr old_head=
head.load(std::memory_order_relaxed);
for(;;)
{
increase_head_count(old_head);
node* const ptr=old_head.ptr;
if(!ptr)
{
return std::shared_ptr<T>();
}
if(head.compare_exchange_strong(
old_head,ptr->next,std::memory_order_relaxed))
{
std::shared_ptr<T> res;
res.swap(ptr->data);
int const count_increase=old_head.external_count-2;
if(ptr->internal_count.fetch_add(
count_increase,std::memory_order_release)==-count_increase)
{
delete ptr;
}
return res;
}
else if(ptr->internal_count.fetch_add(
-1,std::memory_order_relaxed)==1)
{
ptr->internal_count.load(std::memory_order_acquire);
delete ptr;
}
}
}
};
I'm worried about function
我很擔心功能
void increase_head_count(counted_node_ptr& old_counter)
{
counted_node_ptr new_counter;
do
{
new_counter=old_counter;
++new_counter.external_count;
}
while(!head.compare_exchange_strong(
old_counter,new_counter,
std::memory_order_acquire,
std::memory_order_relaxed));
old_counter.external_count=new_counter.external_count;
}
It seems, that new_counter=old_counter; can be executed, when old_counter.ptr has been deleted by another thread.
看來,new_counter = old_counter;當old_counter.ptr被另一個線程刪除時,可以執行。
So, could somebody confirm or refuse, that this stack implementation is strictly incorrect in c++11?
那么,有人可以確認或拒絕,這個堆棧實現在c ++ 11中是嚴格錯誤的嗎?
0
It is possible, but not problematic, because the compare_exchange
call will detect it and discard new_counter
.
這是可能的,但不是問題,因為compare_exchange調用將檢測它並丟棄new_counter。
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2017/05/25/72009a33b2769b39d67ec3ebf640e2d7.html。