+/**
+ * Checks whether one ModelAction/Promise can reach another ModelAction/Promise
+ * @param from The ModelAction or Promise from which to begin exploration
+ * @param to The ModelAction or Promise to reach
+ * @return True, @a from can reach @a to; otherwise, false
+ */
+template <typename T, typename U>
+bool CycleGraph::checkReachable(const T *from, const U *to) const
+{
+ CycleNode *fromnode = getNode_noCreate(from);
+ CycleNode *tonode = getNode_noCreate(to);
+
+ if (!fromnode || !tonode)
+ return false;
+
+ return checkReachable(fromnode, tonode);
+}
+/* Instantiate three forms of CycleGraph::checkReachable */
+template bool CycleGraph::checkReachable(const ModelAction *from,
+ const ModelAction *to) const;
+template bool CycleGraph::checkReachable(const ModelAction *from,
+ const Promise *to) const;
+template bool CycleGraph::checkReachable(const Promise *from,
+ const ModelAction *to) const;
+
+/** @return True, if the promise has failed; false otherwise */
+bool CycleGraph::checkPromise(const ModelAction *fromact, Promise *promise) const
+{
+ std::vector< CycleNode *, ModelAlloc<CycleNode *> > queue;
+ discovered->reset();
+ CycleNode *from = actionToNode.get(fromact);
+
+ queue.push_back(from);
+ discovered->put(from, from);
+ while (!queue.empty()) {
+ CycleNode *node = queue.back();
+ queue.pop_back();
+
+ if (node->getPromise() == promise)
+ return true;
+ if (!node->is_promise() &&
+ promise->eliminate_thread(node->getAction()->get_tid()))
+ return true;
+
+ for (unsigned int i = 0; i < node->getNumEdges(); i++) {
+ CycleNode *next = node->getEdge(i);
+ if (!discovered->contains(next)) {
+ discovered->put(next, next);
+ queue.push_back(next);
+ }
+ }
+ }
+ return false;
+}
+
+void CycleGraph::startChanges()
+{
+ ASSERT(rollbackvector.empty());
+ ASSERT(rmwrollbackvector.empty());
+ ASSERT(oldCycles == hasCycles);
+}
+
+/** Commit changes to the cyclegraph. */
+void CycleGraph::commitChanges()
+{
+ rollbackvector.clear();
+ rmwrollbackvector.clear();
+ oldCycles = hasCycles;
+}
+
+/** Rollback changes to the previous commit. */
+void CycleGraph::rollbackChanges()
+{
+ for (unsigned int i = 0; i < rollbackvector.size(); i++)
+ rollbackvector[i]->removeEdge();
+
+ for (unsigned int i = 0; i < rmwrollbackvector.size(); i++)
+ rmwrollbackvector[i]->clearRMW();
+
+ hasCycles = oldCycles;
+ rollbackvector.clear();
+ rmwrollbackvector.clear();
+}
+