/** Initializes a CycleGraph object. */
CycleGraph::CycleGraph() :
- hasCycles(false)
+ hasCycles(false),
+ oldCycles(false)
{
}
* @param to The edge points to this ModelAction
* @param from The edge comes from this ModelAction
*/
-void CycleGraph::addEdge(const ModelAction *to, const ModelAction *from) {
+void CycleGraph::addEdge(const ModelAction *from, const ModelAction *to) {
CycleNode *fromnode=getNode(from);
CycleNode *tonode=getNode(to);
// Check for Cycles
hasCycles=checkReachable(tonode, fromnode);
}
+
+ rollbackvector.push_back(fromnode);
fromnode->addEdge(tonode);
CycleNode * rmwnode=fromnode->getRMW();
// Check for Cycles
hasCycles=checkReachable(tonode, rmwnode);
}
+ rollbackvector.push_back(rmwnode);
rmwnode->addEdge(tonode);
}
}
* can occur in between the rmw and the from action. Only one RMW
* action can read from a given write.
*/
-void CycleGraph::addRMWEdge(const ModelAction *rmw, const ModelAction *from) {
+void CycleGraph::addRMWEdge(const ModelAction *from, const ModelAction *rmw) {
CycleNode *fromnode=getNode(from);
CycleNode *rmwnode=getNode(rmw);
/* Two RMW actions cannot read from the same write. */
if (fromnode->setRMW(rmwnode)) {
hasCycles=true;
+ } else {
+ rmwrollbackvector.push_back(fromnode);
}
/* Transfer all outgoing edges from the from node to the rmw node */
std::vector<CycleNode *> * edges=fromnode->getEdges();
for(unsigned int i=0;i<edges->size();i++) {
CycleNode * tonode=(*edges)[i];
+ rollbackvector.push_back(rmwnode);
rmwnode->addEdge(tonode);
}
-
+ rollbackvector.push_back(fromnode);
fromnode->addEdge(rmwnode);
}
+/**
+ * Checks whether one ModelAction can reach another.
+ * @param from The ModelAction from which to begin exploration
+ * @param to The ModelAction to reach
+ * @return True, @a from can reach @a to; otherwise, false
+ */
+bool CycleGraph::checkReachable(const ModelAction *from, const ModelAction *to) {
+ CycleNode *fromnode = actionToNode.get(from);
+ CycleNode *tonode = actionToNode.get(to);
+
+ if (!fromnode || !tonode)
+ return false;
+
+ return checkReachable(fromnode, tonode);
+}
/**
* Checks whether one CycleNode can reach another.
return false;
}
+/** Commit changes to the cyclegraph. */
+void CycleGraph::commitChanges() {
+ rollbackvector.resize(0);
+ rmwrollbackvector.resize(0);
+ oldCycles=hasCycles;
+}
+
+/** Rollback changes to the previous commit. */
+void CycleGraph::rollbackChanges() {
+ for (unsigned int i = 0; i < rollbackvector.size(); i++) {
+ rollbackvector[i]->popEdge();
+ }
+
+ for (unsigned int i = 0; i < rmwrollbackvector.size(); i++) {
+ rmwrollbackvector[i]->clearRMW();
+ }
+
+ hasCycles = oldCycles;
+ rollbackvector.resize(0);
+ rmwrollbackvector.resize(0);
+}
+
/** @returns whether a CycleGraph contains cycles. */
bool CycleGraph::checkForCycles() {
return hasCycles;
* @see CycleGraph::addRMWEdge
*/
bool CycleNode::setRMW(CycleNode *node) {
- CycleNode * oldhasRMW=hasRMW;
+ if (hasRMW!=NULL)
+ return true;
hasRMW=node;
- return (oldhasRMW!=NULL);
+ return false;
}