Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  FindSCCs.h   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#ifndef gc_FindSCCs_h
#define gc_FindSCCs_h

#include "mozilla/Assertions.h"  // MOZ_ASSERT

#include <algorithm>  // std::min

#include "js/AllocPolicy.h"         // js::SystemAllocPolicy
#include "js/friend/StackLimits.h"  // js::AutoCheckRecursionLimit
#include "js/HashTable.h"           // js::HashSet, js::DefaultHasher

namespace js {
namespace gc {

template <typename Node>
struct GraphNodeBase {
  using NodeSet =
      js::HashSet<Node*, js::DefaultHasher<Node*>, js::SystemAllocPolicy>;

  NodeSet gcGraphEdges;
  Node* gcNextGraphNode = nullptr;
  Node* gcNextGraphComponent = nullptr;
  unsigned gcDiscoveryTime = 0;
  unsigned gcLowLink = 0;

  Node* nextNodeInGroup() const {
    if (gcNextGraphNode &&
        gcNextGraphNode->gcNextGraphComponent == gcNextGraphComponent) {
      return gcNextGraphNode;
    }
    return nullptr;
  }

  Node* nextGroup() const { return gcNextGraphComponent; }
};

/*
 * Find the strongly connected components of a graph using Tarjan's algorithm,
 * and return them in topological order.
 *
 * Nodes derive from GraphNodeBase and add target edge pointers to
 * sourceNode.gcGraphEdges to describe the graph:
 *
 * struct MyGraphNode : public GraphNodeBase<MyGraphNode>
 * {
 *   ...
 * }
 *
 * MyGraphNode node1, node2, node3;
 * node1.gcGraphEdges.put(node2); // Error checking elided.
 * node2.gcGraphEdges.put(node3);
 * node3.gcGraphEdges.put(node2);
 *
 * ComponentFinder<MyGraphNode> finder;
 * finder.addNode(node1);
 * finder.addNode(node2);
 * finder.addNode(node3);
 * MyGraphNode* result = finder.getResultsList();
 */


template <typename Node>
class ComponentFinder {
 public:
  explicit ComponentFinder(JSContext* cx) : cx(cx) {}

  ~ComponentFinder() {
    MOZ_ASSERT(!stack);
    MOZ_ASSERT(!firstComponent);
  }

  /* Forces all nodes to be added to a single component. */
  void useOneComponent() { stackFull = true; }

  void addNode(Node* v) {
    if (v->gcDiscoveryTime == Undefined) {
      MOZ_ASSERT(v->gcLowLink == Undefined);
      processNode(v);
    }
  }

  Node* getResultsList() {
    if (stackFull) {
      /*
       * All nodes after the stack overflow are in |stack|. Put them all in
       * one big component of their own.
       */

      Node* firstGoodComponent = firstComponent;
      for (Node* v = stack; v; v = stack) {
        stack = v->gcNextGraphNode;
        v->gcNextGraphComponent = firstGoodComponent;
        v->gcNextGraphNode = firstComponent;
        firstComponent = v;
      }
      stackFull = false;
    }

    MOZ_ASSERT(!stack);

    Node* result = firstComponent;
    firstComponent = nullptr;

    for (Node* v = result; v; v = v->gcNextGraphNode) {
      v->gcDiscoveryTime = Undefined;
      v->gcLowLink = Undefined;
    }

    return result;
  }

  static void mergeGroups(Node* first) {
    for (Node* v = first; v; v = v->gcNextGraphNode) {
      v->gcNextGraphComponent = nullptr;
    }
  }

 private:
  // Constant used to indicate an unprocessed vertex.
  static const unsigned Undefined = 0;

  // Constant used to indicate a processed vertex that is no longer on the
  // stack.
  static const unsigned Finished = (unsigned)-1;

  void addEdgeTo(Node* w) {
    if (w->gcDiscoveryTime == Undefined) {
      processNode(w);
      cur->gcLowLink = std::min(cur->gcLowLink, w->gcLowLink);
    } else if (w->gcDiscoveryTime != Finished) {
      cur->gcLowLink = std::min(cur->gcLowLink, w->gcDiscoveryTime);
    }
  }

  void processNode(Node* v) {
    v->gcDiscoveryTime = clock;
    v->gcLowLink = clock;
    ++clock;

    v->gcNextGraphNode = stack;
    stack = v;

    if (stackFull) {
      return;
    }

    AutoCheckRecursionLimit recursion(cx);
    if (!recursion.checkSystemDontReport(cx)) {
      stackFull = true;
      return;
    }

    Node* old = cur;
    cur = v;
    for (auto r = cur->gcGraphEdges.all(); !r.empty(); r.popFront()) {
      addEdgeTo(r.front());
    }
    cur = old;

    if (stackFull) {
      return;
    }

    if (v->gcLowLink == v->gcDiscoveryTime) {
      Node* nextComponent = firstComponent;
      Node* w;
      do {
        MOZ_ASSERT(stack);
        w = stack;
        stack = w->gcNextGraphNode;

        /*
         * Record that the element is no longer on the stack by setting the
         * discovery time to a special value that's not Undefined.
         */

        w->gcDiscoveryTime = Finished;

        /* Figure out which group we're in. */
        w->gcNextGraphComponent = nextComponent;

        /*
         * Prepend the component to the beginning of the output list to
         * reverse the list and achieve the desired order.
         */

        w->gcNextGraphNode = firstComponent;
        firstComponent = w;
      } while (w != v);
    }
  }

 private:
  unsigned clock = 1;
  Node* stack = nullptr;
  Node* firstComponent = nullptr;
  Node* cur = nullptr;
  JSContext* cx;
  bool stackFull = false;
};

/* namespace gc */
/* namespace js */

#endif /* gc_FindSCCs_h */

Messung V0.5
C=93 H=94 G=93

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge