0

I have implemented a Michael and Scott Queue (a concurrent lockfree queue) and I have a problem with dequeue operation code duplication. This question in general is not about the queue algorithm itself but how to cleanly implement several variations of functions that mostly have identical structure. The example I say:

bool dequeue() {
    while(true) {
        // [atomically load head, tail and head->next]
        auto head = m_head.load(std::memory_order_acquire);
        auto head_ptr = head.get();
        auto tail = m_tail.load(std::memory_order_acquire);
        auto next = head_ptr->next.load(std::memory_order_acquire);
        auto next_ptr = next.get();
        // Are head, tail, and next consistent?
        if(head == m_head.load(std::memory_order_acquire)) {
            // Is queue empty or tail falling behind?
            if(head_ptr == tail.get()) {
                // Is queue empty?
                if(!next_ptr) {
                    return false;
                }
                // tail is falling behind. Try to advance it
                m_tail.compare_exchange_strong(tail, tail(next_ptr));
            } else if(next_ptr){
                // [ above check is result free list interaction, not part of orginal algo ]
                // [Read value from next_ptr->data]
                // <<<variant of operation here>>>>
            }
        }
    }
}

I have planned to implement various operations in place of <<<variant of operation here>>>> including logic, if-else code exiting the loop and such and I would like to avoid duplicating the main body of the function. How should I proceed? I'm using at least C++14 standard. The background story is that boost::lockfree::queue<> was too restricted and I would like to implement such operations as pop_if(), compare_front(), begin() that all share the same basic dequeue operation code logic except for the <<<variant operation here>>> part.

7
  • 2
    Move the common code into a function? Commented Oct 29, 2019 at 21:23
  • write the repeated logic in a helper function that you could call like get_next(). Then, each of your API functions can call the helper function. Have the helper function return the next_ptr Commented Oct 29, 2019 at 21:33
  • The problem here is that the variant code is very depend on the base code local variables head, head_ptr,tail,next,next_ptr etc. The code variants are depend on all of these. Best I could think of would be to put all local variables in a struct (derived from the main container class to allow accessing member variables) and put the base code there as member function. Then most derived class would define more specialised operations that operate on the locals? Commented Oct 29, 2019 at 22:04
  • What decides which variant you are going to use? The type of object in the queue or something else? Describe two different variants (preferably in code). Commented Oct 29, 2019 at 22:20
  • @Ted Lyngmo The function variants are just district member functions of the container. (i.e. the container API). It is a static decision, and I'm just thinking how to implement the different functions with least amount code duplication. Commented Oct 29, 2019 at 23:19

1 Answer 1

1

If I understand correctly, you can create a generic method with argument -- a functor

template <class Func>
bool dequeue_generic(Func func) {

....

func(next_ptr->data)

}

then impelement methods using different functors to do the job with the data.

Sign up to request clarification or add additional context in comments.

2 Comments

Problem nro.1 : How do I allow result of func either continue the loop or return from dequeue_generic? Nro. 2: how can I access container's member variables within func?
For 1 you may return bool result from a functor to allow or break the loop. For 2 -- don't do this. It's a bad approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.