1 //===-- sanitizer_bvgraph.h -------------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of Sanitizer runtime.
9 // BVGraph -- a directed graph.
11 //===----------------------------------------------------------------------===//
13 #ifndef SANITIZER_BVGRAPH_H
14 #define SANITIZER_BVGRAPH_H
16 #include "sanitizer_common.h"
17 #include "sanitizer_bitvector.h"
19 namespace __sanitizer
{
21 // Directed graph of fixed size implemented as an array of bit vectors.
22 // Not thread-safe, all accesses should be protected by an external lock.
26 enum SizeEnum
{ kSize
= BV::kSize
};
27 uptr
size() const { return kSize
; }
30 for (uptr i
= 0; i
< size(); i
++)
35 for (uptr i
= 0; i
< size(); i
++)
41 // Returns true if a new edge was added.
42 bool addEdge(uptr from
, uptr to
) {
44 return v
[from
].setBit(to
);
47 // Returns true if at least one new edge was added.
48 uptr
addEdges(const BV
&from
, uptr to
, uptr added_edges
[],
49 uptr max_added_edges
) {
53 uptr node
= t1
.getAndClearFirstOne();
54 if (v
[node
].setBit(to
))
55 if (res
< max_added_edges
)
56 added_edges
[res
++] = node
;
62 // Returns true if an edge from=>to exist.
63 // This function does not use any global state except for 'this' itself,
64 // and thus can be called from different threads w/o locking.
65 // This would be racy.
66 // FIXME: investigate how much we can prove about this race being "benign".
67 bool hasEdge(uptr from
, uptr to
) { return v
[from
].getBit(to
); }
69 // Returns true if the edge from=>to was removed.
70 bool removeEdge(uptr from
, uptr to
) {
71 return v
[from
].clearBit(to
);
74 // Returns true if at least one edge *=>to was removed.
75 bool removeEdgesTo(const BV
&to
) {
77 for (uptr from
= 0; from
< size(); from
++) {
78 if (v
[from
].setDifference(to
))
84 // Returns true if at least one edge from=>* was removed.
85 bool removeEdgesFrom(const BV
&from
) {
89 uptr idx
= t1
.getAndClearFirstOne();
90 if (!v
[idx
].empty()) {
98 void removeEdgesFrom(uptr from
) {
99 return v
[from
].clear();
102 bool hasEdge(uptr from
, uptr to
) const {
104 return v
[from
].getBit(to
);
107 // Returns true if there is a path from the node 'from'
108 // to any of the nodes in 'targets'.
109 bool isReachable(uptr from
, const BV
&targets
) {
112 to_visit
.copyFrom(v
[from
]);
114 visited
.setBit(from
);
115 while (!to_visit
.empty()) {
116 uptr idx
= to_visit
.getAndClearFirstOne();
117 if (visited
.setBit(idx
))
118 to_visit
.setUnion(v
[idx
]);
120 return targets
.intersectsWith(visited
);
123 // Finds a path from 'from' to one of the nodes in 'target',
124 // stores up to 'path_size' items of the path into 'path',
125 // returns the path length, or 0 if there is no path of size 'path_size'.
126 uptr
findPath(uptr from
, const BV
&targets
, uptr
*path
, uptr path_size
) {
130 if (targets
.getBit(from
))
132 // The function is recursive, so we don't want to create BV on stack.
133 // Instead of a getAndClearFirstOne loop we use the slower iterator.
134 for (typename
BV::Iterator
it(v
[from
]); it
.hasNext(); ) {
135 uptr idx
= it
.next();
136 if (uptr res
= findPath(idx
, targets
, path
+ 1, path_size
- 1))
142 // Same as findPath, but finds a shortest path.
143 uptr
findShortestPath(uptr from
, const BV
&targets
, uptr
*path
,
145 for (uptr p
= 1; p
<= path_size
; p
++)
146 if (findPath(from
, targets
, path
, p
) == p
)
152 void check(uptr idx1
, uptr idx2
) const {
153 CHECK_LT(idx1
, size());
154 CHECK_LT(idx2
, size());
157 // Keep temporary vectors here since we can not create large objects on stack.
161 } // namespace __sanitizer
163 #endif // SANITIZER_BVGRAPH_H