On Mon, Aug 3, 2015 at 3:40 PM, K. Frank <kfrank2...@gmail.com> wrote:

> Hello List!
>
> Another question, again looking at the Wt::Dbo tutorial:
>
>    http://www.webtoolkit.eu/wt/doc/tutorial/dbo.html
>
> and, specifically, the example code:
>
>     ...
>     /*
>      * A unit of work happens always within a transaction.
>      */
>     dbo::Transaction transaction(session);
>
>     User *user = new User();
>     user->name = "Joe";
>     user->password = "Secret";
>     user->role = User::Visitor;
>     user->karma = 13;
>
>     dbo::ptr<User> userPtr = session.add(user);
>    }
>
> I would like to check my understanding of Wt::Dbo::ptr.
>
> When I say "ownership" I mean, primarily, the responsibility for
> memory management, in particular, calling delete.
>
> As I understand it it, when the local variable "userPtr" goes out
> of scope (at the closing brace at the end of the example code)
> delete will be called on "user" (of type User*).  Is this correct?
> (I understand that Wt::Dbo::ptr is a shared pointer, so that delete
> will be called when the last of multiple shared pointers is destroyed,
> but in this case userPtr is the only such pointer.)
>
> So, in my language, userPtr (together with any other shared pointers
> pointing to the same object) "owns" the instance of class User pointed
> to by the variable "user".  Is this correct?
>

That matches my experience, the documentation, convention, and shared
pointer semantics :-)


> So, in particular, something like:
>
>    {
>       User user;
>       user-.name = "Joe";
>       // ...
>       dbo::ptr<User> userPtr = session.add(&user);
>    }
>
> would NOT be the right way to do this because when userPtr
> goes out of scope, it would try to delete &user, (a pointer to)
> an object that was not created by a call to new.  (And furthermore
> user's destructor would be called twice -- once by the incorrect
> call to delete, and then again when user went out of scope.)
> Is this correct?
>

Yup.


>
> I have a question about exception safety:  What if the call to
> session.add() throws?  My understanding is that userPtr will
> not yet have been assigned, and will therefore not be able to
> delete (the object.  Who then would have responsibility for calling
> 'delete user;"?
>
> Is this issue just a simplification in the sample code and the (only?)
> exception-safe way to do this would be:
>
>    {
>       User *user = new User();
>
>       // this stuff can't throw -- true?
>       user->name = "Joe";
>       // ...
>       dbo::ptr<User> userPtr((user);
>
>       // this could throw, but userPtr ensures that user will be deleted
>       session.add(userPtr);
>    }
>
> Is there ever any fully exception-safe use of the original version?
>
>    dbo::ptr<User> userPtr = session.add(&user);


Excellent question. Based on the current source, it should be okay to pass
a pointer to a business object even in an exceptional situation. The source
is:

228 template <class C>
229 ptr<C> Session::add(C *obj)
230 {
231   ptr<C> result(obj);
232   return add(result);
233 }

If Wt::Dbo::Session::add(Wt::Dbo::ptr<C>&) throws, the original object will
be deleted. Of course, I can't think of many ways that session.add(&user);
could be used, excepting something like

User * ptr_user = new User();
User & user {*ptr_user};
session.add(&user);
/*We don't own ptr_user anymore, so don't delete it!*/

Happy coding!

In Christ,
Aaron Laws
------------------------------------------------------------------------------
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to