Skip to content

Remove c casts#66

Closed
staffantj wants to merge 8 commits into
masterfrom
remove-c-casts
Closed

Remove c casts#66
staffantj wants to merge 8 commits into
masterfrom
remove-c-casts

Conversation

@staffantj

Copy link
Copy Markdown
Contributor

An attempt to clear up what happens if we removed all the (u)int32_t C-style casts in the codebase. In some cases the clean-up is no doubt the ideal way to deal with the local issue, and in some cases I've punted and tried to enforce a reasonable range. It will in other words probably need a bit of spit and polish were we to merge it as it currently stands.

Comment thread src/Convert.cpp Outdated
if (i > std::numeric_limits<INDEX>::max())
{
PyErr_Format(PyExc_ValueError, "Combine1Filter has attempted to exceed the size of the index value [%lld]", i);
return 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm curious - will this actually cause the exception to be raised when returning to Python?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think this would work, or if it did it seems rather obfuscated.
I think a better pattern may be to return an (result,error) tuple, so the root function could return the error.
@jack-pappas do you have a better suggestion?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To be honest I don't know. It seemed the most python-esque error reporting style in use in the file.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think the general pattern we want is to have only the publicly-exposed (as a function in the riptide_cpp Python module) setting the error/exception for a couple reasons:

  1. That pattern makes it easy to know which function has the responsibility for handling error and/or setting the Python exception.
  2. I think we want to be careful to keep the codebase generally pure C++ (that doesn't know about Python), with a "wrapper" that exposes the core C++ code to Python and handles the interop.

@OrestZborowski-SIG OrestZborowski-SIG Nov 19, 2021

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So two options then: error return (caller must check+translate) or throw exception (and caller must catch+translate)...
I lean towards exception, but I know code-base isn't very exception friendly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the general pattern we want is to have only the publicly-exposed (as a function in the riptide_cpp Python module) setting the error/exception for a couple reasons:

  1. That pattern makes it easy to know which function has the responsibility for handling error and/or setting the Python exception.

This makes sense to me.

  1. I think we want to be careful to keep the codebase generally pure C++ (that doesn't know about Python), with a "wrapper" that exposes the core C++ code to Python and handles the interop.

Absolutely. That's the main reason for the namespace split in the variant based refactor. The benefits are numerous, and the niggles fortunately few (at least when refactoring).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So two options then:
error return (caller must check+translate)
or throw exception (and caller must catch+translate)...
I lean towards exception, but I know code-base isn't very exception friendly.
Either causes a refactor around the call site. I'll take a look and see what feels cleanest. It may be the excuse to create our own exception base class so that we have something just-specific-enough to catch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Throw up to a layer that already had the PyErr_Format / return NULL logic in place implemented.

Comment thread src/Sort.cpp
// partStart, partLength, uniquesBefore);

if (callbackArg->sizeofUINDEX == 4)
if constexpr (sizeof(UINDEX) == 4)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If you're making this change generally, it seems like the sizeofUINDEX field of the struct above (on line 4078) could be removed altogether?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That does feel like a good idea. This was the only one whose side-effects were causing compiler warnings, so I didn't catch the rest.

Comment thread src/UnaryOps.cpp Outdated

int ndimOut;
int64_t strideOut;
int32_t strideOut;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we be using npy_intp or intptr_t (or ptrdiff_t) for representing the stride size everywhere? That's what's returned by the numpy C APIs when asking for the strides of an ndarray.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ptrdiff_t is the correct type according to standard-ese (the size required to hold the difference between an arbitrary pair of pointers within the same object).

However, I suspect that what we really have is an afine space of index and stride - so we should really make strong types out of both of them and subset their operations accordingly.

This changeset is rather in the way of an experiment to see what would happen if we restrict strides to 32-bit values, to avoid having to change the SIMD stride math UnaryOps and TileRepeat do. I wonder if we can live with "current behaviour" (ie re-instating various static_cast's) until we get the variant refactor for those done.

Comment thread src/SDSFile.h
Comment thread src/BasicMath.cpp
@staffantj
staffantj marked this pull request as draft February 14, 2022 14:46
@staffantj staffantj closed this Feb 14, 2022
@staffantj

Copy link
Copy Markdown
Contributor Author

This is an exposition-only PR. We've pulled some ideas from it, and will leave it closed so that we can pull further ideas as we need to.

@jack-pappas
jack-pappas deleted the remove-c-casts branch May 6, 2022 12:44
@jack-pappas
jack-pappas restored the remove-c-casts branch May 6, 2022 12:44
@OrestZborowski-SIG
OrestZborowski-SIG deleted the remove-c-casts branch January 17, 2023 19:05
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.

3 participants