我很难理解为什么priority_queue pop()调用没有删除top()元素。优先级队列具有自定义比较结构,因此较低的数字具有较高的优先级(因此应使用top()检索。
调试文本(如下所示)显示top()元素即使在pop()之后也保持不变。
即使我们假设比较结构有点错误,top()应该在pop()之后改变,对吧?我还能看到什么来理解为什么会这样。 priority_queue代码本身对我来说有点难以理解......
请注意,此行为不一致。还有一些时候top()在pop()之后发生了变化。
有什么想法吗?谢谢!
调试文本(使用top()前面显示的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()!!
我将()推送到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()));
}
我从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()));
}
priority_queue的定义:
typedef priority_queue<PendingPrepare, deque<PendingPrepare>, PendCompare> pendQueue;
自定义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;
}
};
PendingPrepare结构的相关部分:
struct PendingPrepare {
ClockCommand* prepare = NULL;
PrepareOK* prepareOK = NULL;
void operator=(const PrepareOK &b) {
this->prepareOK = new PrepareOK(b);
}
};
答案 0 :(得分:0)
感谢大家的帮助。实际上查看PendingPrepare内容解决了这个问题。我做了一个可怕的假设,即只有一个指针一次被实例化,当有两个实例化时,会混淆PendCompare比较类。
更好的复制构造函数删除并使其他指针为NULL以避免多个实例化解决了问题。