Skip to content

How to track life cycle of Arc<Database> #15

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

Open
katyo opened this issue Sep 18, 2018 · 2 comments
Open

How to track life cycle of Arc<Database> #15

katyo opened this issue Sep 18, 2018 · 2 comments

Comments

@katyo
Copy link

katyo commented Sep 18, 2018

I need to track final dropping of Database object in Arc. In particular I need delete databases (i.e. by calling Database::delete()) which was removed by the application when all references to it is dead.

My idea is a newtype wrapper for Database. I created the struct WrappedDatabase and implemented Deref trait for this newtype, but it still doesn't allows me to create cursors using Arc<WrappedDatabase> because it requires something which implements Into<Supercow<'a, Database>>.

Are anybody known a right solution?

@AltSysrq
Copy link
Owner

Reading between the lines, does WrappedDatabase call Database::delete() in its Drop implementation? The rest of this comment assumes that's the case, but if not, could you share the definition of struct WrappedDatabase and an example of where Database::delete() is called?

I'd initially suggest looking for any way to avoid doing that, but I assume you've already looked at other options.

What you can do here depends on whether you want a Cursor alone to be able to prevent the database deletion. That is, do you need to handle the case where no objects other than Cursor(s) hold a reference to the Database in question?

If "no", I would suggest having an Arc<Database> inside your WrappedDatabase, and cloning that inner Arc when constructing the cursor. Then, in the Drop implementation, you can try_unwrap it to gain ownership and delete it, as long as all cursors have been dropped meanwhile.

If "yes", you're in a stickier situation, but I think you can make it work. Supercow is flexible enough to be able to work with custom smart pointer types; you need to implement ConstDeref in addition to Deref. Then, where you're currently need Into<Supercow<'a, Database>>, use Supercow::shared to do the conversion in your code.

However, consider the fact that deleting a database requires starting and committing a write transaction. If you already have a write transaction open (retained by the Cursor or otherwise), the call to Database::delete() will deadlock. This again goes back to my first point, though you could work around it by arranging for a separate worker thread to call Database::delete() so that blocking to start the new write transaction wouldn't interfere with closing the current one.

@katyo
Copy link
Author

katyo commented Sep 19, 2018

Great thanks for detailed explanation.
Yes, my WrappedDatabase implements Drop trait to call Database::delete() when database was marked as dead.
And "yes" I'm in a stickier situation with cursors, because I need delete database when no cursors which use it.
Currently I delete databases when storage is dropped.
I tried to play with supercow, but unsuccesfully yet now. It seems I need to wrap Arc to get it work. I think this is more proper way.

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

No branches or pull requests

2 participants