control: rework handle allocation.
authorDavin McCall <davmac@davmac.org>
Sat, 10 Feb 2018 15:51:35 +0000 (15:51 +0000)
committerDavin McCall <davmac@davmac.org>
Sat, 10 Feb 2018 15:51:35 +0000 (15:51 +0000)
src/control.cc
src/includes/control.h

index fd89e20b987e11b5a1c8c5d4d71c9d168266a663..e285e2b7328f97cea2a2af70eaec149be2062423 100644 (file)
@@ -292,20 +292,16 @@ bool control_conn_t::list_services()
 
 control_conn_t::handle_t control_conn_t::allocate_service_handle(service_record *record)
 {
-    // Try to find a unique handle (integer) in a single pass. Start with 0, and keep track of the largest
-    // handle seen so far. If we find the current candidate, we set the candidate to (largest+1).
-    bool is_unique = true;
-    handle_t largest_seen = 0;
+    // Try to find a unique handle (integer) in a single pass. Since the map is ordered, we can search until
+    // we find a gap in the handle values.
     handle_t candidate = 0;
     for (auto p : keyServiceMap) {
-        if (p.first > largest_seen) largest_seen = p.first;
-        if (p.first == candidate) {
-            if (largest_seen == std::numeric_limits<handle_t>::max()) throw std::bad_alloc();
-            candidate = largest_seen + 1;
-        }
-        is_unique &= (p.second != record);
+        if (p.first == candidate) candidate++;
+        else break;
     }
 
+    bool is_unique = (serviceKeyMap.find(record) == serviceKeyMap.end());
+
     // The following operations perform allocation (can throw std::bad_alloc). If an exception occurs we
     // must undo any previous actions:
     if (is_unique) {
index dd922018e920819af2cbb63037e31c5a6070c42c..e2aa1df08c71f01df9ed868d7d99c398293cf4ad 100644 (file)
@@ -4,6 +4,7 @@
 #include <list>
 #include <vector>
 #include <unordered_map>
+#include <map>
 #include <limits>
 #include <cstddef>
 
@@ -104,7 +105,7 @@ class control_conn_t : private service_listener
     // in communction
     using handle_t = uint32_t;
     std::unordered_multimap<service_record *, handle_t> serviceKeyMap;
-    std::unordered_map<handle_t, service_record *> keyServiceMap;
+    std::map<handle_t, service_record *> keyServiceMap;
     
     // Buffer for outgoing packets. Each outgoing back is represented as a vector<char>.
     list<vector<char>> outbuf;