【问题标题】:How to avoid code duplication with mostly same member functions?如何避免代码重复与大多数相同的成员函数?
【发布时间】:2019-10-29 21:21:04
【问题描述】:

我已经实现了一个 Michael 和 Scott 队列(一个并发无锁队列),但我遇到了出队操作代码重复的问题。 这个问题通常不是关于队列算法本身,而是关于如何干净地实现函数的几种变体 大多具有相同的结构。 我说的例子:

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>>>>
            }
        }
    }
}

我已经计划实施各种操作来代替&lt;&lt;&lt;variant of operation here&gt;&gt;&gt;&gt; 包括逻辑,退出循环的if-else代码等,我想避免重复主 函数体。我应该如何进行?我至少使用 C++14 标准。 背景故事是 boost::lockfree::queue 过于受限并且 我想实现pop_if()compare_front()begin()这样的操作 除了&lt;&lt;&lt;variant operation here&gt;&gt;&gt; 部分之外,共享相同的基本出队操作代码逻辑。

【问题讨论】:

  • 将通用代码移入函数中?
  • 将重复的逻辑写在一个辅助函数中,你可以像 get_next() 一样调用它。然后,您的每个 API 函数都可以调用辅助函数。让辅助函数返回 next_ptr
  • 这里的问题是变体代码非常依赖基代码局部变量head,head_ptr,tail,next,next_ptr等。代码变体是取决于所有这些。我能想到的最好的办法是将所有局部变量放在一个结构中(从主容器类派生以允许访问成员变量)并将基本代码作为成员函数放在那里。然后大多数派生类将定义更多专门的操作,这些操作在 locals?
  • 是什么决定了您要使用哪种变体?队列中的对象类型还是其他?描述两种不同的变体(最好在代码中)。
  • @Ted Lyngmo 函数变体只是容器的区成员函数。 (即容器 API)。这是一个静态的决定,我只是在考虑如何以最少的代码重复来实现不同的功能。

标签: c++ templates code-duplication


【解决方案1】:

如果我理解正确,您可以创建一个带参数的泛型方法——仿函数

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

....

func(next_ptr->data)

}

然后 impelement 方法使用不同的函子来处理数据。

【讨论】:

  • 问题nro.1:我如何允许func 的结果继续循环或从dequeue_generic 返回?编号2:如何在func内访问容器的成员变量?
  • 对于 1,您可以从函子返回 bool 结果以允许或中断循环。对于 2 - 不要这样做。这是一个糟糕的方法。
猜你喜欢
  • 2012-01-28
  • 2019-02-26
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多