73
73
#include < tuple>
74
74
#include < unistd.h>
75
75
#include < unordered_map>
76
+ #include < unordered_set>
76
77
#include < utility>
77
78
#include < variant>
78
79
#include < vector>
@@ -6513,9 +6514,21 @@ namespace li {
6513
6514
6514
6515
namespace internal {
6515
6516
6516
- template <typename V> struct drt_node {
6517
+ // A simple memory pool for drt_node objects
6518
+ template <typename T> struct drt_node_pool {
6519
+ template <typename ... Args> T* allocate (Args&&... args) {
6520
+ auto new_node = std::make_unique<T>(std::forward<Args>(args)...);
6521
+ T* ptr = new_node.get ();
6522
+ pool_.emplace_back (std::move (new_node));
6523
+ return ptr;
6524
+ }
6517
6525
6518
- drt_node () : v_{0 , nullptr } {}
6526
+ std::vector<std::unique_ptr<T>> pool_;
6527
+ };
6528
+
6529
+ template <typename V> struct drt_node {
6530
+ drt_node () : pool_(nullptr ), v_{0 , nullptr } {}
6531
+ drt_node (drt_node_pool<drt_node>& pool) : pool_(pool), v_{0 , nullptr } {}
6519
6532
6520
6533
struct iterator {
6521
6534
const drt_node<V>* ptr;
@@ -6540,17 +6553,10 @@ template <typename V> struct drt_node {
6540
6553
c++;
6541
6554
std::string_view k = r.substr (s, c - s);
6542
6555
6543
- auto it = children_.find (k);
6544
- if (it != children_.end ())
6545
- return children_[k]->find_or_create (r, c);
6546
- else {
6547
- auto new_node = std::make_shared<drt_node>();
6548
- children_shared_pointers_.push_back (new_node);
6549
- children_.insert ({k, new_node.get ()});
6550
- return new_node->find_or_create (r, c);
6556
+ if (children_.find (k) == children_.end ()) {
6557
+ children_[k] = pool_.allocate (pool_);
6551
6558
}
6552
-
6553
- return v_;
6559
+ return children_[k]->find_or_create (r, c);
6554
6560
}
6555
6561
6556
6562
template <typename F> void for_all_routes (F f, std::string prefix = " " ) const {
@@ -6559,8 +6565,8 @@ template <typename V> struct drt_node {
6559
6565
else {
6560
6566
if (prefix.size () && prefix.back () != ' /' )
6561
6567
prefix += ' /' ;
6562
- for (auto pair : children_)
6563
- pair .second ->for_all_routes (f, prefix + std::string (pair .first ));
6568
+ for (const auto & kv : children_)
6569
+ kv .second ->for_all_routes (f, prefix + std::string (kv .first ));
6564
6570
}
6565
6571
}
6566
6572
@@ -6597,7 +6603,7 @@ template <typename V> struct drt_node {
6597
6603
6598
6604
{
6599
6605
// if one child is a url param {{param_name}}, choose it
6600
- for (auto & kv : children_) {
6606
+ for (const auto & kv : children_) {
6601
6607
auto name = kv.first ;
6602
6608
if (name.size () > 4 and name[0 ] == ' {' and name[1 ] == ' {' and
6603
6609
name[name.size () - 2 ] == ' }' and name[name.size () - 1 ] == ' }' )
@@ -6609,22 +6615,22 @@ template <typename V> struct drt_node {
6609
6615
6610
6616
V v_;
6611
6617
std::unordered_map<std::string_view, drt_node*> children_;
6612
- std::vector<std::shared_ptr< drt_node>> children_shared_pointers_ ;
6618
+ drt_node_pool< drt_node>& pool_ ;
6613
6619
};
6614
- } // namespace internal
6615
6620
6616
- template <typename V> struct dynamic_routing_table {
6621
+ template <typename V> struct dynamic_routing_table_impl {
6622
+ dynamic_routing_table_impl () : root(pool) {}
6617
6623
6618
6624
// Find a route and return reference to a procedure.
6619
6625
auto & operator [](const std::string_view& r) {
6620
- strings.push_back (std::make_shared<std:: string> (r));
6621
- std::string_view r2 (*strings. back () );
6626
+ auto [itr, is_inserted] = strings.emplace (std::string (r));
6627
+ std::string_view r2 (*itr );
6622
6628
return root.find_or_create (r2, 0 );
6623
6629
}
6624
- auto & operator [](const std::string& r ) {
6625
- strings.push_back (std::make_shared<std::string>(r) );
6626
- std::string_view r2 (*strings. back () );
6627
- return root.find_or_create (r2 , 0 );
6630
+ auto & operator [](const std::string& s ) {
6631
+ auto [itr, is_inserted] = strings.emplace (s );
6632
+ std::string_view r (*itr );
6633
+ return root.find_or_create (r , 0 );
6628
6634
}
6629
6635
6630
6636
// Find a route and return an iterator.
@@ -6633,8 +6639,36 @@ template <typename V> struct dynamic_routing_table {
6633
6639
template <typename F> void for_all_routes (F f) const { root.for_all_routes (f); }
6634
6640
auto end () const { return root.end (); }
6635
6641
6636
- std::vector<std::shared_ptr<std::string>> strings;
6637
- internal::drt_node<V> root;
6642
+ std::unordered_set<std::string> strings;
6643
+ drt_node_pool<drt_node<V>> pool;
6644
+ drt_node<V> root;
6645
+ };
6646
+ } // namespace internal
6647
+
6648
+ template <typename V> struct dynamic_routing_table {
6649
+ dynamic_routing_table () : impl_(std::make_shared<internal::dynamic_routing_table_impl<V>>()) {}
6650
+ dynamic_routing_table (const dynamic_routing_table& other) : impl_(other.impl_) {}
6651
+
6652
+ // Assignment operator
6653
+ dynamic_routing_table& operator =(const dynamic_routing_table& other) {
6654
+ if (this != &other) {
6655
+ impl_ = other.impl_ ;
6656
+ }
6657
+ return *this ;
6658
+ }
6659
+
6660
+ // Find a route and return reference to a procedure.
6661
+ auto & operator [](const std::string_view& r) { return impl_->operator [](r); }
6662
+ auto & operator [](const std::string& s) { return impl_->operator [](s); }
6663
+
6664
+ // Find a route and return an iterator.
6665
+ auto find (const std::string_view& r) const { return impl_->find (r); }
6666
+
6667
+ template <typename F> void for_all_routes (F f) const { impl_->for_all_routes (f); }
6668
+ auto end () const { return impl_->end (); }
6669
+
6670
+ private:
6671
+ std::shared_ptr<internal::dynamic_routing_table_impl<V>> impl_;
6638
6672
};
6639
6673
6640
6674
} // namespace li
0 commit comments