-
Notifications
You must be signed in to change notification settings - Fork 56
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
Replace assertions with verifies in ocean.io.* #251
Replace assertions with verifies in ocean.io.* #251
Conversation
These were never compiled nor maintained.
import ocean.core.MessageFiber; | ||
|
||
import ocean.core.Verify; |
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.
double import
@@ -383,10 +384,10 @@ class FileSystemEvent : ISelectClient | |||
{ | |||
foreach ( ev; this.fd.readEvents() ) | |||
{ | |||
assert(ev.mask); | |||
verify(ev.mask != 0); |
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.
Probably would be better off with ev.mask != ev.mask.init
@@ -251,6 +248,7 @@ public class SelectEvent : ISelectEvent | |||
|
|||
protected override bool handle_ ( ulong n ) | |||
{ | |||
verify(this.handler !is null); |
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 one is added here, because it was in line 147, but never compiled (in contracts of the abstract method's implementations are not compiled).
@@ -450,7 +452,7 @@ class DataOutput : OutputFilter | |||
private final void eat (Const!(void)* src, size_t bytes) | |||
{ | |||
auto count = output.write (src[0..bytes]); | |||
assert (count is bytes); | |||
verify(count == bytes); |
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.
Is there any difference in using is
vs ==
for value types?
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.
For structs only (as they may provide own opEqual
)
Codecov Report
@@ Coverage Diff @@
## v3.x.x #251 +/- ##
==========================================
- Coverage 71.96% 71.89% -0.07%
==========================================
Files 458 458
Lines 38798 38836 +38
==========================================
+ Hits 27922 27923 +1
- Misses 10876 10913 +37 |
src/ocean/io/stream/Iterator.d
Outdated
@@ -58,6 +60,7 @@ package import ocean.io.device.Conduit : InputFilter, InputBuffer, InputStream; | |||
|
|||
class Iterator(T) : InputFilter | |||
{ | |||
import ocean.core.Verify; |
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.
double import
f32b2b4
to
4a96555
Compare
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.
All looks ok to me. I agree with your comments.
@@ -161,9 +160,9 @@ class TaskSelectClient: ISelectClient | |||
try | |||
{ | |||
this.task = task.getThis(); | |||
assert(this.task); | |||
verify(this.task !is null); |
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 cases like this we have to be careful: verify(object !is null)
does not call the object invariant while assert(object)
does. Task
doesn't have an invariant so it's fine here, but in general this change can silently drop a debugging aid.
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 the better thing to do would be:
// old
assert(object);
// replace with
verify(object !is null && object); // call invariant
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.
No, only literally assert(object)
works. It is a magic expression to call the invariant.
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.
And assert(task)
is perfectly fine here:
- it will just crash on the next line in release build
- it protects against being called from main thread context - not something that may not be noticed before production deloyment
@@ -206,7 +200,7 @@ struct StructSerializer ( bool AllowUnions = false ) | |||
size_t transmit ( bool receive, S ) ( S* s, void delegate ( void[] data ) transmit_data ) | |||
in | |||
{ | |||
assert (s, typeof (*this).stringof ~ ".transmit (receive = " ~ | |||
verify(s, typeof (*this).stringof ~ ".transmit (receive = " ~ |
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.
Should this be s !is null
?
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.
There's an in
contract here anyway :-)
src/ocean/io/Path.d
Outdated
@@ -1460,11 +1462,11 @@ in | |||
switch (pattern[i]) | |||
{ | |||
case '[': | |||
assert(!inbracket); |
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've grepped for in$
and this showed up as a remaining in
contract. This feels very expensive to be left in release
build. Should I just leave it here and use assert
?
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.
Is patternMatch
a function that you could imagine being called in time critical code?
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.
Puh, I guess you're right. It's still O(n)
, but let's KISS.
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 would keep it nested inside {}
block to make it easier to eventually reconsider and remove it if needed
4a96555
to
eb8133e
Compare
Updated to address @david-eckardt-sociomantic 's comment and to move one debug block from |
eb8133e
to
2c7bf89
Compare
Updated. |
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.
Some arguable comments from my side :)
{ | ||
verify(dst !is null); |
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.
verify(dst.length > 0)
makes more sense here
src/ocean/io/Path.d
Outdated
@@ -1460,11 +1462,11 @@ in | |||
switch (pattern[i]) | |||
{ | |||
case '[': | |||
assert(!inbracket); |
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 would keep it nested inside {}
block to make it easier to eventually reconsider and remove it if needed
@@ -33,6 +33,7 @@ module ocean.io.model.SuspendableThrottlerCount; | |||
*******************************************************************************/ | |||
|
|||
import ocean.transition; | |||
import ocean.core.Verify; |
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 think all checks in this module actually should remain assert
- they don't protect from any kind of memory corruption and relate to hot path in apps.
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.
they don't protect from any kind of memory corruption
But they are valid sanity checks, which is the purpose of verify
. I don't see any harm leaving them as verify
.
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 what I think as well. Perhaps the trick is "hot path"?
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.
No, purpose of verify
is specifically sanity checking you can not abandon. So that when you build -release
you get maximum performance possible while still not compromising the app. No more, no less.
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 other words, "sanity check that is nice to have to catch weird app state but which won't help to keep the app working and won't prevent anything bad" is pretty much definition of assert
use case.
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.
Huh... this makes it a very tricky thing to decide, in many cases. A bug in this class, for example, could lead to seriously wrong app behaviour. Can those checks be abandoned?
Also: I was viewing this conversion process as allowing us to run release builds of D2 apps without losing any of the sanity checks that are in place right now but also without the risk of Error
s being thrown. This is a somewhat different (and I would argue far more pressing) goal.
@@ -300,8 +302,8 @@ public abstract class EpollProcess | |||
|
|||
if (pid == -1) | |||
{ | |||
assert( errno() == ECHILD ); | |||
assert( this.processes.length == 0 ); | |||
verify(errno() == ECHILD); |
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.
either assert
or enforce
- either this is protecting from OS being broken or checking external state that is beyond programmer control
{ | ||
verify(super.fiber.waiting); |
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.
assert
is fine, fiber will have own verify
on resume
@@ -161,9 +160,9 @@ class TaskSelectClient: ISelectClient | |||
try | |||
{ | |||
this.task = task.getThis(); | |||
assert(this.task); | |||
verify(this.task !is null); |
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.
And assert(task)
is perfectly fine here:
- it will just crash on the next line in release build
- it protects against being called from main thread context - not something that may not be noticed before production deloyment
this.task.suspend(); | ||
assert(!this.task); | ||
verify(this.task is null); |
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.
Also can be assert
@@ -219,7 +220,7 @@ public class StringStructSerializer ( Char ) | |||
|
|||
public void open ( ref Char[] output, cstring name ) | |||
{ | |||
assert(this.indent.length == 0, "Non-zero indentation in open"); | |||
verify(this.indent.length == 0, "Non-zero indentation in open"); |
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.
- Error message is reverse wrong btw.
- I think all those check must be
assert
(probably with reusable exception even) as serialization often happens with I/O data
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.
It doesn't look that the error message is wrong :)
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 many negatives :grumpy:
{ | ||
verifyStructPtr!("dump")(s); |
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.
Same for this module - it all should enforce
with actual exception, those are not sanity violations
@@ -450,7 +452,7 @@ class DataOutput : OutputFilter | |||
private final void eat (Const!(void)* src, size_t bytes) | |||
{ | |||
auto count = output.write (src[0..bytes]); | |||
assert (count is bytes); | |||
verify(count == bytes); |
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.
For structs only (as they may provide own opEqual
)
With last discussion in mind only remaining thing I'd like to happen is changing |
I'll change them 👍 |
Updated with the enforcements for the |
Red
|
Most serialization is being done with the external data, so in this case it's more appropriate to do enforce in this cases, with the reusable exception.
6229419
to
006c22f
Compare
Updated. |
No description provided.