-
Notifications
You must be signed in to change notification settings - Fork 123
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
Make Platform functions to return az_result #1256
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.
The other variant is better.
*/ | ||
void az_platform_sleep_msec(int32_t milliseconds); | ||
AZ_NODISCARD az_result az_platform_sleep_msec(int32_t milliseconds); |
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.
This is an unnecessary burden to the implementor of the PAL.
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.
@ahsonkhan are you referring to the AZ_NODISCARD or the az_result. I agree that we shouldn't force AZ_NODISCARD onto the implementations. I however do prefer the az_result return codes on the PAL. The minimal burden is greatly outweighed by the fact we can consistently validate the API performed as expected
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.
are you referring to the AZ_NODISCARD or the az_result
Both.
The minimal burden is greatly outweighed by the fact we can consistently validate the API performed as expected
I don't understand what you mean by this. What are we getting here?
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.
Ha, what I was thinking of, is that you Ahson was talking about the contrast of this variant to the proposal in #1257, saying that out parameters and az_result are generally more cumbersome to implement. I didn't read it as if you are commenting on the AZ_NODISCARD.
Regarding AZ_NODISCARD, I do not think it is a burden on the implementor. It is an intentional burden on the user, i.e. us. So, if we ignore the return result, we get a warning treated as compilation error. For the implementor, I am not sure if they even have to put AZ_NODISCARD in the signature of their imlpementation - having it in this header alone is probably enough (I am not sure, because AZ_NODISCARD is really compiler-specific).
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.
OMHO, platform should not depend on az_core. Only az_core should depend on some specific implementation.
Right now, in order to implement a platform, people need to get az_core, and people getting az_core need an az_platform. I don't like how that look XD. It works using cmake targets, but not sure if it would work without it (including pah directly)
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.
Interesting point on layering the dependency @vhvb1989
} | ||
|
||
void az_platform_sleep_msec(int32_t milliseconds) | ||
AZ_NODISCARD az_result az_platform_sleep_msec(int32_t milliseconds) | ||
{ | ||
(void)usleep((useconds_t)milliseconds * _az_TIME_MICROSECONDS_PER_MILLISECOND); |
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.
unrelated: precondition that milliseconds
is positive.
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.
So far we say in the docs, @remarks The behavior is undefined when \p milliseconds is a non-positive value (0 or less than 0)
. That's because on some platform, it would yield to other thread, but will return control back if no other thread needs it. We don't use this feature though.
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.
That's because on some platform, it would yield to other thread, but will return control back if no other thread needs it. We don't use this feature though.
We can add a precondition now to help folks write correct code, and loosen that in the future, if that value becomes meaningful.
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.
That's because on some platform, it would yield to other thread, but will return control back if no other thread needs it. We don't use this feature though.
We can add a precondition now to help folks write correct code, and loosen that in the future, if that value becomes meaningful.
We could precondition, but we would be limiting to a particular implementation of POSIX. Its not clear if every implementation places the same constraints. e.g. some platforms say the usec is not smaller than 1000000
others allow 0 to mean yield.
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.
This is one particular implementation though. Adding a precondition here doesn't impact users who want to provide their own PAL implementation. Passing in a negative millisecond will overflow when cast to unsigned int, and that could be an unintended bug in the user's code (given usleep
takes an unsigned number).
https://man7.org/linux/man-pages/man3/usleep.3.html#NOTES
*/ | ||
void az_platform_sleep_msec(int32_t milliseconds); | ||
AZ_NODISCARD az_result az_platform_sleep_msec(int32_t milliseconds); |
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.
@ahsonkhan are you referring to the AZ_NODISCARD or the az_result. I agree that we shouldn't force AZ_NODISCARD onto the implementations. I however do prefer the az_result return codes on the PAL. The minimal burden is greatly outweighed by the fact we can consistently validate the API performed as expected
Co-authored-by: Rick Winter <rick.winter@microsoft.com>
Co-authored-by: Rick Winter <rick.winter@microsoft.com>
@ahsonkhan , I pinged Jeffrey, I'll wait to hear his opinion. If you are ok with this implementation, please approve :) |
@ahsonkhan and the team: Jeffrey is ok with returning az_result instead of precondition failure. |
Can we have both? |
We could, and I thought about it at some point, but I don't think we should do it, given that precondition failure is not obvious to the users who are not familiar with it, so now that it is failed, users have to go learn about it first, and only then realize they need to implement PAL layer, so it removes one of the benefits of az_result. |
I would flip that. Precondition failures can be removed in the future. Strengthening a condition is more user hostile than weakening it. |
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.
We didn't discuss @vhvb1989 point on dependency/layering. I think that is a good argument for not returning az_result
. Let's close on that one.
void az_platform_sleep_msec(int32_t milliseconds) { Sleep(milliseconds); } | ||
AZ_NODISCARD az_result az_platform_sleep_msec(int32_t milliseconds) | ||
{ | ||
Sleep(milliseconds); |
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.
I still think we should add a _az_PRECONDITION(milliseconds > 0)
to all the implementations of the PAL.
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.
Since we have a variety of opinions, let's cover it outside of the scope of this PR, it can be added later without affecting this change.
|
||
void az_platform_sleep_msec(int32_t milliseconds) { (void)milliseconds; } | ||
AZ_NODISCARD az_result az_platform_sleep_msec(int32_t milliseconds) |
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.
Looking at this again, I agree with Rick on the sleep API, we should consider removing AZ_NODISCARD
.
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.
I don't think we should. It is us who calls these APIs. Rick's assumption is that 3 things are happening: 1. Customer calls PAL function. 2. Doesn't handle a result, and doesn't need/want to. 3. It is painful to ignore the result, which I think is not:
az_result ignore = az_platform_sleep_msec(1000);
(void)ignore;
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.
In that case, we should consider updating the documentation of az_http_pipeline_policy_logging
and az_http_pipeline_policy_retry
since they can now return any PAL-defined az_result
. Alternatively, those APIs should take any PAL-error and convert it to a single error value, and return/document that.
Jeff said to me "I can appreciate not wanting the customer getting started experience to force understanding on preconditions and figuring out how to deal with an infinite loop. To me, this is the ONLY compelling reason to avoid the precondition. Understanding preconditions is fundamental to our library just like spans and so you're only delaying the customer being forced to understand this; not preventing it entirely." So I replied "What you've just said about delaying the learning, to me sounds like more of an argument for having the az_result, and a relatively significant one." Adding a precondition would eliminate one of the benefits we get now. |
Great point. Progressive disclosure is definitely something we should try to achieve, where possible. |
We had that discussion about last November with Jeffrey, and decided in favor of header-only what-appears-to-look-like circular dependency, because it is simpler, and it works. I was actually a proponent of breaking the core into two modules back then: |
I think the PAL and HTTP adapter sit at different layers, so I don't think they both need to be held at the same bar.
We shouldn't need a small core below at all for PAL (since conceptually it sits below the SDK, closer to the OS/device hardware): |
It was the point that IoT didn't need PAL, and didn't want to depend on it at all so they would depend only on small core. There's even no need to rely on the linker throwing out the unused parts, as today. Small core has spans, results, etc. There was no |
Why |
True. |
This is variant A of the proposed behavior. Variant B: #1257
Closes #1226