lldependencies.h 29 KB

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