有朋友熟悉 C++ 编程吗?能帮我看看这里有什么 bug 吗(更新两个 atomic)
目的是实现一个 Multiset(Non-blocking)
template <typename T>
class CMSet {
bool contains(T element);
int count(T element);
void add(T element);
bool remove(T element);
};
template <typename T> struct ANode {
T data;
std::atomic<int> count{};
std::atomic<ANode<T>*> next;
size_t key{};
ANode() : next(nullptr) {};
explicit ANode(T data) : data(data), next(nullptr) {};
explicit ANode(T data, size_t key) : data(data), key(key), next(nullptr) {
this->count.store(1);
};
};
template<typename T>
class CMSetWithNonBlocking : public CMSet<T> {
private:
atomic<ANode<T>*> head;
public:
CMSetWithNonBlocking () {
auto* h = new ANode<T>;
h->key = std::numeric_limits<size_t>::min();
auto* t = new ANode<T>;
t->key = std::numeric_limits<size_t>::max();
head.store(h);
head.load()->next.store(t);
}
bool contains(T data) {
size_t key = std::hash<T>{}(data);
ANode<T>* curr = head.load()->next.load();
while (curr->key < key) {
curr = curr->next.load();
}
return curr->key == key && curr->count.load() > 0;
}
int count(T data) {
size_t key = std::hash<T>{}(data);
ANode<T>* curr = head.load()->next.load();
while (curr->key < key) {
curr = curr->next.load();
}
if (curr->key == key) {
return curr->count.load();
}
return 0;
}
void add(T data) {
size_t key = std::hash<T>{}(data);
auto* newNode = new ANode<T>(data, key);
while (true) {
ANode<T>* prev = head.load();
ANode<T>* curr = prev->next.load();
while (curr->key < key) {
prev = curr;
curr = curr->next.load();
}
if (curr->key == key) {
// If node with key exists, increment count atomically
int oldCount = curr->count.load();
if (curr->count.compare_exchange_weak(oldCount, oldCount + 1)) {
delete newNode; // newNode not needed, delete it
return;
}
} else {
// Insert new node
newNode->next.store(curr);
if (prev->next.compare_exchange_weak(curr, newNode)) {
return; // Successfully added
}
}
}
}
bool remove(T data) {
size_t key = std::hash<T>{}(data);
while (true) {
ANode<T>* prev = head.load();
ANode<T>* curr = prev->next.load();
while (curr->key < key) {
prev = curr;
curr = curr->next.load();
}
if (curr->key == key) {
int oldCount = curr->count.load();
if (oldCount == 0) {
return false; // Node already removed or never added
}
if (curr->count.compare_exchange_weak(oldCount, oldCount - 1)) {
if (oldCount - 1 == 0) {
// If count decremented to 0, remove node
ANode<T>* next = curr->next.load();
if (!prev->next.compare_exchange_weak(curr, next)) {
continue; // CAS failed, retry
} else {
delete curr; // Node removed, delete it
}
}
return true; // Count decremented successfully
}
// If CAS fails, loop will retry
} else {
return false; // Node with key not found
}
}
}
};
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.