Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding an ArrayList and HashMap implementation to rcutils #131

Merged
merged 6 commits into from
Jan 14, 2019

Conversation

nburek
Copy link
Contributor

@nburek nburek commented Dec 5, 2018

Connects to ros2/rcl#350

This change adds an ArrayList and HashMap implementation to rcutils. These data structures were needed for the rosout logging feature so that we could easily map logger names to nodes/publishers.

These changes were made on top of commits being reviewed in pull request #127. Once that pull request is merged on the latest commit that is on top of that will show in this PR.

@tfoote tfoote added the in review Waiting for review (Kanban column) label Dec 5, 2018
@nburek nburek force-pushed the rosout branch 2 times, most recently from 895cb6a to e3347c9 Compare December 7, 2018 06:05
Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek Awesome contribution! And sorry for the review comments avalanche, it's a big PR.

@@ -0,0 +1,208 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek consider documenting thread safety, memory allocation, atomic usage and lock usage for each function in this API (as it's done here).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this documentation.

rcutils_array_list_t
rcutils_get_zero_initialized_array_list(void);

/// Initialize an array liast with a given initial capacity.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek liast -> list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

size_t data_size,
const rcutils_allocator_t * allocator);

/// Finalize a string array, reclaiming all resources.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek string array -> array list? It looks like there're a bunch of refactor leftovers here and there in this file :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This data structure started as a more generic copy of the string array and then evolved to its current state (same with the hash_map). Sorry for the leftover cruft, I thought I had already scrubbed the documentation before I pushed but I guess I forgot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries.

* array_list.data[0] = rcutils_strdup("Hello", &allocator);
* array_list.data[1] = rcutils_strdup("World", &allocator);
* ret = rcutils_array_list_fini(&array_list);
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek missing closing code block backticks?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, they got pushed bellow some of the other comments that weren't meant to be code. Fixed.

* // ... error handling
* }
* array_list.data[0] = rcutils_strdup("Hello", &allocator);
* array_list.data[1] = rcutils_strdup("World", &allocator);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek it looks like this example is out of date.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this example and a number of others.

HASH_MAP_VALIDATE_ARGUMENT_NOT_NULL(value);

size_t key_hash = 0, map_index = 0, bucket_index = 0;
bool already_exists = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek nit: why not declaring it at the time of first use?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just grouping declarations near the top. They're all used shortly after.

HASH_MAP_VALIDATE_ARGUMENT_NOT_NULL(key);

size_t key_hash = 0, map_index = 0, bucket_index = 0;
bool already_exists = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek nit: why not declaring it at the time of first use?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

rcutils_ret_t ret = RCUTILS_RET_OK;

if (NULL != previous_key) {
already_exists = hash_map_find(hash_map, key, &key_hash, &map_index, &bucket_index, &entry);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek meta^2: iteration looks expensive, I wonder if there's a cheaper way to track where did it left off the last time rcutils_hash_map_get_next_key_and_data was called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case where you're not modifying the map as you iterate through then this shouldn't be that much more expensive. The find should average out to be constant time. There would be some slight benefit in creating an iterator style method for this as it might not need to rehash the key each time. I didn't use the iterator approach for two reasons:

  1. My primary use case was to use this function when cleaning up the map and I would be modifying it by removing entries as I went. A simple iterator would be invalid if the map was modified in between.
  2. So far, the other data structures didn't look like they were using an iterator style approach. This function was more in line with what I was seeing from the other data structures. I didn't want to risk add complexity to this review by trying to set a precedent for iterators when it wasn't needed yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. And I agree with you. Thanks for the detailed reply.

@@ -0,0 +1,355 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek 2017 -> 2019?

@@ -0,0 +1,452 @@
// Copyright 2017 Open Source Robotics Foundation, Inc.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek 2017 -> 2019?

@nburek
Copy link
Contributor Author

nburek commented Jan 7, 2019

@hidmic Thank you for the thorough review of the documentation. There were a lot of little fixups in there that got past me.

I've posted an updated version based on your comments.

Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but for a few minor nits and a question. Also pending green CI.

include/rcutils/types/hash_map.h Outdated Show resolved Hide resolved
include/rcutils/types/hash_map.h Outdated Show resolved Hide resolved
include/rcutils/types/hash_map.h Outdated Show resolved Hide resolved
* The order of the keys in the hash_map is arbitrary and if the hash_map is modified
* between calls to this function the behavior is undefined.
* If the hash_map is modifeid then iteration should begin again by passing NULL to
* get the first key again.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nburek hmm, isn't this statement against your use case in rcl?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll correct the rcl review.

hidmic and others added 3 commits January 8, 2019 08:42
Co-Authored-By: nburek <[email protected]>
Co-Authored-By: nburek <[email protected]>
Co-Authored-By: nburek <[email protected]>
@nburek
Copy link
Contributor Author

nburek commented Jan 8, 2019

Fixed the additional typos you pointed out.

It looks like the build is failing because the uncrustify linter is detecting that the logging_macros.h file is out of compliance. This file is auto generated from logging_macros.h.em and it looks like the failure may be a result of this PR: #133

Since the failure appears to be unrelated to my PR I would prefer not to fix it here.

@hidmic
Copy link
Contributor

hidmic commented Jan 8, 2019

Not sure how could that be the case. IIRC #133 should make uncrustify ignore line lengths. @jacobperron will probably know better though.

In any case, this still needs to go through https://ci.ros2.org. I'll set it up for you.

@hidmic
Copy link
Contributor

hidmic commented Jan 8, 2019

Running CI, including this PR and ros2/rcl#350:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@chapulina
Copy link

Looking at CI, it looks like this PR by itself only has a few uncrustify_logging_macros errors (see Cpr...), but the combination of this PR with ros2/rcl#350 is causing a lot of test failures. I think it would be good to figure out what's causing those errors before merging this PR, just in case.

@nuclearsandwich
Copy link
Member

this PR by itself only has a few uncrustify_logging_macros errors (see Cpr...)

Those are due to the upgrade to uncrustify 0.68.1 on master while we released Crystal with 0.67 and they disagree on a few points. We're upgrading Crystal to 0.68.1 in the upcoming patch release and these errors should subside.

@nburek
Copy link
Contributor Author

nburek commented Jan 11, 2019

Commented on the other PR as well, but the bug in the changes to rcl that were causing the failures due to double free is now fixed. Can you please run the CI pipeline again when you get a chance? Thank you.

@nburek
Copy link
Contributor Author

nburek commented Jan 11, 2019

I take that back, there is one more broken test in rcl related to test_graph because there is now always one extra topic running on the node for rosout. Fixing that now.

@nburek
Copy link
Contributor Author

nburek commented Jan 11, 2019

Okay, now it should be ready for retest.

@chapulina
Copy link

Here you go:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

Copy link
Member

@jacobperron jacobperron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some very minor comments. LGTM

include/rcutils/types/array_list.h Show resolved Hide resolved
include/rcutils/types/array_list.h Outdated Show resolved Hide resolved
src/hash_map.c Outdated Show resolved Hide resolved
src/hash_map.c Outdated Show resolved Hide resolved
@jacobperron jacobperron merged commit b98ac15 into ros2:master Jan 14, 2019
@jacobperron jacobperron removed the in review Waiting for review (Kanban column) label Jan 14, 2019
@nburek
Copy link
Contributor Author

nburek commented Jan 16, 2019

Can we try to get this PR merged into the next Crystal patch release?
ros2/ros2#647

@nuclearsandwich
Copy link
Member

Can we try to get this PR merged into the next Crystal patch release?

This is queued for patch release 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants