lldependencies.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:32k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file   lldependencies.h
  3.  * @author Nat Goodspeed
  4.  * @date   2008-09-17
  5.  * @brief  LLDependencies: a generic mechanism for expressing "b must follow a,
  6.  *         but precede c"
  7.  *
  8.  * $LicenseInfo:firstyear=2008&license=viewergpl$
  9.  * 
  10.  * Copyright (c) 2008-2010, Linden Research, Inc.
  11.  * 
  12.  * Second Life Viewer Source Code
  13.  * The source code in this file ("Source Code") is provided by Linden Lab
  14.  * to you under the terms of the GNU General Public License, version 2.0
  15.  * ("GPL"), unless you have obtained a separate licensing agreement
  16.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  17.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  18.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  19.  * 
  20.  * There are special exceptions to the terms and conditions of the GPL as
  21.  * it is applied to this Source Code. View the full text of the exception
  22.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  23.  * online at
  24.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  25.  * 
  26.  * By copying, modifying or distributing this software, you acknowledge
  27.  * that you have read and understood your obligations described above,
  28.  * and agree to abide by those obligations.
  29.  * 
  30.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  31.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  32.  * COMPLETENESS OR PERFORMANCE.
  33.  * $/LicenseInfo$
  34.  */
  35. #if ! defined(LL_LLDEPENDENCIES_H)
  36. #define LL_LLDEPENDENCIES_H
  37. #include <string>
  38. #include <vector>
  39. #include <set>
  40. #include <map>
  41. #include <stdexcept>
  42. #include <iosfwd>
  43. #include <boost/iterator/transform_iterator.hpp>
  44. #include <boost/iterator/indirect_iterator.hpp>
  45. #include <boost/range/iterator_range.hpp>
  46. #include <boost/function.hpp>
  47. #include <boost/bind.hpp>
  48. /*****************************************************************************
  49. *   Utilities
  50. *****************************************************************************/
  51. /**
  52.  * generic range transformer: given a range acceptable to Boost.Range (e.g. a
  53.  * standard container, an iterator pair, ...) and a unary function to apply to
  54.  * each element of the range, make a corresponding range that lazily applies
  55.  * that function to each element on dereferencing.
  56.  */
  57. template<typename FUNCTION, typename RANGE>
  58. inline
  59. boost::iterator_range<boost::transform_iterator<FUNCTION,
  60.                                                 typename boost::range_const_iterator<RANGE>::type> >
  61. make_transform_range(const RANGE& range, FUNCTION function)
  62. {
  63.     // shorthand for the iterator type embedded in our return type
  64.     typedef boost::transform_iterator<FUNCTION, typename boost::range_const_iterator<RANGE>::type>
  65.         transform_iterator;
  66.     return boost::make_iterator_range(transform_iterator(boost::begin(range), function),
  67.                                       transform_iterator(boost::end(range),   function));
  68. }
  69. /// non-const version of make_transform_range()
  70. template<typename FUNCTION, typename RANGE>
  71. inline
  72. boost::iterator_range<boost::transform_iterator<FUNCTION,
  73.                                                 typename boost::range_iterator<RANGE>::type> >
  74. make_transform_range(RANGE& range, FUNCTION function)
  75. {
  76.     // shorthand for the iterator type embedded in our return type
  77.     typedef boost::transform_iterator<FUNCTION, typename boost::range_iterator<RANGE>::type>
  78.         transform_iterator;
  79.     return boost::make_iterator_range(transform_iterator(boost::begin(range), function),
  80.                                       transform_iterator(boost::end(range),   function));
  81. }
  82. /**
  83.  * From any range compatible with Boost.Range, instantiate any class capable
  84.  * of accepting an iterator pair.
  85.  */
  86. template<class TYPE>
  87. struct instance_from_range: public TYPE
  88. {
  89.     template<typename RANGE>
  90.     instance_from_range(RANGE range):
  91.         TYPE(boost::begin(range), boost::end(range))
  92.     {}
  93. };
  94. /*****************************************************************************
  95. *   LLDependencies
  96. *****************************************************************************/
  97. /**
  98.  * LLDependencies components that should not be reinstantiated for each KEY,
  99.  * NODE specialization
  100.  */
  101. class LL_COMMON_API LLDependenciesBase
  102. {
  103. public:
  104.     virtual ~LLDependenciesBase() {}
  105.     /**
  106.      * Exception thrown by sort() if there's a cycle
  107.      */
  108.     struct Cycle: public std::runtime_error
  109.     {
  110.         Cycle(const std::string& what): std::runtime_error(what) {}
  111.     };
  112.     /**
  113.      * Provide a short description of this LLDependencies instance on the
  114.      * specified output stream, assuming that its KEY type has an operator<<()
  115.      * that works with std::ostream.
  116.      *
  117.      * Pass @a full as @c false to omit any keys without dependency constraints.
  118.      */
  119.     virtual std::ostream& describe(std::ostream& out, bool full=true) const;
  120.     /// describe() to a string
  121.     virtual std::string describe(bool full=true) const;
  122. protected:
  123.     typedef std::vector< std::pair<int, int> > EdgeList;
  124.     typedef std::vector<int> VertexList;
  125.     VertexList topo_sort(int vertices, const EdgeList& edges) const;
  126.     /**
  127.      * refpair is specifically intended to capture a pair of references. This
  128.      * is better than std::pair<T1&, T2&> because some implementations of
  129.      * std::pair's ctor accept const references to the two types. If the
  130.      * types are themselves references, this results in an illegal reference-
  131.      * to-reference.
  132.      */
  133.     template<typename T1, typename T2>
  134.     struct refpair
  135.     {
  136.         refpair(T1 value1, T2 value2):
  137.             first(value1),
  138.             second(value2)
  139.         {}
  140.         T1 first;
  141.         T2 second;
  142.     };
  143. };
  144. /// describe() helper: for most types, report the type as usual
  145. template<typename T>
  146. inline
  147. std::ostream& LLDependencies_describe(std::ostream& out, const T& key)
  148. {
  149.     out << key;
  150.     return out;
  151. }
  152. /// specialize LLDependencies_describe() for std::string
  153. template<>
  154. inline
  155. std::ostream& LLDependencies_describe(std::ostream& out, const std::string& key)
  156. {
  157.     out << '"' << key << '"';
  158.     return out;
  159. }
  160. /**
  161.  * It's reasonable to use LLDependencies in a keys-only way, more or less like
  162.  * std::set. For that case, the default NODE type is an empty struct.
  163.  */
  164. struct LLDependenciesEmpty
  165. {
  166.     LLDependenciesEmpty() {}
  167.     /**
  168.      * Give it a constructor accepting void* so caller can pass placeholder
  169.      * values such as NULL or 0 rather than having to write
  170.      * LLDependenciesEmpty().
  171.      */
  172.     LLDependenciesEmpty(void*) {}    
  173. };
  174. /**
  175.  * This class manages abstract dependencies between node types of your
  176.  * choosing. As with a std::map, nodes are copied when add()ed, so the node
  177.  * type should be relatively lightweight; to manipulate dependencies between
  178.  * expensive objects, use a pointer type.
  179.  *
  180.  * For a given node, you may state the keys of nodes that must precede it
  181.  * and/or nodes that must follow it. The sort() method will produce an order
  182.  * that should work, or throw an exception if the constraints are impossible.
  183.  * We cache results to minimize the cost of repeated sort() calls.
  184.  */
  185. template<typename KEY = std::string,
  186.          typename NODE = LLDependenciesEmpty>
  187. class LLDependencies: public LLDependenciesBase
  188. {
  189.     typedef LLDependencies<KEY, NODE> self_type;
  190.     /**
  191.      * Internally, we bundle the client's NODE with its before/after keys.
  192.      */
  193.     struct DepNode
  194.     {
  195.         typedef std::set<KEY> dep_set;
  196.         DepNode(const NODE& node_, const dep_set& after_, const dep_set& before_):
  197.             node(node_),
  198.             after(after_),
  199.             before(before_)
  200.         {}
  201.         NODE node;
  202.         dep_set after, before;    
  203.     };
  204.     typedef std::map<KEY, DepNode> DepNodeMap;
  205.     typedef typename DepNodeMap::value_type DepNodeMapEntry;
  206.     /// We have various ways to get the dependencies for a given DepNode.
  207.     /// Rather than having to restate each one for 'after' and 'before'
  208.     /// separately, pass a dep_selector so we can apply each to either.
  209.     typedef boost::function<const typename DepNode::dep_set&(const DepNode&)> dep_selector;
  210. public:
  211.     LLDependencies() {}
  212.     typedef KEY key_type;
  213.     typedef NODE node_type;
  214.     /// param type used to express lists of other node keys -- note that such
  215.     /// lists can be initialized with boost::assign::list_of()
  216.     typedef std::vector<KEY> KeyList;
  217.     /**
  218.      * Add a new node. State its dependencies on other nodes (which may not
  219.      * yet have been added) by listing the keys of nodes this new one must
  220.      * follow, and separately the keys of nodes this new one must precede.
  221.      *
  222.      * The node you pass is @em copied into an internal data structure. If you
  223.      * want to modify the node value after add()ing it, capture the returned
  224.      * NODE& reference.
  225.      *
  226.      * @note
  227.      * Actual dependency analysis is deferred to the sort() method, so 
  228.      * you can add an arbitrary number of nodes without incurring analysis
  229.      * overhead for each. The flip side of this is that add()ing nodes that
  230.      * define a cycle leaves this object in a state in which sort() will
  231.      * always throw the Cycle exception.
  232.      *
  233.      * Two distinct use cases are anticipated:
  234.      * * The data used to load this object are completely known at compile
  235.      * time (e.g. LLEventPump listener names). A Cycle exception represents a
  236.      * bug which can be corrected by the coder. The program need neither catch
  237.      * Cycle nor attempt to salvage the state of this object.
  238.      * * The data are loaded at runtime, therefore the universe of
  239.      * dependencies cannot be known at compile time. The client code should
  240.      * catch Cycle.
  241.      * ** If a Cycle exception indicates fatally-flawed input data, this
  242.      * object can simply be discarded, possibly with the entire program run.
  243.      * ** If it is essential to restore this object to a working state, the
  244.      * simplest workaround is to remove() nodes in LIFO order.
  245.      * *** It may be useful to add functionality to this class to track the
  246.      * add() chronology, providing a pop() method to remove the most recently
  247.      * added node.
  248.      * *** It may further be useful to add a restore() method which would
  249.      * pop() until sort() no longer throws Cycle. This method would be
  250.      * expensive -- but it's not clear that client code could resolve the
  251.      * problem more cheaply.
  252.      */
  253.     NODE& add(const KEY& key, const NODE& node = NODE(),
  254.               const KeyList& after = KeyList(),
  255.               const KeyList& before = KeyList())
  256.     {
  257.         // Get the passed-in lists as sets for equality comparison
  258.         typename DepNode::dep_set
  259.             after_set(after.begin(), after.end()),
  260.             before_set(before.begin(), before.end());
  261.         // Try to insert the new node; if it already exists, find the old
  262.         // node instead.
  263.         std::pair<typename DepNodeMap::iterator, bool> inserted =
  264.             mNodes.insert(typename DepNodeMap::value_type(key,
  265.                                                           DepNode(node, after_set, before_set)));
  266.         if (! inserted.second)      // bool indicating success of insert()
  267.         {
  268.             // We already have a node by this name. Have its dependencies
  269.             // changed? If the existing node's dependencies are identical, the
  270.             // result will be unchanged, so we can leave the cache intact.
  271.             // Regardless of inserted.second, inserted.first is the iterator
  272.             // to the newly-inserted (or existing) map entry. Of course, that
  273.             // entry's second is the DepNode of interest.
  274.             if (inserted.first->second.after  != after_set ||
  275.                 inserted.first->second.before != before_set)
  276.             {
  277.                 // Dependencies have changed: clear the cached result.
  278.                 mCache.clear();
  279.                 // save the new dependencies
  280.                 inserted.first->second.after  = after_set;
  281.                 inserted.first->second.before = before_set;
  282.             }
  283.         }
  284.         else                        // this node is new
  285.         {
  286.             // This will change results.
  287.             mCache.clear();
  288.         }
  289.         return inserted.first->second.node;
  290.     }
  291.     /// the value of an iterator, showing both KEY and its NODE
  292.     typedef refpair<const KEY&, NODE&> value_type;
  293.     /// the value of a const_iterator
  294.     typedef refpair<const KEY&, const NODE&> const_value_type;
  295. private:
  296.     // Extract functors
  297.     static value_type value_extract(DepNodeMapEntry& entry)
  298.     {
  299.         return value_type(entry.first, entry.second.node);
  300.     }
  301.     static const_value_type const_value_extract(const DepNodeMapEntry& entry)
  302.     {
  303.         return const_value_type(entry.first, entry.second.node);
  304.     }
  305.     // All the iterator access methods return iterator ranges just to cut down
  306.     // on the friggin' boilerplate!!
  307.     /// generic mNodes range method
  308.     template<typename ITERATOR, typename FUNCTION>
  309.     boost::iterator_range<ITERATOR> generic_range(FUNCTION function)
  310.     {
  311.         return make_transform_range(mNodes, function);
  312.     }
  313.     /// generic mNodes const range method
  314.     template<typename ITERATOR, typename FUNCTION>
  315.     boost::iterator_range<ITERATOR> generic_range(FUNCTION function) const
  316.     {
  317.         return make_transform_range(mNodes, function);
  318.     }
  319. public:
  320.     /// iterator over value_type entries
  321.     typedef boost::transform_iterator<boost::function<value_type(DepNodeMapEntry&)>,
  322.                                       typename DepNodeMap::iterator> iterator;
  323.     /// range over value_type entries
  324.     typedef boost::iterator_range<iterator> range;
  325.     /// iterate over value_type <i>in @c KEY order</i> rather than dependency order
  326.     range get_range()
  327.     {
  328.         return generic_range<iterator>(value_extract);
  329.     }
  330.     /// iterator over const_value_type entries
  331.     typedef boost::transform_iterator<boost::function<const_value_type(const DepNodeMapEntry&)>,
  332.                                       typename DepNodeMap::const_iterator> const_iterator;
  333.     /// range over const_value_type entries
  334.     typedef boost::iterator_range<const_iterator> const_range;
  335.     /// iterate over const_value_type <i>in @c KEY order</i> rather than dependency order
  336.     const_range get_range() const
  337.     {
  338.         return generic_range<const_iterator>(const_value_extract);
  339.     }
  340.     /// iterator over stored NODEs
  341.     typedef boost::transform_iterator<boost::function<NODE&(DepNodeMapEntry&)>,
  342.                                       typename DepNodeMap::iterator> node_iterator;
  343.     /// range over stored NODEs
  344.     typedef boost::iterator_range<node_iterator> node_range;
  345.     /// iterate over NODE <i>in @c KEY order</i> rather than dependency order
  346.     node_range get_node_range()
  347.     {
  348.         // First take a DepNodeMapEntry and extract a reference to its
  349.         // DepNode, then from that extract a reference to its NODE.
  350.         return generic_range<node_iterator>(
  351.             boost::bind<NODE&>(&DepNode::node,
  352.                                boost::bind<DepNode&>(&DepNodeMapEntry::second, _1)));
  353.     }
  354.     /// const iterator over stored NODEs
  355.     typedef boost::transform_iterator<boost::function<const NODE&(const DepNodeMapEntry&)>,
  356.                                       typename DepNodeMap::const_iterator> const_node_iterator;
  357.     /// const range over stored NODEs
  358.     typedef boost::iterator_range<const_node_iterator> const_node_range;
  359.     /// iterate over const NODE <i>in @c KEY order</i> rather than dependency order
  360.     const_node_range get_node_range() const
  361.     {
  362.         // First take a DepNodeMapEntry and extract a reference to its
  363.         // DepNode, then from that extract a reference to its NODE.
  364.         return generic_range<const_node_iterator>(
  365.             boost::bind<const NODE&>(&DepNode::node,
  366.                                      boost::bind<const DepNode&>(&DepNodeMapEntry::second, _1)));
  367.     }
  368.     /// const iterator over stored KEYs
  369.     typedef boost::transform_iterator<boost::function<const KEY&(const DepNodeMapEntry&)>,
  370.                                       typename DepNodeMap::const_iterator> const_key_iterator;
  371.     /// const range over stored KEYs
  372.     typedef boost::iterator_range<const_key_iterator> const_key_range;
  373.     // We don't provide a non-const iterator over KEYs because they should be
  374.     // immutable, and in fact our underlying std::map won't give us non-const
  375.     // references.
  376.     /// iterate over const KEY <i>in @c KEY order</i> rather than dependency order
  377.     const_key_range get_key_range() const
  378.     {
  379.         // From a DepNodeMapEntry, extract a reference to its KEY.
  380.         return generic_range<const_key_iterator>(
  381.             boost::bind<const KEY&>(&DepNodeMapEntry::first, _1));
  382.     }
  383.     /**
  384.      * Find an existing NODE, or return NULL. We decided to avoid providing a
  385.      * method analogous to std::map::find(), for a couple of reasons:
  386.      *
  387.      * * For a find-by-key, getting back an iterator to the (key, value) pair
  388.      * is less than useful, since you already have the key in hand.
  389.      * * For a failed request, comparing to end() is problematic. First, we
  390.      * provide range accessors, so it's more code to get end(). Second, we
  391.      * provide a number of different ranges -- quick, to which one's end()
  392.      * should we compare the iterator returned by find()?
  393.      *
  394.      * The returned pointer is solely to allow expressing the not-found
  395.      * condition. LLDependencies still owns the found NODE.
  396.      */
  397.     const NODE* get(const KEY& key) const
  398.     {
  399.         typename DepNodeMap::const_iterator found = mNodes.find(key);
  400.         if (found != mNodes.end())
  401.         {
  402.             return &found->second.node;
  403.         }
  404.         return NULL;
  405.     }
  406.     /**
  407.      * non-const get()
  408.      */
  409.     NODE* get(const KEY& key)
  410.     {
  411.         // Use const implementation, then cast away const-ness of return
  412.         return const_cast<NODE*>(const_cast<const self_type*>(this)->get(key));
  413.     }
  414.     /**
  415.      * Remove a node with specified key. This operation is the major reason
  416.      * we rebuild the graph on the fly instead of storing it.
  417.      */
  418.     bool remove(const KEY& key)
  419.     {
  420.         typename DepNodeMap::iterator found = mNodes.find(key);
  421.         if (found != mNodes.end())
  422.         {
  423.             mNodes.erase(found);
  424.             return true;
  425.         }
  426.         return false;
  427.     }
  428. private:
  429.     /// cached list of iterators
  430.     typedef std::vector<iterator> iterator_list;
  431.     typedef typename iterator_list::iterator iterator_list_iterator;
  432. public:
  433.     /**
  434.      * The return type of the sort() method needs some explanation. Provide a
  435.      * public typedef to facilitate storing the result.
  436.      *
  437.      * * We will prepare mCache by looking up DepNodeMap iterators.
  438.      * * We want to return a range containing iterators that will walk mCache.
  439.      * * If we simply stored DepNodeMap iterators and returned
  440.      * (mCache.begin(), mCache.end()), dereferencing each iterator would
  441.      * obtain a DepNodeMap iterator.
  442.      * * We want the caller to loop over @c value_type: pair<KEY, NODE>.
  443.      * * This requires two transformations:
  444.      * ** mCache must contain @c LLDependencies::iterator so that
  445.      * dereferencing each entry will obtain an @c LLDependencies::value_type
  446.      * rather than a DepNodeMapEntry.
  447.      * ** We must wrap mCache's iterators in boost::indirect_iterator so that
  448.      * dereferencing one of our returned iterators will also dereference the
  449.      * iterator contained in mCache.
  450.      */
  451.     typedef boost::iterator_range<boost::indirect_iterator<iterator_list_iterator> > sorted_range;
  452.     /// for convenience in looping over a sorted_range
  453.     typedef typename sorted_range::iterator sorted_iterator;
  454.     /**
  455.      * Once we've loaded in the dependencies of interest, arrange them into an
  456.      * order that works -- or throw Cycle exception.
  457.      *
  458.      * Return an iterator range over (key, node) pairs that traverses them in
  459.      * the desired order.
  460.      */
  461.     sorted_range sort() const
  462.     {
  463.         // Changes to mNodes cause us to clear our cache, so empty mCache
  464.         // means it's invalid and should be recomputed. However, if mNodes is
  465.         // also empty, then an empty mCache represents a valid order, so don't
  466.         // bother sorting.
  467.         if (mCache.empty() && ! mNodes.empty())
  468.         {
  469.             // Construct a map of node keys to distinct vertex numbers -- even for
  470.             // nodes mentioned only in before/after constraints, that haven't yet
  471.             // been explicitly added. Rely on std::map rejecting a second attempt
  472.             // to insert the same key. Use the map's size() as the vertex number
  473.             // to get a distinct value for each successful insertion.
  474.             typedef std::map<KEY, int> VertexMap;
  475.             VertexMap vmap;
  476.             // Nest each of these loops because !@#$%? MSVC warns us that its
  477.             // former broken behavior has finally been fixed -- and our builds
  478.             // treat warnings as errors.
  479.             {
  480.                 for (typename DepNodeMap::const_iterator nmi = mNodes.begin(), nmend = mNodes.end();
  481.                      nmi != nmend; ++nmi)
  482.                 {
  483.                     vmap.insert(typename VertexMap::value_type(nmi->first, vmap.size()));
  484.                     for (typename DepNode::dep_set::const_iterator ai = nmi->second.after.begin(),
  485.                                                                    aend = nmi->second.after.end();
  486.                          ai != aend; ++ai)
  487.                     {
  488.                         vmap.insert(typename VertexMap::value_type(*ai, vmap.size()));
  489.                     }
  490.                     for (typename DepNode::dep_set::const_iterator bi = nmi->second.before.begin(),
  491.                                                                    bend = nmi->second.before.end();
  492.                          bi != bend; ++bi)
  493.                     {
  494.                         vmap.insert(typename VertexMap::value_type(*bi, vmap.size()));
  495.                     }
  496.                 }
  497.             }
  498.             // Define the edges. For this we must traverse mNodes again, mapping
  499.             // all the known key dependencies to integer pairs.
  500.             EdgeList edges;
  501.             {
  502.                 for (typename DepNodeMap::const_iterator nmi = mNodes.begin(), nmend = mNodes.end();
  503.                      nmi != nmend; ++nmi)
  504.                 {
  505.                     int thisnode = vmap[nmi->first];
  506.                     // after dependencies: build edges from the named node to this one
  507.                     for (typename DepNode::dep_set::const_iterator ai = nmi->second.after.begin(),
  508.                                                                    aend = nmi->second.after.end();
  509.                          ai != aend; ++ai)
  510.                     {
  511.                         edges.push_back(EdgeList::value_type(vmap[*ai], thisnode));
  512.                     }
  513.                     // before dependencies: build edges from this node to the
  514.                     // named one
  515.                     for (typename DepNode::dep_set::const_iterator bi = nmi->second.before.begin(),
  516.                                                                    bend = nmi->second.before.end();
  517.                          bi != bend; ++bi)
  518.                     {
  519.                         edges.push_back(EdgeList::value_type(thisnode, vmap[*bi]));
  520.                     }
  521.                 }
  522.             }
  523.             // Hide the gory details of our topological sort, since they shouldn't
  524.             // get reinstantiated for each distinct NODE type.
  525.             VertexList sorted(topo_sort(vmap.size(), edges));
  526.             // Build the reverse of vmap to look up the key for each vertex
  527.             // descriptor. vmap contains exactly one entry for each distinct key,
  528.             // and we're certain that the associated int values are distinct
  529.             // indexes. The fact that they're not in order is irrelevant.
  530.             KeyList vkeys(vmap.size());
  531.             for (typename VertexMap::const_iterator vmi = vmap.begin(), vmend = vmap.end();
  532.                  vmi != vmend; ++vmi)
  533.             {
  534.                 vkeys[vmi->second] = vmi->first;
  535.             }
  536.             // Walk the sorted output list, building the result into mCache so
  537.             // we'll have it next time someone asks.
  538.             mCache.clear();
  539.             for (VertexList::const_iterator svi = sorted.begin(), svend = sorted.end();
  540.                  svi != svend; ++svi)
  541.             {
  542.                 // We're certain that vkeys[*svi] exists. However, there might not
  543.                 // yet be a corresponding entry in mNodes.
  544.                 self_type* non_const_this(const_cast<self_type*>(this));
  545.                 typename DepNodeMap::iterator found = non_const_this->mNodes.find(vkeys[*svi]);
  546.                 if (found != non_const_this->mNodes.end())
  547.                 {
  548.                     // Make an iterator of appropriate type.
  549.                     mCache.push_back(iterator(found, value_extract));
  550.                 }
  551.             }
  552.         }
  553.         // Whether or not we've just recomputed mCache, it should now contain
  554.         // the results we want. Return a range of indirect_iterators over it
  555.         // so that dereferencing a returned iterator will dereference the
  556.         // iterator stored in mCache and directly reference the (key, node)
  557.         // pair.
  558.         boost::indirect_iterator<iterator_list_iterator>
  559.             begin(mCache.begin()),
  560.             end(mCache.end());
  561.         return sorted_range(begin, end);
  562.     }
  563. using LLDependenciesBase::describe; // unhide virtual std::string describe(bool full=true) const;
  564.     /// Override base-class describe() with actual implementation
  565.     virtual std::ostream& describe(std::ostream& out, bool full=true) const
  566.     {
  567.         typename DepNodeMap::const_iterator dmi(mNodes.begin()), dmend(mNodes.end());
  568.         if (dmi != dmend)
  569.         {
  570.             std::string sep;
  571.             describe(out, sep, *dmi, full);
  572.             while (++dmi != dmend)
  573.             {
  574.                 describe(out, sep, *dmi, full);
  575.             }
  576.         }
  577.         return out;
  578.     }
  579.     /// describe() helper: report a DepNodeEntry
  580.     static std::ostream& describe(std::ostream& out, std::string& sep,
  581.                                   const DepNodeMapEntry& entry, bool full)
  582.     {
  583.         // If we were asked for a full report, describe every node regardless
  584.         // of whether it has dependencies. If we were asked to suppress
  585.         // independent nodes, describe this one if either after or before is
  586.         // non-empty.
  587.         if (full || (! entry.second.after.empty()) || (! entry.second.before.empty()))
  588.         {
  589.             out << sep;
  590.             sep = "n";
  591.             if (! entry.second.after.empty())
  592.             {
  593.                 out << "after ";
  594.                 describe(out, entry.second.after);
  595.                 out << " -> ";
  596.             }
  597.             LLDependencies_describe(out, entry.first);
  598.             if (! entry.second.before.empty())
  599.             {
  600.                 out << " -> before ";
  601.                 describe(out, entry.second.before);
  602.             }
  603.         }
  604.         return out;
  605.     }
  606.     /// describe() helper: report a dep_set
  607.     static std::ostream& describe(std::ostream& out, const typename DepNode::dep_set& keys)
  608.     {
  609.         out << '(';
  610.         typename DepNode::dep_set::const_iterator ki(keys.begin()), kend(keys.end());
  611.         if (ki != kend)
  612.         {
  613.             LLDependencies_describe(out, *ki);
  614.             while (++ki != kend)
  615.             {
  616.                 out << ", ";
  617.                 LLDependencies_describe(out, *ki);
  618.             }
  619.         }
  620.         out << ')';
  621.         return out;
  622.     }
  623.     /// Iterator over the before/after KEYs on which a given NODE depends
  624.     typedef typename DepNode::dep_set::const_iterator dep_iterator;
  625.     /// range over the before/after KEYs on which a given NODE depends
  626.     typedef boost::iterator_range<dep_iterator> dep_range;
  627.     /// dependencies access from key
  628.     dep_range get_dep_range_from_key(const KEY& key, const dep_selector& selector) const
  629.     {
  630.         typename DepNodeMap::const_iterator found = mNodes.find(key);
  631.         if (found != mNodes.end())
  632.         {
  633.             return dep_range(selector(found->second));
  634.         }
  635.         // We want to return an empty range. On some platforms a default-
  636.         // constructed range (e.g. dep_range()) does NOT suffice! The client
  637.         // is likely to try to iterate from boost::begin(range) to
  638.         // boost::end(range); yet these iterators might not be valid. Instead
  639.         // return a range over a valid, empty container.
  640.         static const typename DepNode::dep_set empty_deps;
  641.         return dep_range(empty_deps.begin(), empty_deps.end());
  642.     }
  643.     /// dependencies access from any one of our key-order iterators
  644.     template<typename ITERATOR>
  645.     dep_range get_dep_range_from_xform(const ITERATOR& iterator, const dep_selector& selector) const
  646.     {
  647.         return dep_range(selector(iterator.base()->second));
  648.     }
  649.     /// dependencies access from sorted_iterator
  650.     dep_range get_dep_range_from_sorted(const sorted_iterator& sortiter,
  651.                                         const dep_selector& selector) const
  652.     {
  653.         // sorted_iterator is a boost::indirect_iterator wrapping an mCache
  654.         // iterator, which we can obtain by sortiter.base(). Deferencing that
  655.         // gets us an mCache entry, an 'iterator' -- one of our traversal
  656.         // iterators -- on which we can use get_dep_range_from_xform().
  657.         return get_dep_range_from_xform(*sortiter.base(), selector);
  658.     }
  659.     /**
  660.      * Get a range over the after KEYs stored for the passed KEY or iterator,
  661.      * in <i>arbitrary order.</i> If you pass a nonexistent KEY, returns empty
  662.      * range -- same as a KEY with no after KEYs. Detect existence of a KEY
  663.      * using get() instead.
  664.      */
  665.     template<typename KEY_OR_ITER>
  666.     dep_range get_after_range(const KEY_OR_ITER& key) const;
  667.     /**
  668.      * Get a range over the before KEYs stored for the passed KEY or iterator,
  669.      * in <i>arbitrary order.</i> If you pass a nonexistent KEY, returns empty
  670.      * range -- same as a KEY with no before KEYs. Detect existence of a KEY
  671.      * using get() instead.
  672.      */
  673.     template<typename KEY_OR_ITER>
  674.     dep_range get_before_range(const KEY_OR_ITER& key) const;
  675. private:
  676.     DepNodeMap mNodes;
  677.     mutable iterator_list mCache;
  678. };
  679. /**
  680.  * Functor to get a dep_range from a KEY or iterator -- generic case. If the
  681.  * passed value isn't one of our iterator specializations, assume it's
  682.  * convertible to the KEY type.
  683.  */
  684. template<typename KEY_ITER>
  685. struct LLDependencies_dep_range_from
  686. {
  687.     template<typename KEY, typename NODE, typename SELECTOR>
  688.     typename LLDependencies<KEY, NODE>::dep_range
  689.     operator()(const LLDependencies<KEY, NODE>& deps,
  690.                const KEY_ITER& key,
  691.                const SELECTOR& selector)
  692.     {
  693.         return deps.get_dep_range_from_key(key, selector);
  694.     }
  695. };
  696. /// Specialize LLDependencies_dep_range_from for our key-order iterators
  697. template<typename FUNCTION, typename ITERATOR>
  698. struct LLDependencies_dep_range_from< boost::transform_iterator<FUNCTION, ITERATOR> >
  699. {
  700.     template<typename KEY, typename NODE, typename SELECTOR>
  701.     typename LLDependencies<KEY, NODE>::dep_range
  702.     operator()(const LLDependencies<KEY, NODE>& deps,
  703.                const boost::transform_iterator<FUNCTION, ITERATOR>& iter,
  704.                const SELECTOR& selector)
  705.     {
  706.         return deps.get_dep_range_from_xform(iter, selector);
  707.     }
  708. };
  709. /// Specialize LLDependencies_dep_range_from for sorted_iterator
  710. template<typename BASEITER>
  711. struct LLDependencies_dep_range_from< boost::indirect_iterator<BASEITER> >
  712. {
  713.     template<typename KEY, typename NODE, typename SELECTOR>
  714.     typename LLDependencies<KEY, NODE>::dep_range
  715.     operator()(const LLDependencies<KEY, NODE>& deps,
  716.                const boost::indirect_iterator<BASEITER>& iter,
  717.                const SELECTOR& selector)
  718.     {
  719.         return deps.get_dep_range_from_sorted(iter, selector);
  720.     }
  721. };
  722. /// generic get_after_range() implementation
  723. template<typename KEY, typename NODE>
  724. template<typename KEY_OR_ITER>
  725. typename LLDependencies<KEY, NODE>::dep_range
  726. LLDependencies<KEY, NODE>::get_after_range(const KEY_OR_ITER& key_iter) const
  727. {
  728.     return LLDependencies_dep_range_from<KEY_OR_ITER>()(
  729.         *this,
  730.         key_iter,
  731.         boost::bind<const typename DepNode::dep_set&>(&DepNode::after, _1));
  732. }
  733. /// generic get_before_range() implementation
  734. template<typename KEY, typename NODE>
  735. template<typename KEY_OR_ITER>
  736. typename LLDependencies<KEY, NODE>::dep_range
  737. LLDependencies<KEY, NODE>::get_before_range(const KEY_OR_ITER& key_iter) const
  738. {
  739.     return LLDependencies_dep_range_from<KEY_OR_ITER>()(
  740.         *this,
  741.         key_iter,
  742.         boost::bind<const typename DepNode::dep_set&>(&DepNode::before, _1));
  743. }
  744. #endif /* ! defined(LL_LLDEPENDENCIES_H) */