简体   繁体   English

C ++ priority_queue pop()和top()差异

[英]C++ priority_queue pop() and top() discrepancy

I'm having a hard time understanding why a priority_queue pop() call is not removing the top() element. 我很难理解为什么priority_queue pop()调用没有删除top()元素。 The priority queue has a custom comparison structure so that lower numbers have higher priority (and therefore should be retrieved with top()). 优先级队列具有自定义比较结构,因此,较低的数字具有较高的优先级(因此应使用top()进行检索)。

The debugging text (below) shows the top() element remains the same even after a pop(). 调试文本(如下)显示,即使在pop()之后,top()元素也保持不变。

Even if we make the assumption that the comparison structure is somehow wrong, top() should change after pop(), right? 即使我们假设比较结构有某种错误,top()应该在pop()之后更改,对吗? What else can I look at to understand why this is happening. 我还能看些什么以了解为什么会这样。 The priority_queue code itself is a little inscrutable to me at the moment... 目前,priority_queue代码本身对我来说有点难以理解。

Note that this behavior is not consistent. 请注意,此行为不一致。 There are other times when top() changes after a pop(). 在其他情况下,top()在pop()之后更改。

Any ideas? 有任何想法吗? Thanks! 谢谢!

Debugging text (edited with top() shown before push(): 调试文本(在push()之前显示的top()中进行了编辑:

size BEFORE push(): 1 TOP: [1488994840.745965281:0106996627] APPENDING: [1488994840.746157190:0106996627]
size  AFTER push(): 2 TOP: [1488994840.745965281:0106996627]
size BEFORE  pop(): 2 TOP: [1488994840.745965281:0106996627]
size  AFTER  pop(): 1 TOP: [1488994840.745965281:0106996627] // <- same top()!!

Where I push() to the priority_queue: 我将()推送到priority_queue的位置:

void Replica::appendPrepareOK(const PrepareOK &prepareOK) {
    PendingPrepare tmpPrepareOK = prepareOK;

    lock_guard<mutex> lck (this->lockPendingPrepare);

    this->logprint(3, "size BEFORE push(): " + to_string(this->pendingPrepare.size()) + " APPENDING: " + to_string(tmpPrepareOK));

    this->pendingPrepare.push(tmpPrepareOK);

    this->logprint(3, "size  AFTER push(): " + to_string(this->pendingPrepare.size()) + " TOP: " + to_string(this->pendingPrepare.top()));
}

Where I pop() from the priority_queue: 我在priority_queue中弹出()的地方:

void Replica::sendPendingCmds() {
    ClockCommand *prepareCmd = NULL;
    PrepareOK *prepareOKCmd = NULL;
    Broadcast *broadcastCmd = NULL;

    {
        lock_guard<mutex> lck(this->lockPendingPrepare);

        if (! this->pendingPrepare.empty()) {
            this->logprint(3, "size BEFORE pop(): " + to_string(this->pendingPrepare.size()) + " TOP: " + to_string(this->pendingPrepare.top()));

            PendingPrepare firstCommand = this->pendingPrepare.top();
            this->pendingPrepare.pop();

            if (! this->pendingPrepare.empty()) {
                this->logprint(3, "size  AFTER pop(): " + to_string(this->pendingPrepare.size()) + " TOP: " + to_string(this->pendingPrepare.top()));
            }
            else {
                this->logprint(3, "size  AFTER pop(): " + to_string(this->pendingPrepare.size()));
            }

Definition of the priority_queue: priority_queue的定义:

typedef priority_queue<PendingPrepare, deque<PendingPrepare>, PendCompare> pendQueue;

Custom PendCompare comparison class: 自定义PendCompare比较类:

class PendCompare {
public:
    bool operator() (const PendingPrepare &a, const PendingPrepare &b) const {
        if (a.prepareOK != NULL) {
            if (b.prepareOK != NULL) { return a.prepareOK->tsOK > b.prepareOK->tsOK; }
            else if (b.prepare != NULL) { return a.prepareOK->tsOK > b.prepare->ts; }
        }
        else if (a.prepare != NULL) {
            if (b.prepareOK != NULL) { return a.prepare->ts > b.prepareOK->tsOK; }
            else if (b.prepare != NULL) { return a.prepare->ts > b.prepare->ts; }
        }

        return false;
    }
};

Relevant parts of the PendingPrepare struct: PendingPrepare结构的相关部分:

struct PendingPrepare {
    ClockCommand* prepare = NULL;
    PrepareOK* prepareOK = NULL;

    void operator=(const PrepareOK &b) {
        this->prepareOK = new PrepareOK(b);
    }
};

Thanks to everyone for your assistance. 感谢大家的协助。 Actually looking at the PendingPrepare contents solved the problem. 实际查看PendingPrepare内容可以解决此问题。 I made the terrible assumption that only one of the pointers would be instantiated at a time, when there were occasions when both were instantiated, confusing the PendCompare comparison class. 我做出了可怕的假设,即一次只有一个指针被实例化,而有时会同时实例化两个指针,这使PendCompare比较类感到困惑。

Better copy constructors that deleted and NULLed the other pointer to avoid multiple instantiations solved the problem. 更好的复制构造函数删除了另一个指针并使其为NULL,以避免多个实例化,从而解决了该问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM