7373#include < tuple>
7474#include < unistd.h>
7575#include < unordered_map>
76+ #include < unordered_set>
7677#include < utility>
7778#include < variant>
7879#include < vector>
@@ -6513,9 +6514,21 @@ namespace li {
65136514
65146515namespace internal {
65156516
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+ }
65176525
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 } {}
65196532
65206533 struct iterator {
65216534 const drt_node<V>* ptr;
@@ -6540,17 +6553,10 @@ template <typename V> struct drt_node {
65406553 c++;
65416554 std::string_view k = r.substr (s, c - s);
65426555
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_);
65516558 }
6552-
6553- return v_;
6559+ return children_[k]->find_or_create (r, c);
65546560 }
65556561
65566562 template <typename F> void for_all_routes (F f, std::string prefix = " " ) const {
@@ -6559,8 +6565,8 @@ template <typename V> struct drt_node {
65596565 else {
65606566 if (prefix.size () && prefix.back () != ' /' )
65616567 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 ));
65646570 }
65656571 }
65666572
@@ -6597,7 +6603,7 @@ template <typename V> struct drt_node {
65976603
65986604 {
65996605 // if one child is a url param {{param_name}}, choose it
6600- for (auto & kv : children_) {
6606+ for (const auto & kv : children_) {
66016607 auto name = kv.first ;
66026608 if (name.size () > 4 and name[0 ] == ' {' and name[1 ] == ' {' and
66036609 name[name.size () - 2 ] == ' }' and name[name.size () - 1 ] == ' }' )
@@ -6609,22 +6615,22 @@ template <typename V> struct drt_node {
66096615
66106616 V v_;
66116617 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_ ;
66136619};
6614- } // namespace internal
66156620
6616- template <typename V> struct dynamic_routing_table {
6621+ template <typename V> struct dynamic_routing_table_impl {
6622+ dynamic_routing_table_impl () : root(pool) {}
66176623
66186624 // Find a route and return reference to a procedure.
66196625 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 );
66226628 return root.find_or_create (r2, 0 );
66236629 }
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 );
66286634 }
66296635
66306636 // Find a route and return an iterator.
@@ -6633,8 +6639,36 @@ template <typename V> struct dynamic_routing_table {
66336639 template <typename F> void for_all_routes (F f) const { root.for_all_routes (f); }
66346640 auto end () const { return root.end (); }
66356641
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_;
66386672};
66396673
66406674} // namespace li
0 commit comments