{
ASSERT(!w_node->is_promise());
ASSERT(p_node->is_promise());
+
const Promise *promise = p_node->getPromise();
if (!promise->is_compatible(w_node->getAction())) {
hasCycles = true;
return false;
}
+ /* Transfer the RMW */
+ CycleNode *promise_rmw = p_node->getRMW();
+ if (promise_rmw && promise_rmw != w_node->getRMW() && w_node->setRMW(promise_rmw))
+ hasCycles = true;
+
/* Transfer back edges to w_node */
while (p_node->getNumBackEdges() > 0) {
CycleNode *back = p_node->removeBackEdge();
* Adds an edge between two CycleNodes.
* @param fromnode The edge comes from this CycleNode
* @param tonode The edge points to this CycleNode
+ * @return True, if new edge(s) are added; otherwise false
*/
-void CycleGraph::addNodeEdge(CycleNode *fromnode, CycleNode *tonode)
+bool CycleGraph::addNodeEdge(CycleNode *fromnode, CycleNode *tonode)
{
+ bool added;
+
if (!hasCycles)
hasCycles = checkReachable(tonode, fromnode);
- if (fromnode->addEdge(tonode))
+ if ((added = fromnode->addEdge(tonode)))
rollbackvector.push_back(fromnode);
/*
if (!hasCycles)
hasCycles = checkReachable(tonode, rmwnode);
- if (rmwnode->addEdge(tonode))
+ if (rmwnode->addEdge(tonode)) {
rollbackvector.push_back(rmwnode);
+ added = true;
+ }
}
+ return added;
}
/**
* @brief Add an edge between a write and the RMW which reads from it
*
* Handles special case of a RMW action, where the ModelAction rmw reads from
- * the ModelAction from. The key differences are:
+ * the ModelAction/Promise from. The key differences are:
* (1) no write can occur in between the rmw and the from action.
* (2) Only one RMW action can read from a given write.
*
- * @param from The edge comes from this ModelAction
+ * @param from The edge comes from this ModelAction/Promise
* @param rmw The edge points to this ModelAction; this action must read from
- * ModelAction from
+ * the ModelAction/Promise from
*/
-void CycleGraph::addRMWEdge(const ModelAction *from, const ModelAction *rmw)
+template <typename T>
+void CycleGraph::addRMWEdge(const T *from, const ModelAction *rmw)
{
ASSERT(from);
ASSERT(rmw);
addNodeEdge(fromnode, rmwnode);
}
+/* Instantiate two forms of CycleGraph::addRMWEdge */
+template void CycleGraph::addRMWEdge(const ModelAction *from, const ModelAction *rmw);
+template void CycleGraph::addRMWEdge(const Promise *from, const ModelAction *rmw);
+
+/**
+ * @brief Adds an edge between objects
+ *
+ * This function will add an edge between any two objects which can be
+ * associated with a CycleNode. That is, if they have a CycleGraph::getNode
+ * implementation.
+ *
+ * The object to is ordered after the object from.
+ *
+ * @param to The edge points to this object, of type T
+ * @param from The edge comes from this object, of type U
+ * @return True, if new edge(s) are added; otherwise false
+ */
+template <typename T, typename U>
+bool CycleGraph::addEdge(const T *from, const U *to)
+{
+ ASSERT(from);
+ ASSERT(to);
+
+ CycleNode *fromnode = getNode(from);
+ CycleNode *tonode = getNode(to);
+
+ return addNodeEdge(fromnode, tonode);
+}
+/* Instantiate three forms of CycleGraph::addEdge */
+template bool CycleGraph::addEdge(const ModelAction *from, const ModelAction *to);
+template bool CycleGraph::addEdge(const ModelAction *from, const Promise *to);
+template bool CycleGraph::addEdge(const Promise *from, const ModelAction *to);
#if SUPPORT_MOD_ORDER_DUMP
void CycleGraph::dumpNodes(FILE *file) const
return false;
}
+/**
+ * Checks whether one ModelAction can reach another ModelAction/Promise
+ * @param from The ModelAction 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>
+bool CycleGraph::checkReachable(const ModelAction *from, const T *to) const
+{
+ CycleNode *fromnode = getNode_noCreate(from);
+ CycleNode *tonode = getNode_noCreate(to);
+
+ if (!fromnode || !tonode)
+ return false;
+
+ return checkReachable(fromnode, tonode);
+}
+/* Instantiate two 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;
+
/** @return True, if the promise has failed; false otherwise */
bool CycleGraph::checkPromise(const ModelAction *fromact, Promise *promise) const
{
void CycleGraph::rollbackChanges()
{
for (unsigned int i = 0; i < rollbackvector.size(); i++)
- rollbackvector[i]->popEdge();
+ rollbackvector[i]->removeEdge();
for (unsigned int i = 0; i < rmwrollbackvector.size(); i++)
rmwrollbackvector[i]->clearRMW();