00001
00027 #ifndef GALOIS_GRAPH_DETAILS_H
00028 #define GALOIS_GRAPH_DETAILS_H
00029
00030 #include "Galois/LargeArray.h"
00031 #include "Galois/LazyObject.h"
00032 #include "Galois/NoDerefIterator.h"
00033 #include "Galois/Threads.h"
00034 #include "Galois/Runtime/Context.h"
00035 #include "Galois/Runtime/MethodFlags.h"
00036 #include "Galois/Runtime/PerThreadStorage.h"
00037
00038 #include <boost/mpl/if.hpp>
00039 #include <algorithm>
00040
00041 namespace Galois {
00042 namespace Graph {
00043
00044 struct read_default_graph_tag { };
00045 struct read_with_aux_graph_tag { };
00046 struct read_lc_inout_graph_tag { };
00047
00049 template<typename GraphNode, typename EdgeTy>
00050 struct EdgeSortValue: public StrictObject<EdgeTy> {
00051 typedef StrictObject<EdgeTy> Super;
00052 typedef typename Super::value_type value_type;
00053
00054 GraphNode dst;
00055
00056 EdgeSortValue(GraphNode d, const value_type& v): Super(v), dst(d) { }
00057
00058 template<typename ER>
00059 EdgeSortValue(const ER& ref) {
00060 ref.initialize(*this);
00061 }
00062 };
00063
00065 namespace detail {
00066
00067 template<bool Enable>
00068 class LocalIteratorFeature {
00069 typedef std::pair<uint64_t,uint64_t> Range;
00070 Runtime::PerThreadStorage<Range> localIterators;
00071 public:
00072 uint64_t localBegin(uint64_t numNodes) const {
00073 return localIterators.getLocal()->first;
00074 }
00075
00076 uint64_t localEnd(uint64_t numNodes) const {
00077 return localIterators.getLocal()->second;
00078 }
00079
00080 void setLocalRange(uint64_t begin, uint64_t end) {
00081 Range& r = *localIterators.getLocal();
00082 r.first = begin;
00083 r.second = end;
00084 }
00085 };
00086
00087 template<>
00088 struct LocalIteratorFeature<false> {
00089 uint64_t localBegin(uint64_t numNodes) const {
00090 unsigned int id = Galois::Runtime::LL::getTID();
00091 unsigned int num = Galois::getActiveThreads();
00092 return (numNodes + num - 1) / num * id;
00093 }
00094
00095 uint64_t localEnd(uint64_t numNodes) const {
00096 unsigned int id = Galois::Runtime::LL::getTID();
00097 unsigned int num = Galois::getActiveThreads();
00098 uint64_t end = (numNodes + num - 1) / num * (id + 1);
00099 return std::min(end, numNodes);
00100 }
00101
00102 void setLocalRange(uint64_t begin, uint64_t end) { }
00103 };
00104
00106 template<typename GraphNode, typename EdgeIndex, typename EdgeDst, typename EdgeData>
00107 struct EdgeSortReference {
00108 typedef typename EdgeData::raw_value_type EdgeTy;
00109 EdgeIndex at;
00110 EdgeDst* edgeDst;
00111 EdgeData* edgeData;
00112
00113 EdgeSortReference(EdgeIndex x, EdgeDst* dsts, EdgeData* data): at(x), edgeDst(dsts), edgeData(data) { }
00114
00115 EdgeSortReference operator=(const EdgeSortValue<GraphNode, EdgeTy>& x) {
00116 edgeDst->set(at, x.dst);
00117 edgeData->set(at, x.get());
00118 return *this;
00119 }
00120
00121 EdgeSortReference operator=(const EdgeSortReference<GraphNode,EdgeIndex,EdgeDst,EdgeData>& x) {
00122 edgeDst->set(at, edgeDst->at(x.at));
00123 edgeData->set(at, edgeData->at(x.at));
00124 return *this;
00125 }
00126
00127 EdgeSortValue<GraphNode, EdgeTy> operator*() const {
00128 return EdgeSortValue<GraphNode, EdgeTy>(edgeDst->at(at), edgeData->at(at));
00129 }
00130
00131 void initialize(EdgeSortValue<GraphNode, EdgeTy>& value) const {
00132 value = *(*this);
00133 }
00134 };
00135
00139 template<typename EdgeSortValueTy,typename CompTy>
00140 struct EdgeSortCompWrapper {
00141 const CompTy& comp;
00142
00143 EdgeSortCompWrapper(const CompTy& c): comp(c) { }
00144 bool operator()(const EdgeSortValueTy& a, const EdgeSortValueTy& b) const {
00145 return comp(a.get(), b.get());
00146 }
00147 };
00148
00158 template<typename GraphNode, typename EdgeIndex, typename EdgeDst, typename EdgeData>
00159 class EdgeSortIterator: public boost::iterator_facade<
00160 EdgeSortIterator<GraphNode, EdgeIndex, EdgeDst, EdgeData>,
00161 EdgeSortValue<GraphNode, typename EdgeData::raw_value_type>,
00162 boost::random_access_traversal_tag,
00163 EdgeSortReference<GraphNode, EdgeIndex, EdgeDst, EdgeData>
00164 > {
00165 typedef EdgeSortIterator<GraphNode,EdgeIndex,EdgeDst,EdgeData> Self;
00166 typedef EdgeSortReference<GraphNode,EdgeIndex,EdgeDst,EdgeData> Reference;
00167
00168 EdgeIndex at;
00169 EdgeDst* edgeDst;
00170 EdgeData* edgeData;
00171 public:
00172 EdgeSortIterator(): at(0) { }
00173 EdgeSortIterator(EdgeIndex x, EdgeDst* dsts, EdgeData* data):
00174 at(x), edgeDst(dsts), edgeData(data) { }
00175 private:
00176 friend class boost::iterator_core_access;
00177
00178 bool equal(const Self& other) const { return at == other.at; }
00179 Reference dereference() const { return Reference(at, edgeDst, edgeData); }
00180 ptrdiff_t distance_to(const Self& other) const { return other.at - (ptrdiff_t) at; }
00181 void increment() { ++at; }
00182 void decrement() { --at; }
00183 void advance(ptrdiff_t n) { at += n; }
00184 };
00185
00186 template<typename IdTy>
00187 class IntrusiveId {
00188 IdTy id;
00189 public:
00190 IdTy& getId() { return id; }
00191 void setId(size_t n) { id = n; }
00192 };
00193
00194 template<>
00195 class IntrusiveId<void> {
00196 public:
00197 char getId() { return 0; }
00198 void setId(size_t n) { }
00199 };
00200
00202 class NoLockable { };
00203
00205 template<typename NodeTy, bool HasLockable>
00206 struct NodeInfoBaseTypes {
00207 typedef NodeTy& reference;
00208 };
00209
00210 template<bool HasLockable>
00211 struct NodeInfoBaseTypes<void, HasLockable> {
00212 typedef void* reference;
00213 };
00214
00216 template<typename NodeTy, bool HasLockable>
00217 class NodeInfoBase:
00218 public boost::mpl::if_c<HasLockable,Galois::Runtime::Lockable,NoLockable>::type,
00219 public NodeInfoBaseTypes<NodeTy, HasLockable>
00220 {
00221 NodeTy data;
00222 public:
00223 template<typename... Args>
00224 NodeInfoBase(Args&&... args): data(std::forward<Args>(args)...) { }
00225
00226 typename NodeInfoBase::reference getData() { return data; }
00227 };
00228
00229 template<bool HasLockable>
00230 struct NodeInfoBase<void, HasLockable>:
00231 public boost::mpl::if_c<HasLockable,Galois::Runtime::Lockable,NoLockable>::type,
00232 public NodeInfoBaseTypes<void, HasLockable>
00233 {
00234 typename NodeInfoBase::reference getData() { return 0; }
00235 };
00236
00237 template<bool Enable>
00238 class OutOfLineLockableFeature {
00239 typedef NodeInfoBase<void,true> OutOfLineLock;
00240 LargeArray<OutOfLineLock> outOfLineLocks;
00241 public:
00242 struct size_of_out_of_line {
00243 static const size_t value = sizeof(OutOfLineLock);
00244 };
00245
00246 void outOfLineAcquire(size_t n, MethodFlag mflag) {
00247 Galois::Runtime::acquire(&outOfLineLocks[n], mflag);
00248 }
00249 void outOfLineAllocateLocal(size_t numNodes, bool preFault) {
00250 outOfLineLocks.allocateLocal(numNodes, preFault);
00251 }
00252 void outOfLineAllocateInterleaved(size_t numNodes) {
00253 outOfLineLocks.allocateInterleaved(numNodes);
00254 }
00255 void outOfLineConstructAt(size_t n) {
00256 outOfLineLocks.constructAt(n);
00257 }
00258 };
00259
00260 template<>
00261 class OutOfLineLockableFeature<false> {
00262 public:
00263 struct size_of_out_of_line {
00264 static const size_t value = 0;
00265 };
00266 void outOfLineAcquire(size_t n, MethodFlag mflag) { }
00267 void outOfLineAllocateLocal(size_t numNodes, bool preFault) { }
00268 void outOfLineAllocateInterleaved(size_t numNodes) { }
00269 void outOfLineConstructAt(size_t n) { }
00270 };
00271
00273 template<typename NodeInfoPtrTy,typename EdgeTy>
00274 struct EdgeInfoBase: public LazyObject<EdgeTy>
00275 {
00276 NodeInfoPtrTy dst;
00277 };
00278
00283 template<typename GraphTy>
00284 class EdgesIterator {
00285 GraphTy& g;
00286 typename GraphTy::GraphNode n;
00287 MethodFlag flag;
00288 public:
00289 typedef NoDerefIterator<typename GraphTy::edge_iterator> iterator;
00290
00291 EdgesIterator(GraphTy& g, typename GraphTy::GraphNode n, MethodFlag f): g(g), n(n), flag(f) { }
00292
00293 iterator begin() { return make_no_deref_iterator(g.edge_begin(n, flag)); }
00294 iterator end() { return make_no_deref_iterator(g.edge_end(n, flag)); }
00295 };
00296
00301 template<typename GraphTy>
00302 class InEdgesIterator {
00303 GraphTy& g;
00304 typename GraphTy::GraphNode n;
00305 MethodFlag flag;
00306 public:
00307 typedef NoDerefIterator<typename GraphTy::in_edge_iterator> iterator;
00308
00309 InEdgesIterator(GraphTy& g, typename GraphTy::GraphNode n, MethodFlag f): g(g), n(n), flag(f) { }
00310
00311 iterator begin() { return make_no_deref_iterator(g.in_edge_begin(n, flag)); }
00312 iterator end() { return make_no_deref_iterator(g.in_edge_end(n, flag)); }
00313 };
00314
00315 template<typename GraphTy>
00316 class EdgesWithNoFlagIterator {
00317 GraphTy& g;
00318 typename GraphTy::GraphNode n;
00319 public:
00320 typedef NoDerefIterator<typename GraphTy::edge_iterator> iterator;
00321
00322 EdgesWithNoFlagIterator(GraphTy& g, typename GraphTy::GraphNode n): g(g), n(n) { }
00323
00324 iterator begin() { return make_no_deref_iterator(g.edge_begin(n)); }
00325 iterator end() { return make_no_deref_iterator(g.edge_end(n)); }
00326 };
00327
00328 template<typename GN, typename EI, typename EdgeData,typename Data>
00329 void swap(EdgeSortReference<GN,EI,EdgeData,Data> a, EdgeSortReference<GN,EI,EdgeData,Data> b) {
00330 auto aa = *a;
00331 auto bb = *b;
00332 a = bb;
00333 b = aa;
00334 }
00335
00336 }
00337 }
00338 }
00339
00340 #endif