@@ -453,6 +453,8 @@ class TxGraphImpl final : public TxGraph
453
453
std::vector<Ref*> GetCluster (const Ref& arg, bool main_only = false ) noexcept final ;
454
454
std::vector<Ref*> GetAncestors (const Ref& arg, bool main_only = false ) noexcept final ;
455
455
std::vector<Ref*> GetDescendants (const Ref& arg, bool main_only = false ) noexcept final ;
456
+ std::vector<Ref*> GetAncestorsUnion (std::span<const Ref* const > args, bool main_only = false ) noexcept final ;
457
+ std::vector<Ref*> GetDescendantsUnion (std::span<const Ref* const > args, bool main_only = false ) noexcept final ;
456
458
GraphIndex GetTransactionCount (bool main_only = false ) noexcept final ;
457
459
bool IsOversized (bool main_only = false ) noexcept final ;
458
460
std::strong_ordering CompareMainOrder (const Ref& a, const Ref& b) noexcept final ;
@@ -1581,6 +1583,70 @@ std::vector<TxGraph::Ref*> TxGraphImpl::GetDescendants(const Ref& arg, bool main
1581
1583
return ret;
1582
1584
}
1583
1585
1586
+ std::vector<TxGraph::Ref*> TxGraphImpl::GetAncestorsUnion (std::span<const Ref* const > args, bool main_only) noexcept
1587
+ {
1588
+ // Apply all dependencies, as the result might be incorrect otherwise.
1589
+ size_t level = GetSpecifiedLevel (main_only);
1590
+ ApplyDependencies (level);
1591
+ // Ancestry cannot be known if unapplied dependencies remain.
1592
+ Assume (GetClusterSet (level).m_deps_to_add .empty ());
1593
+
1594
+ // Translate args to matches.
1595
+ std::vector<std::pair<Cluster*, DepGraphIndex>> matches;
1596
+ matches.reserve (args.size ());
1597
+ for (auto arg : args) {
1598
+ // Skip empty Refs.
1599
+ if (GetRefGraph (*arg) == nullptr ) continue ;
1600
+ Assume (GetRefGraph (*arg) == this );
1601
+ // Find the Cluster the argument is in, and skip if none is found.
1602
+ auto cluster = FindCluster (GetRefIndex (*arg), level);
1603
+ if (cluster == nullptr ) continue ;
1604
+ // Append to matches.
1605
+ matches.emplace_back (cluster, m_entries[GetRefIndex (*arg)].m_locator [cluster->m_level ].index );
1606
+ }
1607
+ // Group by Cluster.
1608
+ std::sort (matches.begin (), matches.end (), [](auto & a, auto & b) noexcept { return std::less{}(a.first , b.first ); });
1609
+ // Dispatch to the Clusters.
1610
+ std::span match_span (matches);
1611
+ std::vector<TxGraph::Ref*> ret;
1612
+ while (!match_span.empty ()) {
1613
+ match_span.front ().first ->GetAncestorRefs (*this , match_span, ret);
1614
+ }
1615
+ return ret;
1616
+ }
1617
+
1618
+ std::vector<TxGraph::Ref*> TxGraphImpl::GetDescendantsUnion (std::span<const Ref* const > args, bool main_only) noexcept
1619
+ {
1620
+ // Apply all dependencies, as the result might be incorrect otherwise.
1621
+ size_t level = GetSpecifiedLevel (main_only);
1622
+ ApplyDependencies (level);
1623
+ // Ancestry cannot be known if unapplied dependencies remain.
1624
+ Assume (GetClusterSet (level).m_deps_to_add .empty ());
1625
+
1626
+ // Translate args to matches.
1627
+ std::vector<std::pair<Cluster*, DepGraphIndex>> matches;
1628
+ matches.reserve (args.size ());
1629
+ for (auto arg : args) {
1630
+ // Skip empty Refs.
1631
+ if (GetRefGraph (*arg) == nullptr ) continue ;
1632
+ Assume (GetRefGraph (*arg) == this );
1633
+ // Find the Cluster the argument is in, and skip if none is found.
1634
+ auto cluster = FindCluster (GetRefIndex (*arg), level);
1635
+ if (cluster == nullptr ) continue ;
1636
+ // Append to matches.
1637
+ matches.emplace_back (cluster, m_entries[GetRefIndex (*arg)].m_locator [cluster->m_level ].index );
1638
+ }
1639
+ // Group by Cluster.
1640
+ std::sort (matches.begin (), matches.end (), [](auto & a, auto & b) noexcept { return std::less{}(a.first , b.first ); });
1641
+ // Dispatch to the Clusters.
1642
+ std::span match_span (matches);
1643
+ std::vector<TxGraph::Ref*> ret;
1644
+ while (!match_span.empty ()) {
1645
+ match_span.front ().first ->GetDescendantRefs (*this , match_span, ret);
1646
+ }
1647
+ return ret;
1648
+ }
1649
+
1584
1650
std::vector<TxGraph::Ref*> TxGraphImpl::GetCluster (const Ref& arg, bool main_only) noexcept
1585
1651
{
1586
1652
// Return the empty vector if the Ref is empty (which may be indicative of the transaction
0 commit comments