Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chapter 7. queue_mpmc.cpp #1

Open
Ilya21 opened this issue Feb 12, 2018 · 1 comment
Open

Chapter 7. queue_mpmc.cpp #1

Ilya21 opened this issue Feb 12, 2018 · 1 comment

Comments

@Ilya21
Copy link

Ilya21 commented Feb 12, 2018

Hello subjum. I have tried to execution your realization of lock-free queue_mpmc, but i recevied segmenation fault (core dump) in push function. Can you help me with this problem, please?

@Ilya21 Ilya21 changed the title Chapter 7. queue_mpms.cpp Chapter 7. queue_mpmc.cpp Feb 12, 2018
@LinRuiiXin
Copy link

@Ilya21

Hello subjum. I have tried to execution your realization of lock-free queue_mpmc, but i recevied segmenation fault (core dump) in push function. Can you help me with this problem, please?

I encountered the same issue, and I assume you’ve resolved it. Let me supplement the solution to this problem:

Memory Alignment Issue with counted_node_ptr Structure (May Occur in Certain Environments):
Differences in compilers might cause the compare_exchange_strong call on std::counted_node_ptr to fail, even when the expected value matches the actual value. To address this, modify the counted_node_ptr structure as follows:

struct counted_node_ptr {
    int     external_count;
    node*   ptr;
    uint8_t padding[sizeof(void*) - sizeof(int)];
};

Then modify the push function:

void push(T new_value) {
    std::unique_ptr<T> new_data(new T(new_value));
    counted_node_ptr new_next;
    new_next.ptr = new node;
    new_next.external_count = 1;
    counted_node_ptr old_tail = tail.load();
    for (;;) {
        increase_external_count(tail, old_tail);
        T* old_data = nullptr;
        if (old_tail.ptr->data.compare_exchange_strong(old_data, new_data.get())) {
            counted_node_ptr old_next = {0, nullptr, {0}};
            if (!old_tail.ptr->next.compare_exchange_strong(old_next, new_next)) { 
                delete new_next.ptr;
                new_next = old_next;
            }
            set_new_tail(old_tail, new_next);
            new_data.release();
            break;
        } else {
            counted_node_ptr old_next = {0, nullptr, {0}};
            if (old_tail.ptr->next.compare_exchange_strong(old_next, new_next)) {
                old_next = new_next;
                new_next.ptr = new node;
            }
            set_new_tail(old_tail, old_next);
        }
    }
}

Also, modify the node constructor:

node() {
    data = nullptr;
    node_counter new_count;
    new_count.internal_count = 0;
    new_count.external_counters = 2;
    count.store(new_count);
    counted_node_ptr new_next {0, nullptr, {0}};
    next.store(new_next);
}

Improper Queue Initialization:
This is the primary cause of the error. Modify the node constructor of the lock_free_queue as follows:

lock_free_queue() {
    counted_node_ptr dummy {1, new node, {0}};
    head = dummy;
    tail = dummy;
}

That’s all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants