-
-
Notifications
You must be signed in to change notification settings - Fork 853
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
Fixed Issue#1628 #1629
Fixed Issue#1628 #1629
Conversation
…- it is done at public method calls
… was disposed, check is delegated to public methods using that property
…having a Finalization method
internal call EnsureNotDisposed is no longer virtual -> micro speedup gain in pixel index accessor Image<TPixel>[x, y].
As Image does not have unmanaged resources and does not implement finalizer method, there's no need for disposable pattern with a pair of Dispose() & Dispose(bool). Due Dispose(bool) was changed to DisposeManaged().
Subject to discuss. Image public properties Height, Width, Metadata and PixelType can't corrupt anything if backing image was disposed so I don't see any point altering that behaviour, it wasn't throwing before this branch and shouldn't throw after.
…ensures all operations are called on valid object
… if object was disposed
Codecov Report
@@ Coverage Diff @@
## master #1629 +/- ##
==========================================
+ Coverage 84.12% 84.15% +0.02%
==========================================
Files 812 812
Lines 35592 35634 +42
Branches 4146 4147 +1
==========================================
+ Hits 29943 29987 +44
Misses 4831 4831
+ Partials 818 816 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
I'll get this reviewed ASAP. Thanks for the contribution! |
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.
Definitely the right direction but we need to fix up the Disposal pattern changes to match convention and prevent breaking the API.
src/ImageSharp/Image.cs
Outdated
/// </summary> | ||
/// <param name="disposing">Whether to dispose of managed and unmanaged objects.</param> | ||
protected abstract void Dispose(bool disposing); | ||
protected abstract void DisposeManaged(); |
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 breaks common convention and the API so I can't allow it.
Providing an abstract protected abstract void Dispose(bool disposing)
is well documented and should be the pattern we use.
public void Save_ObjectDisposedException() | ||
{ | ||
var image = new Image<Rgba32>(this.configuration, 10, 10); | ||
var stream = new MemoryStream(); |
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.
using stream
. The fact that the GC cleans up here is an implementation detail.
src/ImageSharp/Image.cs
Outdated
{ | ||
if (this.isDisposed) | ||
{ | ||
throw new ObjectDisposedException("Trying to execute an operation on a disposed image."); |
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 should be using a ThrowHelper here to allow inlining on sealed instances.
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.
You mean ThrowHelper class from ThrowHelper.cs? Should I add ThrowArgumentException method or am I missing something? (there is none as far as I can see :P)
@@ -11,8 +11,10 @@ namespace SixLabors.ImageSharp | |||
/// Encapsulates a pixel-agnostic collection of <see cref="ImageFrame"/> instances | |||
/// that make up an <see cref="Image"/>. | |||
/// </summary> | |||
public abstract class ImageFrameCollection : IEnumerable<ImageFrame> | |||
public abstract class ImageFrameCollection : IDisposable, IEnumerable<ImageFrame> |
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.
Wow. I hadn't realized this wasn't already implementing the type. Good catch!
@@ -80,8 +82,14 @@ protected Image(Configuration configuration, PixelTypeInfo pixelType, ImageMetad | |||
/// <inheritdoc /> | |||
public void Dispose() | |||
{ | |||
this.Dispose(true); | |||
GC.SuppressFinalize(this); |
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 shouldn't be removing the finalizer suppression in the base class.
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.
Didn't know SuppressFinalize
do nothing if type has no finalizer, thanks!
src/ImageSharp/Image{TPixel}.cs
Outdated
throw new ObjectDisposedException("Trying to execute an operation on a disposed image."); | ||
} | ||
} | ||
protected override void DisposeManaged() => this.frames.Dispose(); |
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 original pattern was correct here.
…d raw throws with this in Image/ImageFrameCollection
@JimBobSquarePants seems like I've messed up with ThrowHelper from shared infrastructure. Although I'd added it locally, I've totally missed that it wasn't in the commit and it isn't tracked by git now. How to fix it? |
Not at all!! You're contributions are most welcome! That's my mistake for not being clear. |
Got it, thanks for answering yet another question! |
@br3aker Can you please give me write access to your fork. For some reason I'm unable to push directly to your PR so we can complete this. |
@JimBobSquarePants that's strange. Edit was enabled from the start, I re-checked it now, can you try it again please? |
@br3aker This isn't the first PR I've had issues with and I'm not sure why it happens. I tried again and it didn't work. The last time the contributor had to explicitly invite me as a contributor to the repo as a workaround. |
@JimBobSquarePants invite sent, thanks for fixing this! |
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.
LGTM 👍 Thanks!
Prerequisites
Description
Fixes #1628
Some public properties can't break anything (e.g image size or metadata), they didn't throw before this PR, this behaviour wasn't altered.
ToString
weren't affected either.Due to slight internal (within
Image
class) API change pixel indexer might be a bit more performant:EnsureNotDisposed()
call is no longer virtual. Although JIT in some runtimes even could inline such virtual calls in previous versions, it's still a nice change of having one less virtual method I guess.This change also affects any public method but their calls are too rare to affect performance.