00001
00002
00003
00004
00005
00006
00007
00008 #ifndef GALOIS_GRAPH_MEMSCALGRAPH_H
00009 #define GALOIS_GRAPH_MEMSCALGRAPH_H
00010
00011 #include "Galois/Bag.h"
00012 #include "Galois/Graph/Details.h"
00013 #include "Galois/Runtime/Context.h"
00014 #include "Galois/Runtime/MethodFlags.h"
00015
00016 #include "Galois/gdeque.h"
00017
00018 #include <boost/functional.hpp>
00019 #include <boost/iterator/transform_iterator.hpp>
00020 #include <boost/iterator/filter_iterator.hpp>
00021
00022 #include <algorithm>
00023 #include <map>
00024 #include <set>
00025 #include <vector>
00026
00027 namespace Galois {
00028 namespace Graph {
00029
00030 template<typename NodeTy, typename EdgeTy, bool Directional>
00031 class MemScalGraph : private boost::noncopyable {
00032 template<typename T>
00033 struct first_eq_and_valid {
00034 T N2;
00035 first_eq_and_valid(T& n) :N2(n) {}
00036 template <typename T2>
00037 bool operator()(const T2& ii) const {
00038 return ii.first() == N2 && ii.first();
00039 }
00040 };
00041 struct first_not_valid {
00042 template <typename T2>
00043 bool operator()(const T2& ii) const { return !ii.first();}
00044 };
00045
00046 struct gNode: public Galois::Runtime::Lockable {
00048 typedef GraphImpl::EdgeItem<gNode, EdgeTy, Directional> EITy;
00049
00051
00052 typedef Galois::gdeque<EITy,32> EdgesTy;
00053 typedef typename EdgesTy::iterator iterator;
00054
00055 EdgesTy edges;
00056 NodeTy data;
00057
00058
00059 template<typename... Args>
00060 gNode(Args&&... args): data(std::forward<Args>(args)...) { }
00061
00062 iterator begin() { return edges.begin(); }
00063 iterator end() { return edges.end(); }
00064
00065 void erase(iterator ii) {
00066 *ii = edges.back();
00067 edges.pop_back();
00068 }
00069
00070 void erase(gNode* N) {
00071 iterator ii = find(N);
00072 if (ii != end())
00073 edges.erase(ii);
00074 }
00075
00076 iterator find(gNode* N) {
00077 return std::find_if(begin(), end(), first_eq_and_valid<gNode*>(N));
00078 }
00079
00080
00081 template<typename... Args>
00082 iterator createEdge(gNode* N, EdgeTy* v, Args&&... args) {
00083 edges.push_front(EITy(N, v, std::forward<Args>(args)...));
00084 return edges.begin();
00085 }
00086
00087 template<typename... Args>
00088 iterator createEdgeWithReuse(gNode* N, EdgeTy* v, Args&&... args) {
00089
00090 iterator ii = std::find_if(begin(), end(), first_not_valid());
00091 if (ii != end()) {
00092 *ii = EITy(N, v, std::forward<Args>(args)...);
00093 return ii;
00094 }
00095 edges.push_front(EITy(N, v, std::forward<Args>(args)...));
00096 return edges.begin();
00097 }
00098 };
00099
00100
00101 typedef Galois::InsertBag<gNode> NodeListTy;
00102 NodeListTy nodes;
00103
00104 GraphImpl::EdgeFactory<EdgeTy> edges;
00105
00106
00107 struct is_node : public std::unary_function<gNode&, bool>{
00108 bool operator() (const gNode& g) const { return true; }
00109 };
00110 struct is_edge : public std::unary_function<typename gNode::EITy&, bool> {
00111 bool operator()(typename gNode::EITy& e) const { return true; }
00112 };
00113 struct makeGraphNode: public std::unary_function<gNode&, gNode*> {
00114 gNode* operator()(gNode& data) const { return &data; }
00115 };
00116
00117 public:
00119 typedef gNode* GraphNode;
00121 typedef EdgeTy edge_type;
00123 typedef NodeTy node_type;
00125 typedef typename gNode::iterator edge_iterator;
00127 typedef typename gNode::EITy::reference edge_data_reference;
00129 typedef boost::transform_iterator<makeGraphNode,
00130 boost::filter_iterator<is_node,
00131 typename NodeListTy::iterator> > iterator;
00132
00133 private:
00134 template<typename... Args>
00135 edge_iterator createEdgeWithReuse(GraphNode src, GraphNode dst, Galois::MethodFlag mflag, Args&&... args) {
00136 assert(src);
00137 assert(dst);
00138 Galois::Runtime::checkWrite(mflag, true);
00139 Galois::Runtime::acquire(src, mflag);
00140 typename gNode::iterator ii = src->find(dst);
00141 if (ii == src->end()) {
00142 if (Directional) {
00143 ii = src->createEdgeWithReuse(dst, 0, std::forward<Args>(args)...);
00144 } else {
00145 Galois::Runtime::acquire(dst, mflag);
00146 EdgeTy* e = edges.mkEdge(std::forward<Args>(args)...);
00147 ii = dst->createEdgeWithReuse(src, e, std::forward<Args>(args)...);
00148 ii = src->createEdgeWithReuse(dst, e, std::forward<Args>(args)...);
00149 }
00150 }
00151
00152 return ii;
00153 }
00154
00155 template<typename... Args>
00156 edge_iterator createEdge(GraphNode src, GraphNode dst, Galois::MethodFlag mflag, Args&&... args) {
00157 assert(src);
00158 assert(dst);
00159 Galois::Runtime::checkWrite(mflag, true);
00160 Galois::Runtime::acquire(src, mflag);
00161 typename gNode::iterator ii = src->end();
00162 if (ii == src->end()) {
00163 if (Directional) {
00164 ii = src->createEdge(dst, 0, std::forward<Args>(args)...);
00165 } else {
00166 Galois::Runtime::acquire(dst, mflag);
00167 EdgeTy* e = edges.mkEdge(std::forward<Args>(args)...);
00168 ii = dst->createEdge(src, e, std::forward<Args>(args)...);
00169 ii = src->createEdge(dst, e, std::forward<Args>(args)...);
00170 }
00171 }
00172 return ii;
00173 }
00174
00175 public:
00180 template<typename... Args>
00181 GraphNode createNode(Args&&... args) {
00182 gNode* N = &(nodes.emplace(std::forward<Args>(args)...));
00183 return GraphNode(N);
00184 }
00185
00189 void addNode(const GraphNode& n, Galois::MethodFlag mflag = MethodFlag::ALL) {
00190 Galois::Runtime::checkWrite(mflag, true);
00191 Galois::Runtime::acquire(n, mflag);
00192 }
00193
00195 NodeTy& getData(const GraphNode& n, Galois::MethodFlag mflag = MethodFlag::ALL) const {
00196 assert(n);
00197 Galois::Runtime::checkWrite(mflag, false);
00198 Galois::Runtime::acquire(n, mflag);
00199 return n->data;
00200 }
00201
00203 bool containsNode(const GraphNode& n, Galois::MethodFlag mflag = MethodFlag::ALL) const {
00204 assert(n);
00205 Galois::Runtime::acquire(n, mflag);
00206 }
00207
00208
00209
00217 edge_iterator addEdge(GraphNode src, GraphNode dst, Galois::MethodFlag mflag = MethodFlag::ALL) {
00218 return createEdgeWithReuse(src, dst, mflag);
00219 }
00220
00222 template<typename... Args>
00223 edge_iterator addMultiEdge(GraphNode src, GraphNode dst, Galois::MethodFlag mflag, Args&&... args) {
00224 return createEdge(src, dst, mflag, std::forward<Args>(args)...);
00225 }
00226
00227
00229 edge_iterator findEdge(GraphNode src, GraphNode dst, Galois::MethodFlag mflag = MethodFlag::ALL) {
00230 assert(src);
00231 assert(dst);
00232 Galois::Runtime::acquire(src, mflag);
00233
00234 return src->find(dst);
00235 }
00236
00244 edge_data_reference getEdgeData(edge_iterator ii, Galois::MethodFlag mflag = MethodFlag::NONE) const {
00245
00246 Galois::Runtime::checkWrite(mflag, false);
00247 Galois::Runtime::acquire(ii->first(), mflag);
00248 return *ii->second();
00249 }
00250
00252 GraphNode getEdgeDst(edge_iterator ii) {
00253
00254 return GraphNode(ii->first());
00255 }
00256
00258
00260 edge_iterator edge_begin(GraphNode N, Galois::MethodFlag mflag = MethodFlag::ALL) {
00261 assert(N);
00262 Galois::Runtime::acquire(N, mflag);
00263
00264 if (Galois::Runtime::shouldLock(mflag)) {
00265 for (typename gNode::iterator ii = N->begin(), ee = N->end(); ii != ee; ++ii) {
00266
00267 Galois::Runtime::acquire(ii->first(), mflag);
00268 }
00269 }
00270 return N->begin();
00271 }
00272
00274 edge_iterator edge_end(GraphNode N, Galois::MethodFlag mflag = MethodFlag::ALL) {
00275 assert(N);
00276
00277
00278
00279 return N->end();
00280 }
00281
00286 detail::EdgesIterator<MemScalGraph> out_edges(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00287 return detail::EdgesIterator<MemScalGraph>(*this, N, mflag);
00288 }
00289
00293 iterator begin() {
00294 return boost::make_transform_iterator(nodes.begin(),makeGraphNode());
00295 }
00296
00298 iterator end() {
00299 return boost::make_transform_iterator(nodes.end(),makeGraphNode());
00300 }
00301
00302 typedef iterator local_iterator;
00303
00304 local_iterator local_begin() {
00305 return boost::make_transform_iterator(nodes.local_begin(),makeGraphNode());
00306 }
00307
00308 local_iterator local_end() {
00309 return boost::make_transform_iterator(nodes.local_end(),makeGraphNode());
00310
00311 }
00312
00316 unsigned int size() {
00317 return std::distance(begin(), end());
00318 }
00319
00321 size_t sizeOfEdgeData() const {
00322 return gNode::EITy::sizeOfSecond();
00323 }
00324
00325 MemScalGraph() { }
00326 };
00327
00328 }
00329 }
00330
00331
00332 #endif