summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Sustrik <sustrik@250bpm.com>2011-09-16 16:34:28 +0200
committerMartin Sustrik <sustrik@250bpm.com>2011-09-16 16:34:28 +0200
commite170136a2e00eec2e786441cdc090c3b00a8fbd4 (patch)
tree786ac67e14af4bfc3b5909b2db51935a4f68a206 /src
parent5936379b292dec79efd3a1eaa7cafae4fc6d675a (diff)
More bugs in mtrie fixed
Aside of fixing couple of corner cases this patch turns the 'match' function in mtrie from recursive to iterative. Signed-off-by: Martin Sustrik <sustrik@250bpm.com>
Diffstat (limited to 'src')
-rw-r--r--src/mtrie.cpp57
-rw-r--r--src/mtrie.hpp2
2 files changed, 30 insertions, 29 deletions
diff --git a/src/mtrie.cpp b/src/mtrie.cpp
index bb20df8..edff336 100644
--- a/src/mtrie.cpp
+++ b/src/mtrie.cpp
@@ -209,33 +209,36 @@ bool zmq::mtrie_t::rm_helper (unsigned char *prefix_, size_t size_,
void zmq::mtrie_t::match (unsigned char *data_, size_t size_,
void (*func_) (pipe_t *pipe_, void *arg_), void *arg_)
{
- match_helper (data_, size_, func_, arg_);
-}
-
-void zmq::mtrie_t::match_helper (unsigned char *data_, size_t size_,
- void (*func_) (pipe_t *pipe_, void *arg_), void *arg_)
-{
- // TODO: This function is on critical path. Rewrite it as iteration
- // rather than recursion.
-
- // Signal the pipes attached to this node.
- for (pipes_t::iterator it = pipes.begin (); it != pipes.end (); ++it)
- func_ (*it, arg_);
-
- // If there are no subnodes in the trie, return.
- if (count == 0)
- return;
-
- // If there's one subnode (optimisation).
- if (count == 1) {
- if (min == data_ [0])
- next.node->match_helper (data_ + 1, size_ - 1, func_, arg_);
- return;
+ mtrie_t *current = this;
+ while (size_) {
+
+ // Signal the pipes attached to this node.
+ for (pipes_t::iterator it = current->pipes.begin ();
+ it != current->pipes.end (); ++it)
+ func_ (*it, arg_);
+
+ // If there are no subnodes in the trie, return.
+ if (current->count == 0)
+ break;
+
+ // If there's one subnode (optimisation).
+ if (current->count == 1) {
+ if (data_ [0] != current->min)
+ break;
+ current = current->next.node;
+ data_++;
+ size_--;
+ continue;
+ }
+
+ // If there are multiple subnodes.
+ if (data_ [0] < min || data_ [0] >= min + count)
+ break;
+ if (!current->next.table [data_ [0] - min])
+ break;
+ current = current->next.table [data_ [0] - min];
+ data_++;
+ size_--;
}
-
- // If there are multiple subnodes.
- if (next.table [data_ [0] - min])
- next.table [data_ [0] - min]->match_helper (data_ + 1, size_ - 1,
- func_, arg_);
}
diff --git a/src/mtrie.hpp b/src/mtrie.hpp
index 68a3f2c..2c2cc32 100644
--- a/src/mtrie.hpp
+++ b/src/mtrie.hpp
@@ -67,8 +67,6 @@ namespace zmq
void *arg_);
bool rm_helper (unsigned char *prefix_, size_t size_,
class pipe_t *pipe_);
- void match_helper (unsigned char *data_, size_t size_,
- void (*func_) (class pipe_t *pipe_, void *arg_), void *arg_);
typedef std::set <class pipe_t*> pipes_t;
pipes_t pipes;