Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
L
libzmq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
libzmq
Commits
1186e986
Commit
1186e986
authored
Jun 28, 2019
by
Shubham Lagwankar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Problem: code doesn't follow libzmq naming conventions
Solution: rename types/variables that are inconsistent
parent
4a855fba
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
225 additions
and
223 deletions
+225
-223
benchmark_radix_tree.cpp
perf/benchmark_radix_tree.cpp
+9
-9
radix_tree.cpp
src/radix_tree.cpp
+149
-147
radix_tree.hpp
src/radix_tree.hpp
+38
-38
xsub.hpp
src/xsub.hpp
+1
-1
unittest_radix_tree.cpp
unittests/unittest_radix_tree.cpp
+28
-28
No files found.
perf/benchmark_radix_tree.cpp
View file @
1186e986
...
...
@@ -48,28 +48,28 @@ const char *chars = "abcdefghijklmnopqrstuvwxyz0123456789";
const
int
chars_len
=
36
;
template
<
class
T
>
void
benchmark_lookup
(
T
&
t
,
std
::
vector
<
unsigned
char
*>
&
input_set
,
std
::
vector
<
unsigned
char
*>
&
queries
)
void
benchmark_lookup
(
T
&
subscriptions_
,
std
::
vector
<
unsigned
char
*>
&
input_set
_
,
std
::
vector
<
unsigned
char
*>
&
queries
_
)
{
using
namespace
std
::
chrono
;
std
::
vector
<
duration
<
long
,
std
::
nano
>>
samples_vec
;
samples_vec
.
reserve
(
samples
);
for
(
std
::
size_t
run
=
0
;
run
<
warmup_runs
;
++
run
)
{
for
(
auto
&
query
:
queries
)
t
.
check
(
query
,
key_length
);
for
(
auto
&
query
:
queries
_
)
subscriptions_
.
check
(
query
,
key_length
);
}
for
(
std
::
size_t
run
=
0
;
run
<
samples
;
++
run
)
{
duration
<
long
,
std
::
nano
>
interval
(
0
);
for
(
auto
&
query
:
queries
)
{
for
(
auto
&
query
:
queries
_
)
{
auto
start
=
steady_clock
::
now
();
t
.
check
(
query
,
key_length
);
subscriptions_
.
check
(
query
,
key_length
);
auto
end
=
steady_clock
::
now
();
interval
+=
end
-
start
;
}
samples_vec
.
push_back
(
interval
/
queries
.
size
());
samples_vec
.
push_back
(
interval
/
queries
_
.
size
());
}
std
::
size_t
sum
=
0
;
...
...
@@ -102,7 +102,7 @@ int main ()
// Keeping initialization out of the benchmarking function helps
// heaptrack detect peak memory consumption of the radix tree.
zmq
::
trie_t
trie
;
zmq
::
radix_tree
radix_tree
;
zmq
::
radix_tree
_t
radix_tree
;
for
(
auto
&
key
:
input_set
)
{
trie
.
add
(
key
,
key_length
);
radix_tree
.
add
(
key
,
key_length
);
...
...
src/radix_tree.cpp
View file @
1186e986
...
...
@@ -36,54 +36,54 @@
#include <string.h>
#include <vector>
node_t
::
node_t
(
unsigned
char
*
data
)
:
data_
(
data
)
node_t
::
node_t
(
unsigned
char
*
data
_
)
:
_data
(
data_
)
{
}
uint32_t
node_t
::
refcount
()
{
uint32_t
u32
;
memcpy
(
&
u32
,
data_
,
sizeof
(
u32
));
memcpy
(
&
u32
,
_data
,
sizeof
(
u32
));
return
u32
;
}
void
node_t
::
set_refcount
(
uint32_t
value
)
void
node_t
::
set_refcount
(
uint32_t
value
_
)
{
memcpy
(
data_
,
&
value
,
sizeof
(
value
));
memcpy
(
_data
,
&
value_
,
sizeof
(
value_
));
}
uint32_t
node_t
::
prefix_length
()
{
uint32_t
u32
;
memcpy
(
&
u32
,
data_
+
sizeof
(
uint32_t
),
sizeof
(
u32
));
memcpy
(
&
u32
,
_data
+
sizeof
(
uint32_t
),
sizeof
(
u32
));
return
u32
;
}
void
node_t
::
set_prefix_length
(
uint32_t
value
)
void
node_t
::
set_prefix_length
(
uint32_t
value
_
)
{
memcpy
(
data_
+
sizeof
(
value
),
&
value
,
sizeof
(
value
));
memcpy
(
_data
+
sizeof
(
value_
),
&
value_
,
sizeof
(
value_
));
}
uint32_t
node_t
::
edgecount
()
{
uint32_t
u32
;
memcpy
(
&
u32
,
data_
+
2
*
sizeof
(
uint32_t
),
sizeof
(
u32
));
memcpy
(
&
u32
,
_data
+
2
*
sizeof
(
uint32_t
),
sizeof
(
u32
));
return
u32
;
}
void
node_t
::
set_edgecount
(
uint32_t
value
)
void
node_t
::
set_edgecount
(
uint32_t
value
_
)
{
memcpy
(
data_
+
2
*
sizeof
(
value
),
&
value
,
sizeof
(
value
));
memcpy
(
_data
+
2
*
sizeof
(
value_
),
&
value_
,
sizeof
(
value_
));
}
unsigned
char
*
node_t
::
prefix
()
{
return
data_
+
3
*
sizeof
(
uint32_t
);
return
_data
+
3
*
sizeof
(
uint32_t
);
}
void
node_t
::
set_prefix
(
const
unsigned
char
*
bytes
)
void
node_t
::
set_prefix
(
const
unsigned
char
*
bytes
_
)
{
memcpy
(
prefix
(),
bytes
,
prefix_length
());
memcpy
(
prefix
(),
bytes
_
,
prefix_length
());
}
unsigned
char
*
node_t
::
first_bytes
()
...
...
@@ -91,21 +91,21 @@ unsigned char *node_t::first_bytes ()
return
prefix
()
+
prefix_length
();
}
void
node_t
::
set_first_bytes
(
const
unsigned
char
*
bytes
)
void
node_t
::
set_first_bytes
(
const
unsigned
char
*
bytes
_
)
{
memcpy
(
first_bytes
(),
bytes
,
edgecount
());
memcpy
(
first_bytes
(),
bytes
_
,
edgecount
());
}
unsigned
char
node_t
::
first_byte_at
(
size_t
index
)
unsigned
char
node_t
::
first_byte_at
(
size_t
index
_
)
{
zmq_assert
(
index
<
edgecount
());
return
first_bytes
()[
index
];
zmq_assert
(
index
_
<
edgecount
());
return
first_bytes
()[
index
_
];
}
void
node_t
::
set_first_byte_at
(
size_t
index
,
unsigned
char
byte
)
void
node_t
::
set_first_byte_at
(
size_t
index
_
,
unsigned
char
byte_
)
{
zmq_assert
(
index
<
edgecount
());
first_bytes
()[
index
]
=
byte
;
zmq_assert
(
index
_
<
edgecount
());
first_bytes
()[
index
_
]
=
byte_
;
}
unsigned
char
*
node_t
::
node_pointers
()
...
...
@@ -113,113 +113,115 @@ unsigned char *node_t::node_pointers ()
return
prefix
()
+
prefix_length
()
+
edgecount
();
}
void
node_t
::
set_node_pointers
(
const
unsigned
char
*
pointers
)
void
node_t
::
set_node_pointers
(
const
unsigned
char
*
pointers
_
)
{
memcpy
(
node_pointers
(),
pointers
,
edgecount
()
*
sizeof
(
void
*
));
memcpy
(
node_pointers
(),
pointers
_
,
edgecount
()
*
sizeof
(
void
*
));
}
node_t
node_t
::
node_at
(
size_t
index
)
node_t
node_t
::
node_at
(
size_t
index
_
)
{
zmq_assert
(
index
<
edgecount
());
zmq_assert
(
index
_
<
edgecount
());
unsigned
char
*
data
;
memcpy
(
&
data
,
node_pointers
()
+
index
*
sizeof
(
void
*
),
sizeof
(
data
));
memcpy
(
&
data
,
node_pointers
()
+
index
_
*
sizeof
(
void
*
),
sizeof
(
data
));
return
node_t
(
data
);
}
void
node_t
::
set_node_at
(
size_t
index
,
node_t
node
)
void
node_t
::
set_node_at
(
size_t
index
_
,
node_t
node_
)
{
zmq_assert
(
index
<
edgecount
());
memcpy
(
node_pointers
()
+
index
*
sizeof
(
void
*
),
&
node
.
data_
,
sizeof
(
node
.
data_
));
zmq_assert
(
index
_
<
edgecount
());
memcpy
(
node_pointers
()
+
index
_
*
sizeof
(
void
*
),
&
node_
.
_data
,
sizeof
(
node
_
.
_data
));
}
void
node_t
::
set_edge_at
(
size_t
index
,
unsigned
char
first_byte
,
node_t
node
)
void
node_t
::
set_edge_at
(
size_t
index_
,
unsigned
char
first_byte_
,
node_t
node_
)
{
set_first_byte_at
(
index
,
first_byte
);
set_node_at
(
index
,
node
);
set_first_byte_at
(
index
_
,
first_byte_
);
set_node_at
(
index
_
,
node_
);
}
bool
node_t
::
operator
==
(
node_t
other
)
const
bool
node_t
::
operator
==
(
node_t
other
_
)
const
{
return
data_
==
other
.
data_
;
return
_data
==
other_
.
_data
;
}
bool
node_t
::
operator
!=
(
node_t
other
)
const
bool
node_t
::
operator
!=
(
node_t
other
_
)
const
{
return
!
(
*
this
==
other
);
return
!
(
*
this
==
other
_
);
}
void
node_t
::
resize
(
size_t
prefix_length
,
size_t
edgecount
)
void
node_t
::
resize
(
size_t
prefix_length
_
,
size_t
edgecount_
)
{
size_t
node_size
=
3
*
sizeof
(
uint32_t
)
+
prefix_length
+
edgecount
*
(
1
+
sizeof
(
void
*
));
size_t
node_size
=
3
*
sizeof
(
uint32_t
)
+
prefix_length_
+
edgecount_
*
(
1
+
sizeof
(
void
*
));
unsigned
char
*
new_data
=
static_cast
<
unsigned
char
*>
(
realloc
(
data_
,
node_size
));
static_cast
<
unsigned
char
*>
(
realloc
(
_data
,
node_size
));
zmq_assert
(
new_data
);
data_
=
new_data
;
set_prefix_length
(
static_cast
<
uint32_t
>
(
prefix_length
));
set_edgecount
(
static_cast
<
uint32_t
>
(
edgecount
));
_data
=
new_data
;
set_prefix_length
(
static_cast
<
uint32_t
>
(
prefix_length
_
));
set_edgecount
(
static_cast
<
uint32_t
>
(
edgecount
_
));
}
node_t
make_node
(
size_t
refcount
,
size_t
prefix_length
,
size_t
edgecount
)
node_t
make_node
(
size_t
refcount
_
,
size_t
prefix_length_
,
size_t
edgecount_
)
{
size_t
node_size
=
3
*
sizeof
(
uint32_t
)
+
prefix_length
+
edgecount
*
(
1
+
sizeof
(
void
*
));
size_t
node_size
=
3
*
sizeof
(
uint32_t
)
+
prefix_length_
+
edgecount_
*
(
1
+
sizeof
(
void
*
));
unsigned
char
*
data
=
static_cast
<
unsigned
char
*>
(
malloc
(
node_size
));
zmq_assert
(
data
);
node_t
node
(
data
);
node
.
set_refcount
(
static_cast
<
uint32_t
>
(
refcount
));
node
.
set_prefix_length
(
static_cast
<
uint32_t
>
(
prefix_length
));
node
.
set_edgecount
(
static_cast
<
uint32_t
>
(
edgecount
));
node
.
set_refcount
(
static_cast
<
uint32_t
>
(
refcount
_
));
node
.
set_prefix_length
(
static_cast
<
uint32_t
>
(
prefix_length
_
));
node
.
set_edgecount
(
static_cast
<
uint32_t
>
(
edgecount
_
));
return
node
;
}
// ----------------------------------------------------------------------
zmq
::
radix_tree
::
radix_tree
()
:
root_
(
make_node
(
0
,
0
,
0
)),
size_
(
0
)
zmq
::
radix_tree
_t
::
radix_tree_t
()
:
_root
(
make_node
(
0
,
0
,
0
)),
_size
(
0
)
{
}
static
void
free_nodes
(
node_t
node
)
static
void
free_nodes
(
node_t
node
_
)
{
for
(
size_t
i
=
0
;
i
<
node
.
edgecount
();
++
i
)
free_nodes
(
node
.
node_at
(
i
));
free
(
node
.
data_
);
for
(
size_t
i
=
0
;
i
<
node
_
.
edgecount
();
++
i
)
free_nodes
(
node
_
.
node_at
(
i
));
free
(
node
_
.
_data
);
}
zmq
::
radix_tree
::~
radix_tree
()
zmq
::
radix_tree
_t
::~
radix_tree_t
()
{
free_nodes
(
root_
);
free_nodes
(
_root
);
}
match_result_t
::
match_result_t
(
size_t
key_bytes_matched
,
size_t
prefix_bytes_matched
,
size_t
edge_index
,
size_t
parent_edge_index
,
node_t
current
,
node_t
parent
,
node_t
grandparent
)
:
key_bytes_matched
(
key_bytes_matched
),
prefix_bytes_matched
(
prefix_bytes_matched
),
edge_index
(
edge_index
),
parent_edge_index
(
parent_edge_index
),
current_node
(
current
),
parent_node
(
parent
),
grandparent_node
(
grandparent
)
match_result_t
::
match_result_t
(
size_t
key_bytes_matched
_
,
size_t
prefix_bytes_matched
_
,
size_t
edge_index
_
,
size_t
parent_edge_index
_
,
node_t
current
_
,
node_t
parent
_
,
node_t
grandparent
_
)
:
_key_bytes_matched
(
key_bytes_matched_
),
_prefix_bytes_matched
(
prefix_bytes_matched_
),
_edge_index
(
edge_index_
),
_parent_edge_index
(
parent_edge_index_
),
_current_node
(
current_
),
_parent_node
(
parent_
),
_grandparent_node
(
grandparent_
)
{
}
match_result_t
zmq
::
radix_tree
::
match
(
const
unsigned
char
*
key
,
size_t
key_size
,
bool
is_lookup
=
false
)
const
match_result_t
zmq
::
radix_tree
_t
::
match
(
const
unsigned
char
*
key_
,
size_t
key_size_
,
bool
is_lookup_
=
false
)
const
{
zmq_assert
(
key
);
zmq_assert
(
key
_
);
// Node we're currently at in the traversal and its predecessors.
node_t
current_node
=
root_
;
node_t
current_node
=
_root
;
node_t
parent_node
=
current_node
;
node_t
grandparent_node
=
current_node
;
// Index of the next byte to match in the key.
...
...
@@ -234,32 +236,32 @@ match_result_t zmq::radix_tree::match (const unsigned char *key,
while
(
current_node
.
prefix_length
()
>
0
||
current_node
.
edgecount
()
>
0
)
{
for
(
prefix_byte_index
=
0
;
prefix_byte_index
<
current_node
.
prefix_length
()
&&
key_byte_index
<
key_size
;
&&
key_byte_index
<
key_size
_
;
++
prefix_byte_index
,
++
key_byte_index
)
{
if
(
current_node
.
prefix
()[
prefix_byte_index
]
!=
key
[
key_byte_index
])
!=
key
_
[
key_byte_index
])
break
;
}
// Even if a prefix of the key matches and we're doing a
// lookup, this means we've found a matching subscription.
if
(
is_lookup
&&
prefix_byte_index
==
current_node
.
prefix_length
()
if
(
is_lookup
_
&&
prefix_byte_index
==
current_node
.
prefix_length
()
&&
current_node
.
refcount
()
>
0
)
{
key_byte_index
=
key_size
;
key_byte_index
=
key_size
_
;
break
;
}
// There was a mismatch or we've matched the whole key, so
// there's nothing more to do.
if
(
prefix_byte_index
!=
current_node
.
prefix_length
()
||
key_byte_index
==
key_size
)
||
key_byte_index
==
key_size
_
)
break
;
// We need to match the rest of the key. Check if there's an
// outgoing edge from this node.
node_t
next_node
=
current_node
;
for
(
size_t
i
=
0
;
i
<
current_node
.
edgecount
();
++
i
)
{
if
(
current_node
.
first_byte_at
(
i
)
==
key
[
key_byte_index
])
{
if
(
current_node
.
first_byte_at
(
i
)
==
key
_
[
key_byte_index
])
{
parent_edge_index
=
edge_index
;
edge_index
=
i
;
next_node
=
current_node
.
node_at
(
i
);
...
...
@@ -279,24 +281,24 @@ match_result_t zmq::radix_tree::match (const unsigned char *key,
grandparent_node
);
}
bool
zmq
::
radix_tree
::
add
(
const
unsigned
char
*
key
,
size_t
key_size
)
bool
zmq
::
radix_tree
_t
::
add
(
const
unsigned
char
*
key_
,
size_t
key_size_
)
{
match_result_t
match_result
=
match
(
key
,
key_size
);
size_t
key_bytes_matched
=
match_result
.
key_bytes_matched
;
size_t
prefix_bytes_matched
=
match_result
.
prefix_bytes_matched
;
size_t
edge_index
=
match_result
.
edge_index
;
node_t
current_node
=
match_result
.
current_node
;
node_t
parent_node
=
match_result
.
parent_node
;
match_result_t
match_result
=
match
(
key
_
,
key_size_
);
size_t
key_bytes_matched
=
match_result
.
_
key_bytes_matched
;
size_t
prefix_bytes_matched
=
match_result
.
_
prefix_bytes_matched
;
size_t
edge_index
=
match_result
.
_
edge_index
;
node_t
current_node
=
match_result
.
_
current_node
;
node_t
parent_node
=
match_result
.
_
parent_node
;
if
(
key_bytes_matched
!=
key_size
)
{
if
(
key_bytes_matched
!=
key_size
_
)
{
// Not all characters match, we might have to split the node.
if
(
key_bytes_matched
==
0
||
prefix_bytes_matched
==
current_node
.
prefix_length
())
{
// The mismatch is at one of the outgoing edges, so we
// create an edge from the current node to a new leaf node
// that has the rest of the key as the prefix.
node_t
key_node
=
make_node
(
1
,
key_size
-
key_bytes_matched
,
0
);
key_node
.
set_prefix
(
key
+
key_bytes_matched
);
node_t
key_node
=
make_node
(
1
,
key_size
_
-
key_bytes_matched
,
0
);
key_node
.
set_prefix
(
key
_
+
key_bytes_matched
);
// Reallocate for one more edge.
current_node
.
resize
(
current_node
.
prefix_length
(),
...
...
@@ -315,15 +317,15 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t key_size)
// Add an edge to the new node.
current_node
.
set_edge_at
(
current_node
.
edgecount
()
-
1
,
key
[
key_bytes_matched
],
key_node
);
key
_
[
key_bytes_matched
],
key_node
);
// We need to update all pointers to the current node
// after the call to resize().
if
(
current_node
.
prefix_length
()
==
0
)
root_
.
data_
=
current_node
.
data_
;
_root
.
_data
=
current_node
.
_data
;
else
parent_node
.
set_node_at
(
edge_index
,
current_node
);
++
size_
;
++
_size
;
return
true
;
}
...
...
@@ -333,14 +335,14 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t key_size)
// One node will have the rest of the characters from the key,
// and the other node will have the rest of the characters
// from the current node's prefix.
node_t
key_node
=
make_node
(
1
,
key_size
-
key_bytes_matched
,
0
);
node_t
key_node
=
make_node
(
1
,
key_size
_
-
key_bytes_matched
,
0
);
node_t
split_node
=
make_node
(
current_node
.
refcount
(),
current_node
.
prefix_length
()
-
prefix_bytes_matched
,
current_node
.
edgecount
());
// Copy the prefix chunks to the new nodes.
key_node
.
set_prefix
(
key
+
key_bytes_matched
);
key_node
.
set_prefix
(
key
_
+
key_bytes_matched
);
split_node
.
set_prefix
(
current_node
.
prefix
()
+
prefix_bytes_matched
);
// Copy the current node's edges to the new node.
...
...
@@ -359,7 +361,7 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t key_size)
current_node
.
set_edge_at
(
0
,
key_node
.
prefix
()[
0
],
key_node
);
current_node
.
set_edge_at
(
1
,
split_node
.
prefix
()[
0
],
split_node
);
++
size_
;
++
_size
;
parent_node
.
set_node_at
(
edge_index
,
current_node
);
return
true
;
}
...
...
@@ -391,42 +393,42 @@ bool zmq::radix_tree::add (const unsigned char *key, size_t key_size)
current_node
.
set_edge_at
(
0
,
split_node
.
prefix
()[
0
],
split_node
);
current_node
.
set_refcount
(
1
);
++
size_
;
++
_size
;
parent_node
.
set_node_at
(
edge_index
,
current_node
);
return
true
;
}
zmq_assert
(
key_bytes_matched
==
key_size
);
zmq_assert
(
key_bytes_matched
==
key_size
_
);
zmq_assert
(
prefix_bytes_matched
==
current_node
.
prefix_length
());
++
size_
;
++
_size
;
current_node
.
set_refcount
(
current_node
.
refcount
()
+
1
);
return
current_node
.
refcount
()
==
1
;
}
bool
zmq
::
radix_tree
::
rm
(
const
unsigned
char
*
key
,
size_t
key_size
)
bool
zmq
::
radix_tree
_t
::
rm
(
const
unsigned
char
*
key_
,
size_t
key_size_
)
{
match_result_t
match_result
=
match
(
key
,
key_size
);
size_t
key_bytes_matched
=
match_result
.
key_bytes_matched
;
size_t
prefix_bytes_matched
=
match_result
.
prefix_bytes_matched
;
size_t
edge_index
=
match_result
.
edge_index
;
size_t
parent_edge_index
=
match_result
.
parent_edge_index
;
node_t
current_node
=
match_result
.
current_node
;
node_t
parent_node
=
match_result
.
parent_node
;
node_t
grandparent_node
=
match_result
.
grandparent_node
;
match_result_t
match_result
=
match
(
key
_
,
key_size_
);
size_t
key_bytes_matched
=
match_result
.
_
key_bytes_matched
;
size_t
prefix_bytes_matched
=
match_result
.
_
prefix_bytes_matched
;
size_t
edge_index
=
match_result
.
_
edge_index
;
size_t
parent_edge_index
=
match_result
.
_
parent_edge_index
;
node_t
current_node
=
match_result
.
_
current_node
;
node_t
parent_node
=
match_result
.
_
parent_node
;
node_t
grandparent_node
=
match_result
.
_
grandparent_node
;
if
(
key_bytes_matched
!=
key_size
if
(
key_bytes_matched
!=
key_size
_
||
prefix_bytes_matched
!=
current_node
.
prefix_length
()
||
current_node
.
refcount
()
==
0
)
return
false
;
current_node
.
set_refcount
(
current_node
.
refcount
()
-
1
);
--
size_
;
--
_size
;
if
(
current_node
.
refcount
()
>
0
)
return
false
;
// Don't delete the root node.
if
(
current_node
==
root_
)
if
(
current_node
==
_root
)
return
true
;
size_t
outgoing_edges
=
current_node
.
edgecount
();
...
...
@@ -455,13 +457,13 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t key_size)
current_node
.
set_node_pointers
(
child
.
node_pointers
());
current_node
.
set_refcount
(
child
.
refcount
());
free
(
child
.
data_
);
free
(
child
.
_data
);
parent_node
.
set_node_at
(
edge_index
,
current_node
);
return
true
;
}
if
(
parent_node
.
edgecount
()
==
2
&&
parent_node
.
refcount
()
==
0
&&
parent_node
!=
root_
)
{
&&
parent_node
!=
_root
)
{
// Removing this node leaves the parent with one child.
// If the parent doesn't hold a key or if it isn't the root,
// we can merge it with its single child node.
...
...
@@ -484,8 +486,8 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t key_size)
parent_node
.
set_node_pointers
(
other_child
.
node_pointers
());
parent_node
.
set_refcount
(
other_child
.
refcount
());
free
(
current_node
.
data_
);
free
(
other_child
.
data_
);
free
(
current_node
.
_data
);
free
(
other_child
.
_data
);
grandparent_node
.
set_node_at
(
parent_edge_index
,
parent_node
);
return
true
;
}
...
...
@@ -515,59 +517,59 @@ bool zmq::radix_tree::rm (const unsigned char *key, size_t key_size)
parent_node
.
edgecount
()
-
1
);
// Nothing points to this node now, so we can reclaim it.
free
(
current_node
.
data_
);
free
(
current_node
.
_data
);
if
(
parent_node
.
prefix_length
()
==
0
)
root_
.
data_
=
parent_node
.
data_
;
_root
.
_data
=
parent_node
.
_data
;
else
grandparent_node
.
set_node_at
(
parent_edge_index
,
parent_node
);
return
true
;
}
bool
zmq
::
radix_tree
::
check
(
const
unsigned
char
*
key
,
size_t
key_size
)
bool
zmq
::
radix_tree
_t
::
check
(
const
unsigned
char
*
key_
,
size_t
key_size_
)
{
if
(
root_
.
refcount
()
>
0
)
if
(
_root
.
refcount
()
>
0
)
return
true
;
match_result_t
match_result
=
match
(
key
,
key_size
,
true
);
return
match_result
.
key_bytes_matched
==
key_size
&&
match_result
.
prefix_bytes_matched
==
match_result
.
current_node
.
prefix_length
()
&&
match_result
.
current_node
.
refcount
()
>
0
;
match_result_t
match_result
=
match
(
key
_
,
key_size_
,
true
);
return
match_result
.
_key_bytes_matched
==
key_size_
&&
match_result
.
_
prefix_bytes_matched
==
match_result
.
_
current_node
.
prefix_length
()
&&
match_result
.
_
current_node
.
refcount
()
>
0
;
}
static
void
visit_keys
(
node_t
node
,
std
::
vector
<
unsigned
char
>
&
buffer
,
void
(
*
func
)
(
unsigned
char
*
data
,
size_t
size
,
void
*
arg
),
void
*
arg
)
visit_keys
(
node_t
node
_
,
std
::
vector
<
unsigned
char
>
&
buffer
_
,
void
(
*
func
_
)
(
unsigned
char
*
data
,
size_t
size
,
void
*
arg
),
void
*
arg
_
)
{
for
(
size_t
i
=
0
;
i
<
node
.
prefix_length
();
++
i
)
buffer
.
push_back
(
node
.
prefix
()[
i
]);
for
(
size_t
i
=
0
;
i
<
node
_
.
prefix_length
();
++
i
)
buffer
_
.
push_back
(
node_
.
prefix
()[
i
]);
if
(
node
.
refcount
()
>
0
)
{
zmq_assert
(
!
buffer
.
empty
());
func
(
&
buffer
[
0
],
buffer
.
size
(),
arg
);
if
(
node
_
.
refcount
()
>
0
)
{
zmq_assert
(
!
buffer
_
.
empty
());
func
_
(
&
buffer_
[
0
],
buffer_
.
size
(),
arg_
);
}
for
(
size_t
i
=
0
;
i
<
node
.
edgecount
();
++
i
)
visit_keys
(
node
.
node_at
(
i
),
buffer
,
func
,
arg
);
for
(
size_t
i
=
0
;
i
<
node
.
prefix_length
();
++
i
)
buffer
.
pop_back
();
for
(
size_t
i
=
0
;
i
<
node
_
.
edgecount
();
++
i
)
visit_keys
(
node
_
.
node_at
(
i
),
buffer_
,
func_
,
arg_
);
for
(
size_t
i
=
0
;
i
<
node
_
.
prefix_length
();
++
i
)
buffer
_
.
pop_back
();
}
void
zmq
::
radix_tree
::
apply
(
void
(
*
func
)
(
unsigned
char
*
data
,
size_t
size
,
void
*
arg
),
void
*
arg
)
void
zmq
::
radix_tree
_t
::
apply
(
void
(
*
func
_
)
(
unsigned
char
*
data
,
size_t
size
,
void
*
arg
),
void
*
arg_
)
{
if
(
root_
.
refcount
()
>
0
)
func
(
NULL
,
0
,
arg
);
// Root node is always empty.
if
(
_root
.
refcount
()
>
0
)
func
_
(
NULL
,
0
,
arg_
);
// Root node is always empty.
std
::
vector
<
unsigned
char
>
buffer
;
for
(
size_t
i
=
0
;
i
<
root_
.
edgecount
();
++
i
)
visit_keys
(
root_
.
node_at
(
i
),
buffer
,
func
,
arg
);
for
(
size_t
i
=
0
;
i
<
_root
.
edgecount
();
++
i
)
visit_keys
(
_root
.
node_at
(
i
),
buffer
,
func_
,
arg_
);
}
size_t
zmq
::
radix_tree
::
size
()
const
size_t
zmq
::
radix_tree
_t
::
size
()
const
{
return
size_
;
return
_size
;
}
src/radix_tree.hpp
View file @
1186e986
...
...
@@ -62,62 +62,62 @@
// of the chunk of first bytes and node pointers respectively.
struct
node_t
{
unsigned
char
*
data_
;
explicit
node_t
(
unsigned
char
*
data_
)
;
explicit
node_t
(
unsigned
char
*
data
);
bool
operator
==
(
node_t
other
)
const
;
bool
operator
!=
(
node_t
other
)
const
;
bool
operator
==
(
node_t
other_
)
const
;
bool
operator
!=
(
node_t
other_
)
const
;
inline
uint32_t
refcount
();
inline
uint32_t
prefix_length
();
inline
uint32_t
edgecount
();
inline
unsigned
char
*
prefix
();
inline
unsigned
char
*
first_bytes
();
inline
unsigned
char
first_byte_at
(
size_t
index
);
inline
unsigned
char
first_byte_at
(
size_t
index
_
);
inline
unsigned
char
*
node_pointers
();
inline
node_t
node_at
(
size_t
index
);
inline
void
set_refcount
(
uint32_t
value
);
inline
void
set_prefix_length
(
uint32_t
value
);
inline
void
set_edgecount
(
uint32_t
value
);
inline
void
set_prefix
(
const
unsigned
char
*
prefix
);
inline
void
set_first_bytes
(
const
unsigned
char
*
bytes
);
inline
void
set_first_byte_at
(
size_t
index
,
unsigned
char
byte
);
inline
void
set_node_pointers
(
const
unsigned
char
*
pointers
);
inline
void
set_node_at
(
size_t
index
,
node_t
node
);
inline
node_t
node_at
(
size_t
index
_
);
inline
void
set_refcount
(
uint32_t
value
_
);
inline
void
set_prefix_length
(
uint32_t
value
_
);
inline
void
set_edgecount
(
uint32_t
value
_
);
inline
void
set_prefix
(
const
unsigned
char
*
prefix
_
);
inline
void
set_first_bytes
(
const
unsigned
char
*
bytes
_
);
inline
void
set_first_byte_at
(
size_t
index
_
,
unsigned
char
byte_
);
inline
void
set_node_pointers
(
const
unsigned
char
*
pointers
_
);
inline
void
set_node_at
(
size_t
index
_
,
node_t
node_
);
inline
void
set_edge_at
(
size_t
index
,
unsigned
char
first_byte
,
node_t
node
);
void
resize
(
size_t
prefix_length
,
size_t
edgecount
);
set_edge_at
(
size_t
index_
,
unsigned
char
first_byte_
,
node_t
node_
);
void
resize
(
size_t
prefix_length_
,
size_t
edgecount_
);
unsigned
char
*
_data
;
};
node_t
make_node
(
size_t
refcount
,
size_t
prefix_length
,
size_t
edgecount
);
node_t
make_node
(
size_t
refcount
_
,
size_t
prefix_length_
,
size_t
edgecount_
);
struct
match_result_t
{
size_t
key_bytes_matched
;
size_t
prefix_bytes_matched
;
size_t
edge_index
;
size_t
parent_edge_index
;
node_t
current_node
;
node_t
parent_node
;
node_t
grandparent_node
;
match_result_t
(
size_t
key_bytes_matched
,
size_t
prefix_bytes_matched
,
size_t
edge_index
,
size_t
parent_edge_index
,
node_t
current
,
node_t
parent
,
match_result_t
(
size_t
key_bytes_matched_
,
size_t
prefix_bytes_matched_
,
size_t
edge_index_
,
size_t
parent_edge_index_
,
node_t
current_
,
node_t
parent_
,
node_t
grandparent
);
size_t
_key_bytes_matched
;
size_t
_prefix_bytes_matched
;
size_t
_edge_index
;
size_t
_parent_edge_index
;
node_t
_current_node
;
node_t
_parent_node
;
node_t
_grandparent_node
;
};
namespace
zmq
{
class
radix_tree
class
radix_tree
_t
{
public
:
radix_tree
();
~
radix_tree
();
radix_tree
_t
();
~
radix_tree
_t
();
// Add key to the tree. Returns true if this was a new key rather
// than a duplicate.
...
...
@@ -138,10 +138,10 @@ class radix_tree
private
:
inline
match_result_t
match
(
const
unsigned
char
*
key
,
size_t
key_size
,
bool
is_lookup
)
const
;
match
(
const
unsigned
char
*
key
_
,
size_t
key_size_
,
bool
is_lookup_
)
const
;
node_t
root_
;
size_t
size_
;
node_t
_root
;
size_t
_size
;
};
}
...
...
src/xsub.hpp
View file @
1186e986
...
...
@@ -83,7 +83,7 @@ class xsub_t : public socket_base_t
// The repository of subscriptions.
#ifdef ZMQ_USE_RADIX_TREE
radix_tree
_subscriptions
;
radix_tree
_t
_subscriptions
;
#else
trie_t
_subscriptions
;
#endif
...
...
unittests/unittest_radix_tree.cpp
View file @
1186e986
...
...
@@ -35,41 +35,41 @@ void tearDown ()
{
}
bool
tree_add
(
zmq
::
radix_tree
&
tree
,
const
std
::
string
&
key
)
bool
tree_add
(
zmq
::
radix_tree
_t
&
tree_
,
const
std
::
string
&
key_
)
{
return
tree
.
add
(
reinterpret_cast
<
const
unsigned
char
*>
(
key
.
data
()),
key
.
size
());
return
tree
_
.
add
(
reinterpret_cast
<
const
unsigned
char
*>
(
key_
.
data
()),
key_
.
size
());
}
bool
tree_rm
(
zmq
::
radix_tree
&
tree
,
const
std
::
string
&
key
)
bool
tree_rm
(
zmq
::
radix_tree
_t
&
tree_
,
const
std
::
string
&
key_
)
{
return
tree
.
rm
(
reinterpret_cast
<
const
unsigned
char
*>
(
key
.
data
()),
key
.
size
());
return
tree
_
.
rm
(
reinterpret_cast
<
const
unsigned
char
*>
(
key_
.
data
()),
key_
.
size
());
}
bool
tree_check
(
zmq
::
radix_tree
&
tree
,
const
std
::
string
&
key
)
bool
tree_check
(
zmq
::
radix_tree
_t
&
tree_
,
const
std
::
string
&
key_
)
{
return
tree
.
check
(
reinterpret_cast
<
const
unsigned
char
*>
(
key
.
data
()),
key
.
size
());
return
tree
_
.
check
(
reinterpret_cast
<
const
unsigned
char
*>
(
key_
.
data
()),
key_
.
size
());
}
void
test_empty
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
TEST_ASSERT_TRUE
(
tree
.
size
()
==
0
);
}
void
test_add_single_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
TEST_ASSERT_TRUE
(
tree_add
(
tree
,
"foo"
));
}
void
test_add_same_entry_twice
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
TEST_ASSERT_TRUE
(
tree_add
(
tree
,
"test"
));
TEST_ASSERT_FALSE
(
tree_add
(
tree
,
"test"
));
...
...
@@ -77,14 +77,14 @@ void test_add_same_entry_twice ()
void
test_rm_when_empty
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
TEST_ASSERT_FALSE
(
tree_rm
(
tree
,
"test"
));
}
void
test_rm_single_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"temporary"
);
TEST_ASSERT_TRUE
(
tree_rm
(
tree
,
"temporary"
));
...
...
@@ -92,7 +92,7 @@ void test_rm_single_entry ()
void
test_rm_unique_entry_twice
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"test"
);
TEST_ASSERT_TRUE
(
tree_rm
(
tree
,
"test"
));
...
...
@@ -101,7 +101,7 @@ void test_rm_unique_entry_twice ()
void
test_rm_duplicate_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"test"
);
tree_add
(
tree
,
"test"
);
...
...
@@ -111,7 +111,7 @@ void test_rm_duplicate_entry ()
void
test_rm_common_prefix
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"checkpoint"
);
tree_add
(
tree
,
"checklist"
);
...
...
@@ -120,7 +120,7 @@ void test_rm_common_prefix ()
void
test_rm_common_prefix_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"checkpoint"
);
tree_add
(
tree
,
"checklist"
);
...
...
@@ -130,7 +130,7 @@ void test_rm_common_prefix_entry ()
void
test_rm_null_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
""
);
TEST_ASSERT_TRUE
(
tree_rm
(
tree
,
""
));
...
...
@@ -138,14 +138,14 @@ void test_rm_null_entry ()
void
test_check_empty
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
TEST_ASSERT_FALSE
(
tree_check
(
tree
,
"foo"
));
}
void
test_check_added_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"entry"
);
TEST_ASSERT_TRUE
(
tree_check
(
tree
,
"entry"
));
...
...
@@ -153,7 +153,7 @@ void test_check_added_entry ()
void
test_check_common_prefix
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"introduce"
);
tree_add
(
tree
,
"introspect"
);
...
...
@@ -162,7 +162,7 @@ void test_check_common_prefix ()
void
test_check_prefix
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"toasted"
);
TEST_ASSERT_FALSE
(
tree_check
(
tree
,
"toast"
));
...
...
@@ -172,7 +172,7 @@ void test_check_prefix ()
void
test_check_nonexistent_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"red"
);
TEST_ASSERT_FALSE
(
tree_check
(
tree
,
"blue"
));
...
...
@@ -180,7 +180,7 @@ void test_check_nonexistent_entry ()
void
test_check_query_longer_than_entry
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
"foo"
);
TEST_ASSERT_TRUE
(
tree_check
(
tree
,
"foobar"
));
...
...
@@ -188,7 +188,7 @@ void test_check_query_longer_than_entry ()
void
test_check_null_entry_added
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
tree_add
(
tree
,
""
);
TEST_ASSERT_TRUE
(
tree_check
(
tree
,
"all queries return true"
));
...
...
@@ -196,7 +196,7 @@ void test_check_null_entry_added ()
void
test_size
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
// Adapted from the example on wikipedia.
std
::
vector
<
std
::
string
>
keys
;
...
...
@@ -234,7 +234,7 @@ void return_key (unsigned char *data, size_t size, void *arg)
void
test_apply
()
{
zmq
::
radix_tree
tree
;
zmq
::
radix_tree
_t
tree
;
std
::
set
<
std
::
string
>
keys
;
keys
.
insert
(
"tester"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment