Skip to content

Commit

Permalink
Much simplified and improved CO_Update merge
Browse files Browse the repository at this point in the history
  • Loading branch information
nfomon committed Sep 20, 2015
1 parent 48da633 commit 1ba09db
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 101 deletions.
2 changes: 1 addition & 1 deletion statik/Batch.cpp
Expand Up @@ -29,7 +29,7 @@ std::string Batch::BatchItem::Print() const {
s += lexical_cast<string>(node) + " " + node->Print();
}
if (pos) {
s += " @ " + pos->Print();
s += " @ " + lexical_cast<string>(pos) + " " + pos->Print();
}
return s;
}
Expand Down
118 changes: 25 additions & 93 deletions statik/IncParser.cpp
Expand Up @@ -11,6 +11,9 @@
#include "SLog.h"
#include "STree.h"

#include <boost/lexical_cast.hpp>
using boost::lexical_cast;

#include <map>
#include <memory>
#include <set>
Expand Down Expand Up @@ -370,7 +373,7 @@ void IncParser::ProcessActions() {
}

void IncParser::ComputeOutput_Update(const STree& node, Batch& out_batch, const List*& behind_node, State::Station worst_station) {
g_log.debug() << "IncParser " << m_name << ": Computing output UPDATE for node " << node;
g_log.debug() << "IncParser " << m_name << ": Computing output UPDATE for node " << node << " with behind node " << behind_node;
worst_station = std::min(node.GetState().GetStation(), worst_station);

node.GetOutputFunc() ();
Expand All @@ -391,103 +394,32 @@ void IncParser::ComputeOutput_Update(const STree& node, Batch& out_batch, const
g_log.debug() << node << " was emitting " << prev_output.size() << " items";
g_log.debug() << node << " is now emitting " << output.size() << " items";

// Linear pass through both lists, comparing elements.
OutputList::iterator item = output.begin();
OutputList::const_iterator prev_item = prev_output.begin();
while (item != output.end() && prev_item != prev_output.end()) {
if (*item == *prev_item) {
g_log.debug() << "CO_Update for " << node << " linear pass, case 1 (lists match); before call, have batch=" << out_batch;
UpdateOutput(*item, out_batch, behind_node, worst_station);
g_log.debug() << "case 1 " << node << " inner call gave us batch: " << out_batch << " at item " << *item;
behind_node = GetOEnd(*item);
++item;
++prev_item;
typedef set<OutputItem> node_set;
typedef node_set::iterator node_mod_iter;
node_set nodes(output.begin(), output.end());
for (OutputList::const_iterator prev_item = prev_output.begin();
prev_item != prev_output.end(); ++prev_item) {
node_mod_iter find_del = nodes.find(*prev_item);
if (nodes.end() == find_del) {
g_log.debug() << "Removing prev_item " << *prev_item;
RemoveOutput(*prev_item, out_batch, worst_station);
} else {
g_log.debug() << "CO_Update for " << node << " linear pass, case 2 (lists don't match)";
// Buffer both sides, and keep a lookup-set so we can identify if/when we
// find a node in one list that was surpassed in the other.
typedef set<OutputItem> node_set;
typedef node_set::const_iterator node_iter;
node_set ins_set;
node_set del_set;
OutputList::iterator ins_item = item;
OutputList::const_iterator del_item = prev_item;
while (ins_item != output.end() && del_item != prev_output.end()) {
g_log.debug() << "while";
for (node_iter i = ins_set.begin(); i != ins_set.end(); ++i) {
g_log.debug() << " ins set: " << *i;
}
g_log.debug() << "Looking for del item " << &*del_item << ": " << *del_item;
node_iter find_ins = ins_set.find(*del_item);
if (find_ins != ins_set.end()) {
// insert nodes up to find_ins
do {
g_log.debug() << "do1";
InsertOutput(*item, out_batch, behind_node, worst_station);
behind_node = GetOEnd(*item);
++item;
} while (*find_ins != *item);
// then remove the nodes up to find_ins from ins_set, and advance item to find_ins+1
// - actually, we can just nix the ins_set, since we'll break. meh
// - nope? because if we don't break and just finish the list(s(?)), we'll want to Insert/Remove the unprocessed intermediaries
ins_set.clear();
++item;
// prev_item stays where it is
// then break
break;
}
for (node_iter i = del_set.begin(); i != del_set.end(); ++i) {
g_log.debug() << " del set: " << *i;
}
g_log.debug() << "Looking for ins item " << &*ins_item << ": " << *ins_item;
node_iter find_del = del_set.find(*ins_item);
if (find_del != del_set.end()) {
do {
g_log.debug() << "do2";
RemoveOutput(*prev_item, out_batch, worst_station);
++prev_item;
} while (*find_del != *prev_item);
del_set.clear();
++prev_item;
break;
}
ins_set.insert(*ins_item);
del_set.insert(*del_item);
++ins_item;
++del_item;
g_log.debug() << "woop";
}
// grab any remaining items in the ins_set / del_set (no-break case)
for (; item != ins_item; ++item) {
g_log.debug() << "ins wow";
InsertOutput(*item, out_batch, behind_node, worst_station);
behind_node = GetOEnd(*item);
}
for (; prev_item != del_item; ++prev_item) {
g_log.debug() << "del wow";
RemoveOutput(*prev_item, out_batch, worst_station);
}
g_log.debug() << "outwhile";
if (item != output.end()) {
g_log.debug() << " have item";
} else {
g_log.debug() << " do not have item";
}
if (prev_item != prev_output.end()) {
g_log.debug() << " have prev_item";
} else {
g_log.debug() << " do not have prev_item";
}
nodes.erase(find_del);
}
}
g_log.info() << " " << node << " ok...";
for (; item != output.end(); ++item) {
InsertOutput(*item, out_batch, behind_node, worst_station);
for (OutputList::iterator item = output.begin();
item != output.end(); ++item) {
node_mod_iter find_ins = nodes.find(*item);
if (nodes.end() == find_ins) {
g_log.debug() << "Updating item " << *item << " behind node " << behind_node;
UpdateOutput(*item, out_batch, behind_node, worst_station);
} else {
nodes.erase(find_ins);
g_log.debug() << "Inserting item " << *item << " behind node " << behind_node;
InsertOutput(*item, out_batch, behind_node, worst_station);
}
behind_node = GetOEnd(*item);
}
for (; prev_item != prev_output.end(); ++prev_item) {
RemoveOutput(*prev_item, out_batch, worst_station);
}

if (output.empty()) {
m_outputPerNode.erase(&node);
Expand Down
10 changes: 3 additions & 7 deletions statik/test/Star.cpp
Expand Up @@ -107,10 +107,11 @@ void Star::run() {
{
Batch expected_batch;
List xca("a", "");
expected_batch.Delete(ca);
expected_batch.Insert(xca, NULL);
expected_batch.Delete(ca); // why does delete come after insert?
if (test(out_batch, expected_batch, "output")) {
xca_pos = out_batch.begin()->node;
xca_pos = (out_batch.begin()+1)->node;
g_log.debug() << " xca_pos: " << xca_pos;
}
}
out_batch.Clear();
Expand All @@ -131,12 +132,7 @@ void Star::run() {
test(root.GetState().GetStation(), statik::State::ST_DONE, "a");
ip.ExtractChanges(out_batch);
{
// Both items are deleted, then the remaining one is added back.
// That seems ok.
Batch expected_batch;
List xca("a", "");
expected_batch.Insert(xca, NULL);
expected_batch.Delete(ca3);
expected_batch.Delete(ca2);
test(out_batch, expected_batch, "output");
}
Expand Down

0 comments on commit 1ba09db

Please sign in to comment.