fast path for normal demons

This commit is contained in:
lperron@google.com
2012-09-10 08:37:41 +00:00
parent 687e049204
commit 8885a7ecb8
3 changed files with 104 additions and 19 deletions

View File

@@ -260,6 +260,22 @@ class Queue {
}
}
void ProcessNormalDemon(Demon* const demon) {
if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % 10000 == 0) {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
}
void ProcessInstrumentedNormalDemon(Demon* const demon) {
solver_->GetPropagationMonitor()->BeginDemonRun(demon);
if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % 10000 == 0) {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
solver_->GetPropagationMonitor()->EndDemonRun(demon);
}
void Process() {
if (!in_process_) {
in_process_ = true;
@@ -275,7 +291,11 @@ class Queue {
void Execute(Demon* const demon) {
if (demon->stamp() < stamp_) {
if (demon->priority() == Solver::NORMAL_PRIORITY) {
ProcessOneDemon(demon);
if (!instruments_demons_) {
ProcessNormalDemon(demon);
} else {
ProcessInstrumentedNormalDemon(demon);
}
} else {
DCHECK_EQ(demon->priority(), Solver::DELAYED_PRIORITY);
demon->set_stamp(stamp_);
@@ -284,6 +304,29 @@ class Queue {
}
}
void ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
if (!instruments_demons_) {
for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
Demon* const demon = *it;
if (demon->stamp() < stamp_) {
DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY);
if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % 10000 == 0) {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
}
}
} else {
for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
Demon* const demon = *it;
if (demon->stamp() < stamp_) {
DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY);
ProcessInstrumentedNormalDemon(demon);
}
}
}
}
void EnqueueVar(Demon* const demon) {
DCHECK(demon->priority() == Solver::VAR_PRIORITY);
if (demon->stamp() < stamp_) {
@@ -1633,6 +1676,10 @@ void Solver::Execute(Demon* const d) {
queue_->Execute(d);
}
void Solver::ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
queue_->ExecuteAll(demons);
}
uint64 Solver::stamp() const {
return queue_->stamp();
}
@@ -2558,6 +2605,10 @@ string PropagationBaseObject::BaseName() const {
return "";
}
void PropagationBaseObject::ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
solver_->ExecuteAll(demons);
}
// ---------- Decision Builder ----------
string DecisionBuilder::DebugString() const {

View File

@@ -2844,6 +2844,7 @@ class Solver {
void EnqueueVar(Demon* const d);
void EnqueueDelayedDemon(Demon* const d);
void Execute(Demon* const d);
void ExecuteAll(const SimpleRevFIFO<Demon*>& demons);
void UnfreezeQueue();
void set_queue_action_on_fail(Action* a);
void set_queue_cleaner_on_fail(IntVar* const var);
@@ -3031,6 +3032,7 @@ class PropagationBaseObject : public BaseObject {
void EnqueueDelayedDemon(Demon* const d) { solver_->EnqueueDelayedDemon(d); }
void EnqueueVar(Demon* const d) { solver_->EnqueueVar(d); }
void Execute(Demon* const d) { solver_->Execute(d); }
void ExecuteAll(const SimpleRevFIFO<Demon*>& demons);
// This method sets a callback that will be called if a failure
// happens during the propagation of the queue.

View File

@@ -753,17 +753,32 @@ class DomainIntVar : public IntVar {
void CreateBits();
virtual void WhenBound(Demon* d) {
if (min_.Value() != max_.Value()) {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
if (d->priority() == Solver::DELAYED_PRIORITY) {
delayed_bound_demons_.PushIfNotTop(solver(),
solver()->RegisterDemon(d));
} else {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
}
}
}
virtual void WhenRange(Demon* d) {
if (min_.Value() != max_.Value()) {
range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
if (d->priority() == Solver::DELAYED_PRIORITY) {
delayed_range_demons_.PushIfNotTop(solver(),
solver()->RegisterDemon(d));
} else {
range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
}
}
}
virtual void WhenDomain(Demon* d) {
if (min_.Value() != max_.Value()) {
domain_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
if (d->priority() == Solver::DELAYED_PRIORITY) {
delayed_domain_demons_.PushIfNotTop(solver(),
solver()->RegisterDemon(d));
} else {
domain_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
}
}
}
@@ -952,6 +967,9 @@ class DomainIntVar : public IntVar {
SimpleRevFIFO<Demon*> bound_demons_;
SimpleRevFIFO<Demon*> range_demons_;
SimpleRevFIFO<Demon*> domain_demons_;
SimpleRevFIFO<Demon*> delayed_bound_demons_;
SimpleRevFIFO<Demon*> delayed_range_demons_;
SimpleRevFIFO<Demon*> delayed_domain_demons_;
QueueHandler handler_;
bool in_process_;
BitSet* bits_;
@@ -1801,17 +1819,26 @@ void DomainIntVar::Process() {
new_min_ = min_.Value();
new_max_ = max_.Value();
if (min_.Value() == max_.Value()) {
for (SimpleRevFIFO<Demon*>::Iterator it(&bound_demons_); it.ok(); ++it) {
Execute(*it);
ExecuteAll(bound_demons_);
for (SimpleRevFIFO<Demon*>::Iterator it(&delayed_bound_demons_);
it.ok();
++it) {
EnqueueDelayedDemon(*it);
}
}
if (min_.Value() != OldMin() || max_.Value() != OldMax()) {
for (SimpleRevFIFO<Demon*>::Iterator it(&range_demons_); it.ok(); ++it) {
Execute(*it);
ExecuteAll(range_demons_);
for (SimpleRevFIFO<Demon*>::Iterator it(&delayed_range_demons_);
it.ok();
++it) {
EnqueueDelayedDemon(*it);
}
}
for (SimpleRevFIFO<Demon*>::Iterator it(&domain_demons_); it.ok(); ++it) {
Execute(*it);
ExecuteAll(domain_demons_);
for (SimpleRevFIFO<Demon*>::Iterator it(&delayed_domain_demons_);
it.ok();
++it) {
EnqueueDelayedDemon(*it);
}
clear_queue_action_on_fail();
ClearInProcess();
@@ -1915,18 +1942,19 @@ class BooleanVar : public IntVar {
virtual void RemoveInterval(int64 l, int64 u);
virtual void WhenBound(Demon* d) {
if (value_ == kUnboundBooleanVarValue) {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
if (d->priority() == Solver::DELAYED_PRIORITY) {
delayed_bound_demons_.PushIfNotTop(solver(),
solver()->RegisterDemon(d));
} else {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
}
}
}
virtual void WhenRange(Demon* d) {
if (value_ == kUnboundBooleanVarValue) {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
}
WhenRange(d);
}
virtual void WhenDomain(Demon* d) {
if (value_ == kUnboundBooleanVarValue) {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(d));
}
WhenRange(d);
}
void Process();
void Push() {
@@ -2006,6 +2034,7 @@ class BooleanVar : public IntVar {
private:
int value_;
SimpleRevFIFO<Demon*> bound_demons_;
SimpleRevFIFO<Demon*> delayed_bound_demons_;
Handler handler_;
};
@@ -2077,8 +2106,11 @@ void BooleanVar::RemoveInterval(int64 l, int64 u) {
void BooleanVar::Process() {
DCHECK_NE(value_, kUnboundBooleanVarValue);
for (SimpleRevFIFO<Demon*>::Iterator it(&bound_demons_); it.ok(); ++it) {
Execute(*it);
ExecuteAll(bound_demons_);
for (SimpleRevFIFO<Demon*>::Iterator it(&delayed_bound_demons_);
it.ok();
++it) {
EnqueueDelayedDemon(*it);
}
}