graphcycles.h
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 //
00015 
00016 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_
00017 #define ABSL_SYNCHRONIZATION_INTERNAL_GRAPHCYCLES_H_
00018 
00019 // GraphCycles detects the introduction of a cycle into a directed
00020 // graph that is being built up incrementally.
00021 //
00022 // Nodes are identified by small integers.  It is not possible to
00023 // record multiple edges with the same (source, destination) pair;
00024 // requests to add an edge where one already exists are silently
00025 // ignored.
00026 //
00027 // It is also not possible to introduce a cycle; an attempt to insert
00028 // an edge that would introduce a cycle fails and returns false.
00029 //
00030 // GraphCycles uses no internal locking; calls into it should be
00031 // serialized externally.
00032 
00033 // Performance considerations:
00034 //   Works well on sparse graphs, poorly on dense graphs.
00035 //   Extra information is maintained incrementally to detect cycles quickly.
00036 //   InsertEdge() is very fast when the edge already exists, and reasonably fast
00037 //   otherwise.
00038 //   FindPath() is linear in the size of the graph.
00039 // The current implemenation uses O(|V|+|E|) space.
00040 
00041 #include <cstdint>
00042 
00043 namespace absl {
00044 namespace synchronization_internal {
00045 
00046 // Opaque identifier for a graph node.
00047 struct GraphId {
00048   uint64_t handle;
00049 
00050   bool operator==(const GraphId& x) const { return handle == x.handle; }
00051   bool operator!=(const GraphId& x) const { return handle != x.handle; }
00052 };
00053 
00054 // Return an invalid graph id that will never be assigned by GraphCycles.
00055 inline GraphId InvalidGraphId() {
00056   return GraphId{0};
00057 }
00058 
00059 class GraphCycles {
00060  public:
00061   GraphCycles();
00062   ~GraphCycles();
00063 
00064   // Return the id to use for ptr, assigning one if necessary.
00065   // Subsequent calls with the same ptr value will return the same id
00066   // until Remove().
00067   GraphId GetId(void* ptr);
00068 
00069   // Remove "ptr" from the graph.  Its corresponding node and all
00070   // edges to and from it are removed.
00071   void RemoveNode(void* ptr);
00072 
00073   // Return the pointer associated with id, or nullptr if id is not
00074   // currently in the graph.
00075   void* Ptr(GraphId id);
00076 
00077   // Attempt to insert an edge from source_node to dest_node.  If the
00078   // edge would introduce a cycle, return false without making any
00079   // changes. Otherwise add the edge and return true.
00080   bool InsertEdge(GraphId source_node, GraphId dest_node);
00081 
00082   // Remove any edge that exists from source_node to dest_node.
00083   void RemoveEdge(GraphId source_node, GraphId dest_node);
00084 
00085   // Return whether node exists in the graph.
00086   bool HasNode(GraphId node);
00087 
00088   // Return whether there is an edge directly from source_node to dest_node.
00089   bool HasEdge(GraphId source_node, GraphId dest_node) const;
00090 
00091   // Return whether dest_node is reachable from source_node
00092   // by following edges.
00093   bool IsReachable(GraphId source_node, GraphId dest_node) const;
00094 
00095   // Find a path from "source" to "dest".  If such a path exists,
00096   // place the nodes on the path in the array path[], and return
00097   // the number of nodes on the path.  If the path is longer than
00098   // max_path_len nodes, only the first max_path_len nodes are placed
00099   // in path[].  The client should compare the return value with
00100   // max_path_len" to see when this occurs.  If no path exists, return
00101   // 0.  Any valid path stored in path[] will start with "source" and
00102   // end with "dest".  There is no guarantee that the path is the
00103   // shortest, but no node will appear twice in the path, except the
00104   // source and destination node if they are identical; therefore, the
00105   // return value is at most one greater than the number of nodes in
00106   // the graph.
00107   int FindPath(GraphId source, GraphId dest, int max_path_len,
00108                GraphId path[]) const;
00109 
00110   // Update the stack trace recorded for id with the current stack
00111   // trace if the last time it was updated had a smaller priority
00112   // than the priority passed on this call.
00113   //
00114   // *get_stack_trace is called to get the stack trace.
00115   void UpdateStackTrace(GraphId id, int priority,
00116                         int (*get_stack_trace)(void**, int));
00117 
00118   // Set *ptr to the beginning of the array that holds the recorded
00119   // stack trace for id and return the depth of the stack trace.
00120   int GetStackTrace(GraphId id, void*** ptr);
00121 
00122   // Check internal invariants. Crashes on failure, returns true on success.
00123   // Expensive: should only be called from graphcycles_test.cc.
00124   bool CheckInvariants() const;
00125 
00126   // ----------------------------------------------------
00127   struct Rep;
00128  private:
00129   Rep *rep_;      // opaque representation
00130   GraphCycles(const GraphCycles&) = delete;
00131   GraphCycles& operator=(const GraphCycles&) = delete;
00132 };
00133 
00134 }  // namespace synchronization_internal
00135 }  // namespace absl
00136 
00137 #endif


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14