abseil-cpp/absl/synchronization/internal/graphcycles.h
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 
16 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_
17 #define ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_
18 
19 // GraphCycles detects the introduction of a cycle into a directed
20 // graph that is being built up incrementally.
21 //
22 // Nodes are identified by small integers. It is not possible to
23 // record multiple edges with the same (source, destination) pair;
24 // requests to add an edge where one already exists are silently
25 // ignored.
26 //
27 // It is also not possible to introduce a cycle; an attempt to insert
28 // an edge that would introduce a cycle fails and returns false.
29 //
30 // GraphCycles uses no internal locking; calls into it should be
31 // serialized externally.
32 
33 // Performance considerations:
34 // Works well on sparse graphs, poorly on dense graphs.
35 // Extra information is maintained incrementally to detect cycles quickly.
36 // InsertEdge() is very fast when the edge already exists, and reasonably fast
37 // otherwise.
38 // FindPath() is linear in the size of the graph.
39 // The current implementation uses O(|V|+|E|) space.
40 
41 #include <cstdint>
42 
43 #include "absl/base/config.h"
44 
45 namespace absl {
47 namespace synchronization_internal {
48 
49 // Opaque identifier for a graph node.
50 struct GraphId {
52 
53  bool operator==(const GraphId& x) const { return handle == x.handle; }
54  bool operator!=(const GraphId& x) const { return handle != x.handle; }
55 };
56 
57 // Return an invalid graph id that will never be assigned by GraphCycles.
59  return GraphId{0};
60 }
61 
62 class GraphCycles {
63  public:
64  GraphCycles();
65  ~GraphCycles();
66 
67  // Return the id to use for ptr, assigning one if necessary.
68  // Subsequent calls with the same ptr value will return the same id
69  // until Remove().
70  GraphId GetId(void* ptr);
71 
72  // Remove "ptr" from the graph. Its corresponding node and all
73  // edges to and from it are removed.
74  void RemoveNode(void* ptr);
75 
76  // Return the pointer associated with id, or nullptr if id is not
77  // currently in the graph.
78  void* Ptr(GraphId id);
79 
80  // Attempt to insert an edge from source_node to dest_node. If the
81  // edge would introduce a cycle, return false without making any
82  // changes. Otherwise add the edge and return true.
83  bool InsertEdge(GraphId source_node, GraphId dest_node);
84 
85  // Remove any edge that exists from source_node to dest_node.
86  void RemoveEdge(GraphId source_node, GraphId dest_node);
87 
88  // Return whether node exists in the graph.
89  bool HasNode(GraphId node);
90 
91  // Return whether there is an edge directly from source_node to dest_node.
92  bool HasEdge(GraphId source_node, GraphId dest_node) const;
93 
94  // Return whether dest_node is reachable from source_node
95  // by following edges.
96  bool IsReachable(GraphId source_node, GraphId dest_node) const;
97 
98  // Find a path from "source" to "dest". If such a path exists,
99  // place the nodes on the path in the array path[], and return
100  // the number of nodes on the path. If the path is longer than
101  // max_path_len nodes, only the first max_path_len nodes are placed
102  // in path[]. The client should compare the return value with
103  // max_path_len" to see when this occurs. If no path exists, return
104  // 0. Any valid path stored in path[] will start with "source" and
105  // end with "dest". There is no guarantee that the path is the
106  // shortest, but no node will appear twice in the path, except the
107  // source and destination node if they are identical; therefore, the
108  // return value is at most one greater than the number of nodes in
109  // the graph.
110  int FindPath(GraphId source, GraphId dest, int max_path_len,
111  GraphId path[]) const;
112 
113  // Update the stack trace recorded for id with the current stack
114  // trace if the last time it was updated had a smaller priority
115  // than the priority passed on this call.
116  //
117  // *get_stack_trace is called to get the stack trace.
118  void UpdateStackTrace(GraphId id, int priority,
119  int (*get_stack_trace)(void**, int));
120 
121  // Set *ptr to the beginning of the array that holds the recorded
122  // stack trace for id and return the depth of the stack trace.
123  int GetStackTrace(GraphId id, void*** ptr);
124 
125  // Check internal invariants. Crashes on failure, returns true on success.
126  // Expensive: should only be called from graphcycles_test.cc.
127  bool CheckInvariants() const;
128 
129  // ----------------------------------------------------
130  struct Rep;
131  private:
132  Rep *rep_; // opaque representation
133  GraphCycles(const GraphCycles&) = delete;
134  GraphCycles& operator=(const GraphCycles&) = delete;
135 };
136 
137 } // namespace synchronization_internal
139 } // namespace absl
140 
141 #endif
absl::synchronization_internal::GraphCycles::InsertEdge
bool InsertEdge(GraphId source_node, GraphId dest_node)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:493
ptr
char * ptr
Definition: abseil-cpp/absl/base/internal/low_level_alloc_test.cc:45
absl::synchronization_internal::GraphCycles::HasEdge
bool HasEdge(GraphId source_node, GraphId dest_node) const
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:470
absl::synchronization_internal::GraphCycles::rep_
Rep * rep_
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:130
priority
int priority
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:286
absl::synchronization_internal::GraphCycles::UpdateStackTrace
void UpdateStackTrace(GraphId id, int priority, int(*get_stack_trace)(void **, int))
absl::synchronization_internal::GraphId::operator==
bool operator==(const GraphId &x) const
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:53
absl::synchronization_internal::GraphCycles::~GraphCycles
~GraphCycles()
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:371
absl::synchronization_internal::GraphCycles::GraphCycles
GraphCycles()
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:365
absl::synchronization_internal::GraphCycles::CheckInvariants
bool CheckInvariants() const
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:380
absl::synchronization_internal::GraphCycles::HasNode
bool HasNode(GraphId node)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:466
absl::synchronization_internal::GraphCycles::IsReachable
bool IsReachable(GraphId source_node, GraphId dest_node) const
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:669
check_documentation.path
path
Definition: check_documentation.py:57
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::synchronization_internal::GraphId::operator!=
bool operator!=(const GraphId &x) const
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:54
absl::synchronization_internal::GraphId
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:50
absl::synchronization_internal::GraphCycles::RemoveNode
void RemoveNode(void *ptr)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:437
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
absl::synchronization_internal::GraphCycles::RemoveEdge
void RemoveEdge(GraphId source_node, GraphId dest_node)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:475
absl::synchronization_internal::GraphCycles::GetStackTrace
int GetStackTrace(GraphId id, void ***ptr)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:683
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
absl::synchronization_internal::GraphCycles::Ptr
void * Ptr(GraphId id)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:460
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
tests.qps.qps_worker.dest
dest
Definition: qps_worker.py:45
absl::synchronization_internal::GraphId::handle
uint64_t handle
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:51
absl::synchronization_internal::GraphCycles::operator=
GraphCycles & operator=(const GraphCycles &)=delete
absl::synchronization_internal::GraphCycles::Rep
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:345
absl::synchronization_internal::GraphCycles::GetId
GraphId GetId(void *ptr)
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:406
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
absl::synchronization_internal::InvalidGraphId
GraphId InvalidGraphId()
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:58
absl::synchronization_internal::GraphCycles
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.h:62
absl::synchronization_internal::GraphCycles::FindPath
int FindPath(GraphId source, GraphId dest, int max_path_len, GraphId path[]) const
Definition: abseil-cpp/absl/synchronization/internal/graphcycles.cc:625


grpc
Author(s):
autogenerated on Fri May 16 2025 02:58:44