Boost logo

Boost :

From: Marco Manfredini (marco_at_[hidden])
Date: 2000-03-07 16:38:02


Hello Boosters

> -----Original Message-----
> From: Miki Jovanovic [mailto:miki_at_[hidden]]
> Sent: Tuesday, March 07, 2000 8:22 PM
> To: boost_at_[hidden]
> Subject: [boost] Re: Bogus smart pointers?
>
>
> "marco manfredini" <marc-_at_[hidden]> wrote:
> > void doit()
> > {

>
> Complicated e-mail, and complicated code, for a simple question. All
> smart pointers out there do provide a 'locking' mechanism as you call
> it. And that is a temporary pointer, which you have actually
> mentioned.
>

Could you point me where that 'call locking' is? I've looked up the boost
smart-pointer classes from boost.org and did not find anything and the issue
isn't mentioned in the docs.

It all looks like:
 T* operator->() const throw() { return px; }

> Difference is, pointers do not deal with temporaries by
> default because
> of the performance hit. Also your problem of two way
> referencing of two
> classes is also not very common, and such dependencies should be

I must object. It wouldn't take it so serious, if I haven't had been then
victim of mutually calling classes several times. The problem is, that in a
framework that is composed out of components from different sources, you
can't track what is actually called.
There is nothing I can avoid there, because I cannot assess the complete
structure of the framework. I can just guarantee, that my components follow
the rules and implement their interfaces accordingly. Performance is no more
an issue here: if one component out of hundreds fails to take full liability
for the ownership of its data, the whole framework will fail.

> avoided whenever possible.
>
> So your code should simply become:
>
> void doit()
> {
> _ptr<Worker> temp( w );
> temp->work();
> }
>

I would prefer a way to enforce locking, for example distiguishing between a
'storing' smart pointer and a 'applyable' one:

void doit()
{
        _apply_ptr<Worker> t(w);
        t->work();
}

_apply_ptr locks like _ptr, but has the operations to access the pointer
value. Such a scheme, to explicitly the usage of a pointer for a stack
frame, could probably also be applyable to "owning only" smart pointer
classes.

The scoped_ptr could for example be extended with a locking count (a private
reference count so-to-say), which would make it more flexible and provide
better checking for misuse in runtime:

apply_scoped_ptr<A> foreign;
void doit()
{
        scoped_ptr<A> sa(new A);
        {
        apply_scoped_ptr<A> asa(sa); // lock scope pointer - asa's lifetime is a
strict subset of sa's lifetime, because I must construct from a existing
instance.
        //use it..
        }
        scoped_ptr tsa(new A);
        sa=tsa; // safe, because no more in use.

        apply_scoped_ptr<A> asa(sa);
        foreign=asa; // foreign has a lifetime that is not a subset of sa's
liefetime - this may be a problem! anyway allowed.

} // sa is destroyed and recognizes, that it is still in use! This is a
violation of scope_ptr's application (as non-shareable) and I think
it is justified, that sa throws an exception in it's destructor, because
silently destroying the enclosed object will open the possibility, that
'foreign' is used later in the program and giving unexpected results. This
place here is much closer to the source of the problem.
The introduction of apply_scoped_ptr<> does not violate the meaning of
ownership of scoped_ptr<>. An apply_scoped_ptr<> does not "share" with
scoped_ptr, it witnesses the ownership of scoped_ptr

I would suggest however, that the applyable form is a member type of the
smart pointer type (I think this is straightforward extension)

-Marco


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk