|
||||
File indexing completed on 2025-01-30 09:31:55
0001 // Copyright 2017 The Abseil Authors. 0002 // 0003 // Licensed under the Apache License, Version 2.0 (the "License"); 0004 // you may not use this file except in compliance with the License. 0005 // You may obtain a copy of the License at 0006 // 0007 // https://www.apache.org/licenses/LICENSE-2.0 0008 // 0009 // Unless required by applicable law or agreed to in writing, software 0010 // distributed under the License is distributed on an "AS IS" BASIS, 0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0012 // See the License for the specific language governing permissions and 0013 // limitations under the License. 0014 // 0015 0016 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_ 0017 #define ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_ 0018 0019 // GraphCycles detects the introduction of a cycle into a directed 0020 // graph that is being built up incrementally. 0021 // 0022 // Nodes are identified by small integers. It is not possible to 0023 // record multiple edges with the same (source, destination) pair; 0024 // requests to add an edge where one already exists are silently 0025 // ignored. 0026 // 0027 // It is also not possible to introduce a cycle; an attempt to insert 0028 // an edge that would introduce a cycle fails and returns false. 0029 // 0030 // GraphCycles uses no internal locking; calls into it should be 0031 // serialized externally. 0032 0033 // Performance considerations: 0034 // Works well on sparse graphs, poorly on dense graphs. 0035 // Extra information is maintained incrementally to detect cycles quickly. 0036 // InsertEdge() is very fast when the edge already exists, and reasonably fast 0037 // otherwise. 0038 // FindPath() is linear in the size of the graph. 0039 // The current implementation uses O(|V|+|E|) space. 0040 0041 #include <cstdint> 0042 0043 #include "absl/base/config.h" 0044 0045 namespace absl { 0046 ABSL_NAMESPACE_BEGIN 0047 namespace synchronization_internal { 0048 0049 // Opaque identifier for a graph node. 0050 struct GraphId { 0051 uint64_t handle; 0052 0053 bool operator==(const GraphId& x) const { return handle == x.handle; } 0054 bool operator!=(const GraphId& x) const { return handle != x.handle; } 0055 }; 0056 0057 // Return an invalid graph id that will never be assigned by GraphCycles. 0058 inline GraphId InvalidGraphId() { 0059 return GraphId{0}; 0060 } 0061 0062 class GraphCycles { 0063 public: 0064 GraphCycles(); 0065 ~GraphCycles(); 0066 0067 // Return the id to use for ptr, assigning one if necessary. 0068 // Subsequent calls with the same ptr value will return the same id 0069 // until Remove(). 0070 GraphId GetId(void* ptr); 0071 0072 // Remove "ptr" from the graph. Its corresponding node and all 0073 // edges to and from it are removed. 0074 void RemoveNode(void* ptr); 0075 0076 // Return the pointer associated with id, or nullptr if id is not 0077 // currently in the graph. 0078 void* Ptr(GraphId id); 0079 0080 // Attempt to insert an edge from source_node to dest_node. If the 0081 // edge would introduce a cycle, return false without making any 0082 // changes. Otherwise add the edge and return true. 0083 bool InsertEdge(GraphId source_node, GraphId dest_node); 0084 0085 // Remove any edge that exists from source_node to dest_node. 0086 void RemoveEdge(GraphId source_node, GraphId dest_node); 0087 0088 // Return whether node exists in the graph. 0089 bool HasNode(GraphId node); 0090 0091 // Return whether there is an edge directly from source_node to dest_node. 0092 bool HasEdge(GraphId source_node, GraphId dest_node) const; 0093 0094 // Return whether dest_node is reachable from source_node 0095 // by following edges. 0096 bool IsReachable(GraphId source_node, GraphId dest_node) const; 0097 0098 // Find a path from "source" to "dest". If such a path exists, 0099 // place the nodes on the path in the array path[], and return 0100 // the number of nodes on the path. If the path is longer than 0101 // max_path_len nodes, only the first max_path_len nodes are placed 0102 // in path[]. The client should compare the return value with 0103 // max_path_len" to see when this occurs. If no path exists, return 0104 // 0. Any valid path stored in path[] will start with "source" and 0105 // end with "dest". There is no guarantee that the path is the 0106 // shortest, but no node will appear twice in the path, except the 0107 // source and destination node if they are identical; therefore, the 0108 // return value is at most one greater than the number of nodes in 0109 // the graph. 0110 int FindPath(GraphId source, GraphId dest, int max_path_len, 0111 GraphId path[]) const; 0112 0113 // Update the stack trace recorded for id with the current stack 0114 // trace if the last time it was updated had a smaller priority 0115 // than the priority passed on this call. 0116 // 0117 // *get_stack_trace is called to get the stack trace. 0118 void UpdateStackTrace(GraphId id, int priority, 0119 int (*get_stack_trace)(void**, int)); 0120 0121 // Set *ptr to the beginning of the array that holds the recorded 0122 // stack trace for id and return the depth of the stack trace. 0123 int GetStackTrace(GraphId id, void*** ptr); 0124 0125 // Check internal invariants. Crashes on failure, returns true on success. 0126 // Expensive: should only be called from graphcycles_test.cc. 0127 bool CheckInvariants() const; 0128 0129 // Test-only method to add more nodes. The nodes will not be valid, and this 0130 // method should only be used to test the behavior of the graph when it is 0131 // very full. 0132 void TestOnlyAddNodes(uint32_t n); 0133 0134 // ---------------------------------------------------- 0135 struct Rep; 0136 private: 0137 Rep *rep_; // opaque representation 0138 GraphCycles(const GraphCycles&) = delete; 0139 GraphCycles& operator=(const GraphCycles&) = delete; 0140 }; 0141 0142 } // namespace synchronization_internal 0143 ABSL_NAMESPACE_END 0144 } // namespace absl 0145 0146 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |