Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

tanneberger
Copy link
Member

@tanneberger tanneberger commented Oct 20, 2023

Contribution

Testing procedure

Issues/PRs references

@waehlisch
Copy link
Member

@mroethke @fho any feedback is highly appreciated. a group of students at TUD started to integrate ASPA into RTRlib.

@tanneberger tanneberger marked this pull request as draft October 21, 2023 00:14
@tanneberger
Copy link
Member Author

Please note that the main development will first happen in the fork https://revol-xut/rtrlib, and then we will do a larger PR that adds full ASPA support at once, following the rfc @waehlisch just posted.

So this PR will grow slowly over the next couple of weeks.

@tanneberger tanneberger force-pushed the data-structure branch 4 times, most recently from cadc145 to 7f1ea85 Compare October 22, 2023 14:40
@mroethke
Copy link
Member

Several quick comments:

  • Commit messages should be in imparative mood lib: add aspa_vector …
  • Please also explain the why in the commit message. Why is this data structure needed? Why this kind of data structure and not something else.
  • I don't really like the name, it is an ordered dynamic array, please call it that. (ordered_dyn_array or something like that would also work for me)
  • Please use the malloc wrapper from rtrlib/lib/alloc_utils.h instead of calling malloc and friends directly.

I have not really looked at the code so far, I will do that after you have explained the why.

- add aspa_record struct
- add aspa_vector_{create, delete, reallocate, ordered_insert, insert, delete_at, find_cas}
- aspa_vector is simimlar in function to std::vector but is sorted therefore search can be performed with binary search
Copy link
Member

@fho fho left a comment

Choose a reason for hiding this comment

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

great project, the code looks good, I reviewed ~80.

  1. I'm wondering why it is chosen to dynamically resize the array.
    Why does it fit better the user case then then letting the caller specify the
    initial size + providing a resize operation where the new size is explicitly
    passed?
    The reason should also be documented in the commit and/or PR description.
  2. It's not needed to have a comment for every line.
    Most of the the code is self-explanatory, e.g. when calling free or assigning an array element. Having comments for those simple operations makes it actually more cumbersome to read.
  3. The naming became inconsistent. In some places the data structure is called
    vector (var names, documentations) in other places ordered_dyn_array.
  4. Use more error codes then -1.
    Currently only -1 is returned on errors. This makes it very hard to impossible for the caller to figure why an operation failed.

int ordered_dyn_array_create(struct ordered_dyn_array **vector_pointer)
{
const size_t DEFAULT_INITIAL_SIZE = 128;

Copy link
Member

Choose a reason for hiding this comment

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

If you allocate *vector first you do not need the data_field var and could directory store the pointer for the allocated data memory in vector->data


int ordered_dyn_array_create(struct ordered_dyn_array **vector_pointer)
{
const size_t DEFAULT_INITIAL_SIZE = 128;
Copy link
Member

Choose a reason for hiding this comment

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

Why was 128 chosen?

Comment on lines +52 to +55
if (vector->data != NULL) {
// freeing the data
free(vector->data);
}
Copy link
Member

Choose a reason for hiding this comment

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

Why is the behavior different when vector is NULL and vector->data is NULL?
If vector is null an error is returned, if vector->data is null it will be silently ignored and success will be returned.

Is there a valid usecase where vector is not null but vector->data is?

Comment on lines +69 to +84
struct aspas_record *new_data_field = (struct aspas_record *)lrtr_malloc(
sizeof(struct aspas_record) * vector->capacity * SIZE_INCREASE_EXPONENTIAL);

// malloc failed so returning an error
if (new_data_field == NULL) {
return -1;
}

// copying the data from the old location to the new one
memcpy(new_data_field, vector->data, vector->capacity * sizeof(struct aspas_record));

// deleting the old vector
free(vector->data);

// assigning the new array to the vector and incrementing the capacity
vector->data = new_data_field;
Copy link
Member

Choose a reason for hiding this comment

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

This block looks like it could be replaced by a single call to realloc or reallocarray.

* creates an vector object
* @param[vector_pointer] the pointer to the newly created pointer will be written to *vector_pointer
* @result Valid pointer to an ordered_dyn_array struct
* @result Null On error.
Copy link
Member

Choose a reason for hiding this comment

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

documentation is outdated, it can't return null

* @result 0 On success.
* @result -1 On error.
*/
int ordered_dyn_array_reallocate(struct ordered_dyn_array *vector);
Copy link
Member

Choose a reason for hiding this comment

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

Why is this function exported?
If the user can't choose the new size, I don't know a reason why he would ever want to call it explicitly.


/**
* @brief Struct which is similar in function to std::vector from C++.
* If the vector is running full a larger chunk of memory is allocated and the data is copied over.
Copy link
Member

Choose a reason for hiding this comment

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

document in which order the records are kept

Comment on lines +47 to +50
// if the vector is null just return
if (vector == NULL) {
return -1;
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't think it adds value to return success/failure the nothing from this function.
If an error is returned how is the caller expected to handle the situation?

I would instead either:

  • Expect that the caller calls this function only once for a vector and does not call it with a nulll value. If he does run into the segfault.
  • Handle the situation gracefully if one of the ptr is null ignore it, only run free if it is not null, additionally log a message if one of the ptrs is null but it is not expected, to allow to find the cases and fix them.

};

/**
* @brief Struct which is similar in function to std::vector from C++.
Copy link
Member

Choose a reason for hiding this comment

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

Instead of referencing std::vector here, it would be better to describe what it does.
Otherwise the reader first have to figure out how std::vector functions to know what ordered_dyn_array does

@fho
Copy link
Member

fho commented Feb 29, 2024

@tanneberger can this PR be closed? Seems to be superseded by #285

@fho fho mentioned this pull request Mar 10, 2024
@fho
Copy link
Member

fho commented Apr 1, 2024

@tanneberger can this PR be closed? Seems to be superseded by #285

I assume, no reply means "Yes".
Feel free to reopen the PR otherwise.

@fho fho closed this Apr 1, 2024
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.

4 participants