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
d5067df2
Unverified
Commit
d5067df2
authored
5 years ago
by
Luca Boccassi
Committed by
GitHub
5 years ago
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3559 from ssbl/inconsistent-naming-convention-fix
Problem: code doesn't follow libzmq naming conventions
parents
4a855fba
1186e986
No related merge requests found
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 @
d5067df2
...
...
@@ -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
);
...
...
This diff is collapsed.
Click to expand it.
src/radix_tree.cpp
View file @
d5067df2
...
...
@@ -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
;
}
This diff is collapsed.
Click to expand it.
src/radix_tree.hpp
View file @
d5067df2
...
...
@@ -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
;
};
}
...
...
This diff is collapsed.
Click to expand it.
src/xsub.hpp
View file @
d5067df2
...
...
@@ -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
...
...
This diff is collapsed.
Click to expand it.
unittests/unittest_radix_tree.cpp
View file @
d5067df2
...
...
@@ -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"
);
...
...
This diff is collapsed.
Click to expand it.
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