-
Notifications
You must be signed in to change notification settings - Fork 69
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
core-clp: Add templates to support systematic and type-safe error code handling. #486
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets resolve some of the inconsistent naming:
- we switch between
err
anderror
throughout the code errno
inget_errno
anderror_num
in other places should be the same as far as I can tellm_error
is a little ambiguous given almost everything is prefixed with "error" and its getter (currentlyget_err_enum
) should match the name
I think it would be good if we add a test where we make a condition with a stdlib error_code and an error_code from your template to sanity check / ensure we don't break any functionality.
Made some of the methods inline to the template declaration so that they can't be specialized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The major thing I'm concerned with is how to actually use this error-handling library beyond the examples provided in the unit tests.
From what I've seen after testing out this library myself:
- The templates are implemented in the namespace
clp::error_handling
, so the overridden function implementations need to be in the same namespace as well. This is a bit counter-intuitive if you are working in a different namespace. - Ideally the ErrorCode enum class and the actual ErrorCode class should be placed in another header file so that the same error code system can be potentially used across different files. They could also be declared in a namespace that' could be entirely orthogonal to
clp::error_handling
. I don't have a clear clue on how that can be achieved. In the unit tests, these classes are defined in a global scope, and not in a header file. So a README that can guide library users would be very helpful. - Once the error code library works 100%, we can implement the same for the error conditions, and then figure out all possible scenarios of them comparing against each other.
- we've discussed things like using small/harmless macros to help library users implementing their custom error codes. But this is not as important as figuring out how to use it properly first.
|
Description
Problem Statement
In the current CLP core, we use a generic enum defined in
clp/ErrorCode.hpp
as our error code machism. We've been seeing problems of this design from the following perspectives:ErrorCode_Unsupported
is used in both reader interfaces to indicate unsupported operations, and it is also used inWildcardToken
to report an unsupported wildcard token. This error code itself doesn't provide the upper caller with the context of the error.ffi/ir_stream
component defines its own error enumsIRErrorCode
andIRProtocalErrorCode
, instead of using the genericErrorCode_xxx
. There is no systematic way to organize these different error code enums across the code base.std_result
fromoutcome
, orstd::expected
in the future if we migrate to C++23.Solution
In modern C++, the standard does provide a systematic and type-safe way of managing error codes:
<system_error>
. A detailed tutorial can be found in a cppcon talk here.The idea of this standard is simple. As module developers, you need to extend
std::error_code
to be compatible with a customizedstd::error_category
and an enum of possible errors. Thestd::error_category
will be used to identify the context of the errors with human-readable messages for each defined error. And for module users, they only need to compare the enum against thestd::error_code
instance to inspect errors.Furthermore, the standard library also provide capabilities to define mappings from multiple error codes to one "error condition" using
std::error_condition
, providing better management for sources of errors.By using this library, we should be able to solve all the problems mentioned in the previous section.
Implementation
This PR implements
ErrorCode
as a generic error code template, which integratesstd::error_code
and can be extended to customized error enums.To implement a new set of error codes, developers need to do the following steps:
MyErrorCodeEnum
ErrorCodeCategory<MyErrorCodeEnum>
:name()
: Defines the name of the error categorymessage(MyErrorCodeEnum error_enum)
: Provides a translation from the error enum to an error message stringstd
namespace, specialize the following template to be true:After these three steps,
ErrorCode<MyErrorCodeEnum>
will be considered as a valid clp error code class. An instance of this class, initialized by an enum value fromMyErrorCodeEnum
, will be considered as a domain-specific error. This error can be implicitly converted into astd::error_code
, providing compatibilities withoutcome::std_result
and user-level error inspections.In addition to the template implementation, we also include a unit test to not only test the basic usage of the
ErrorCode
template, but also give an example of how to use the template to define a set of errors of a specific domain.Last but not least, the current implementation should be extendable to add error condition supports in the future.
Validation performed
std::error_code
handling introduced there.