, shared_ptr s.
, ( shared_ptr, , ) shared_ptr, , shared_ptr .
, shared_ptr , , shared_ptr, - -const, next.
( ) - libstd++ shared_ptr:
shared_ptr(const shared_ptr& rhs)
: m_ptr(rhs.m_ptr),
m_refcount(rhs.m_refcount)
{ }
m_ptr , m_refcount - , , m_ptr.
, : , , . auto curr = head->next List::contains. , curr.m_ptr, , .
head. ref-count head->next - 1 ( , ref-count head->next 1), , node, .
. curr, m_ptr , 2 , node. key > curr->key 1 .
std:: atomic_load std:: atomic_store
std::atomic_load std::atomic_store copy-constructor/copy-assign-operator shared_ptr, . shared_ptr, , std::atomic_load/std::atomic_store . , m_ptr, , shared_ptr.
- List :
bool validate(Node const& pred, Node const& curr) {
return !(pred.marked) && !(curr.marked) &&
(std::atomic_load(&pred.next).get() == &curr);
}
bool add(int key) {
while (true) {
auto pred = std::atomic_load(&head);
auto curr = std::atomic_load(&pred->next);
while (key > (curr->key)) {
pred = std::move(curr);
curr = std::atomic_load(&pred->next);
}
std::scoped_lock lock{pred->nodeLock, curr->nodeLock};
if (validate(*pred, *curr)) {
if (curr->key == key) {
return false;
} else {
auto new_node = std::make_shared<Node>(key);
new_node->next = std::move(curr);
std::atomic_store(&pred->next, std::move(new_node));
return true;
}
}
}
}
bool remove(int key) {
while (true) {
auto pred = std::atomic_load(&head);
auto curr = std::atomic_load(&pred->next);
while (key > (curr->key)) {
pred = std::move(curr);
curr = std::atomic_load(&pred->next);
}
std::scoped_lock lock{pred->nodeLock, curr->nodeLock};
if (validate(*pred, *curr)) {
if (curr->key != key) {
return false;
} else {
curr->marked = true;
std::atomic_store(&pred->next, std::atomic_load(&curr->next));
return true;
}
}
}
}
bool contains(int key) {
auto curr = std::atomic_load(&head->next);
while (key > (curr->key)) {
curr = std::atomic_load(&curr->next);
}
return curr->key == key && !curr->marked;
}
, Node::marked a std::atomic_bool.