c++ - 用于顺序处理的高效通用缓冲队列

标签 c++ algorithm oop compiler-optimization

我有一个生产者-消费者队列,它正在由并行程序更新。查询队列以获取各种统计信息,例如平均值或标准差或方差或当前队列内容的其他信息。对于意思是,这是代码,我使用

class BufferQueue {
    const int nMaxQueueSize_;
    int* values;
    int head, tail;
    double sum;
    ::utils::FastMutex queue_mutex;

public:

    BufferQueue(const int nMaxQueueSize) :
    nMaxQueueSize_(nMaxQueueSize) {
        head = tail = 0;
        sum = 0;
        values = new int[nMaxQueueSize_];
    }

    void enqueue(int val) {
        values[head] = val;
        if ((head + 1) % nMaxQueueSize_ == tail) {
            queue_mutex.lock();
            sum = val.value_point - values[tail].value_point;
            utils::memory_barrier();
            head = (1 + head) % nMaxQueueSize_;
            tail = (1 + tail) % nMaxQueueSize_;
            queue_mutex.unlock();
        } else {
            queue_mutex.lock();
            sum += val.value_point;
            utils::memory_barrier();
            head = (1 + head) % nMaxQueueSize_;
            queue_mutex.unlock();
        }
    }

    bool dequeue() {
        if (head != tail) {
            queue_mutex.lock();
            sum -= values[tail].value_point;
            utils::memory_barrier();
            tail = (1 + tail) % nMaxQueueSize_;
            queue_mutex.unlock();
            return true;
        } else {
            sum = 0;
            return false;
        }
    }

    MarketSpreadPoint& operator[](int i) {
        return values[ (tail + i) % nMaxQueueSize_ ];
    }

    inline int getSize() {
        return (head - tail + nMaxQueueSize_) % nMaxQueueSize_;
    }

    inline double average() {
        queue_mutex.lock();
        double result = sum / getSize();
        queue_mutex.unlock();
        return result;
    }

    ~BufferQueue() {
        delete values;
    }
};

注意:要记住的一件重要的事情是只执行一项操作。我也不想通过编写单独的实现来重复代码,例如 BufferQueueAverageBufferQueueVariance 等。我想要非常有限的代码冗余(编译器优化)。即使对每次更新的队列类型进行调节似乎也不是最优的。

    inline double average() {
        queue_mutex.lock();
        if(type_is_average){
            double result = sum / getSize();
        }else if(type_is_variance){
            /// update accordingly.
        }
        double result = sum / getSize();
        queue_mutex.unlock();
        return result;
    }

什么可以替代这个想法?

注意:在这个实现中,如果队列满了,head会自动让tail向前移动。换句话说,最旧的元素会被自动删除。

谢谢

最佳答案

所以你想将队列与统计数据分开。我看到两种可能的解决方案:

  1. 使用模板方法策略等模式来分解依赖性。
  2. 使用可以执行此操作的模板。

假设您收集的所有统计数据都可以gathered incrementally ,后者可能类似于以下内容(仅表示伪代码):

class StatisticsMean
{
private:
    int n = 0;
    double mean = 0.0;
public: 
    void addSample(int s) { ++n; mean += (s - mean) / n; }
    void removeSample(int s) { ... }
    double getStatistic() const { return mean; }
}

template <typename TStatistics>
class BufferQueue 
{
    TStatistics statistics;
    ...

    void enqueue(int val) 
    {
        ...
        statistics.addSample(val);
    }
    ...
    double getStatistic() const { return statistics.getStatistic(); }
}

模板方法为您提供全面的编译时优化。您可以使用模板方法模式实现相同的目的。这还允许您为 getter 指定不同的名称(上面示例中的 getStatistic())。

这可能看起来类似于:

class AbstractBufferQueue 
{
    virtual void addSample(int s) = 0;
    virtual void removeSample(int s) = 0;

    void enqueue(int val) 
    {
        ...
        addSample(val);
    }
}

class BufferQueueAverage : public AbstractBufferQueue
{
    int n;
    double mean;

    void addSample(int s) { ++n; mean += (s - mean) / n; }
    void removeSample(int s) { ... }
    double getAverage() const { return mean; }
}

关于c++ - 用于顺序处理的高效通用缓冲队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39271826/

相关文章:

c++ - “变量”不是类型 'pointer to member function' 的有效模板参数

c# - 基于位值启用行为

algorithm - 将事件事件节点图转换为事件节点图

c++ - 在 Windows x64 上构建 xlnt 库

java - C++ 到 Java 按位等效

c++ - AWS 上的 GLIBCXX 版本错误

打包算法的Python实现

c++ - 如何在其父类中调用子类?

python - 传递列表并将其长度设置为python中的默认参数

java - 这是某些类型的方法变量吗?