Skip to content

Implement IDisposable in OdbBackend #713

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

Merged
merged 1 commit into from
Jun 7, 2014
Merged

Implement IDisposable in OdbBackend #713

merged 1 commit into from
Jun 7, 2014

Conversation

nulltoken
Copy link
Member

Seeing how it implements Dispose, it doesn't make sense not to have it implement IDisposable

@ethomson
Copy link
Member

It does make sense; the lifecycle for an OdbBackend is such that libgit2 itself is the one who disposes the backend, not the caller.

@synhershko
Copy link
Author

Yes, unless you're writing your own and want to properly test it (my case). Anyway, the framework can do nice things with disposables, so why not tell it it is one?

@ethomson
Copy link
Member

Well, maybe I'm not understanding what you want to do. But if you were to make that Dispose method public, and make the class IDisposable, then as soon as you disposed the OdbBackend, you'd get an access violation when libgit2 called in to your OdbBackend the next time.

I guess I just don't understand what problem you're trying to solve.

@synhershko
Copy link
Author

Implement my own OdbBackend and unit-test it, and currently I cannot do:

using (var be = new MyOdbBackend())
{
// test
}

Even though it does implement Dispose()

In what scenarios do you see ppl going to dispose the backend and expecting libgit2 not to throw???

@ethomson
Copy link
Member

Yes, but it's not clear to me why you want to do that. We also implement our own OdbBackends, we also unit test them, and making them IDisposable or not does not impact that.

Right now: there are no scenarios where people can dispose the backend. Only libgit2 can dispose the backend. That's why the Dispose method is not public.

@synhershko
Copy link
Author

Because testing a backend through libgit2 is not unit testing :) there are a few behaviors I'm testing directly, at least as smoke tests. It would be easier to have a disposable object implement IDisposable but I can see your point for not buying that (although I disagree with the approach).

Feel free to close this if the answer is still no.

@dahlbyk
Copy link
Member

dahlbyk commented May 19, 2014

Similar to #528 (comment), perhaps we should reserve Dispose for truly IDisposable use cases and use something else (Free?) for cleanup managed by libgit2?

It would be easier to have a disposable object implement IDisposable but I can see your point for not buying that (although I disagree with the approach).

Nothing prevents you from making MyOdbBackend implement IDisposable to simplify your unit testing.

@synhershko
Copy link
Author

Free like in C or in Beer ? :)

@synhershko
Copy link
Author

And good point @dahlbyk

@synhershko synhershko closed this May 19, 2014
@ethomson
Copy link
Member

Aha aha - I see. Yeah, I think that what @dahlbyk is suggesting is the best solution, that:

  1. We should not call this method Dispose because it is very confusing and might get in the way with you implementing IDisposable in your OdbBackend
  2. Then you can implement IDisposable (independent of the method that libgit2 calls when it's done with your backend)

Does this seem reasonable?

@synhershko
Copy link
Author

@ethomson yep, but try finding a better name than Free :)

@ethomson
Copy link
Member

Okay, that's fair. I'm partial to Free but if you have a better idea,
I'm all ears.

Thanks for your patience in explaining this problem; apologies for being
dense.

On Mon, May 19, 2014 at 4:09 PM, Itamar Syn-Hershko <
[email protected]> wrote:

@ethomson https://github.com/ethomson yep, but try finding a better
name than Free :)


Reply to this email directly or view it on GitHubhttps://github.com//issues/713#issuecomment-43569534
.

@synhershko synhershko reopened this May 19, 2014
@nulltoken
Copy link
Member

Ok. I turned this issue into a PR with a proposal.

I changed the way OdbBackend deals with the release of its own resources while making it easier for the consumer to create its own IDisposable backend.

Previous implementation was allowing the consumer to override Dispose(), but there was a risk of leak if the consumer forgot to call base.Dispose().

The change allows the following:

  • No funky Dispose() method exposed
  • OdbBackend will always release its own resources
  • If the backend implements IDisposable, the Dispose() method will be called

@nulltoken
Copy link
Member

Implement my own OdbBackend and unit-test it, and currently I cannot do:

using (var be = new MyOdbBackend())
{
// test
}

Even though it does implement Dispose()

@synhershko I wouldn't recommend this kind of unit testing. AFAIK, Read() and ReadPrefix() will delegate to libgit2 the memory allocation (through Allocate()) and only libgit2 is in charge of releasing the memory when it's done with it.

Leveraging the backend by itself, outside of the libgit2sharp/libgit2 ecosystem would short-circuit the memory life cycle and lead to memory leaks.

Well, at least this is my understanding of the code... and I may be completely wrong.

/cc @ethomson

{
if (IntPtr.Zero != nativeBackendPointer)
if (nativeBackendPointer == IntPtr.Zero)
Copy link
Member Author

Choose a reason for hiding this comment

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

No Yoda talk

Copy link
Contributor

Choose a reason for hiding this comment

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

I propose to rename the variable to pointerBackendNative

@phkelley
Copy link
Member

phkelley commented Jun 7, 2014

This looks good. The only thing I would say is that sometimes with Dispose methods there are bugs where the environment invokes the Dispose method twice. It might be interesting to modify the test case to check for a stronger guarantee -- that the dispose count on the MockOdbBackend is exactly 1 after the Repository is disposed, rather than just checking that it has been invoked at least once, which is what is happening now. This is only a suggestion and should not hold up this PR, because what you have here is fine as is as well.

@nulltoken nulltoken added this to the v0.19.0 milestone Jun 7, 2014
@nulltoken
Copy link
Member

@phkelley You're right. Fixed! Thanks for your 👀 !

@nulltoken nulltoken merged commit ed3eda0 into vNext Jun 7, 2014
@nulltoken nulltoken deleted the ntk/odb_free branch June 7, 2014 16:13
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.

6 participants