New shared pointer - revision 2

Frerich Raabe raabe at kde.org
Sat Sep 10 05:32:42 BST 2005


On Saturday 10 September 2005 01:48, Thiago Macieira wrote:
> Frerich Raabe wrote:
> >struct KDECORE_EXPORT KShared
> >{
> >        virtual ~KShared() {}
> >};
>
> The destructor here is unnecessary and its presence will cause an
> out-of-line empty destructor, a virtual table and the typeinfo
> information to be emitted, which is unnecessary.
>
> Simply leave the struct empty. It's valid in C++.

I know that it's valid, but it's not a good idea. Leaving aside that KShared 
is a baseclass, gcc will give you warnings if you don't make the destructor 
virtual because some classes (KSycocaEntry, for instance) have virtual 
functions but don't have a virtual destructor. Since KShared had a virtual 
destructor as well, and since this is just a helper to ease porting (so it 
should try to resemble the old behaviour), the virtual should be there.

> >                KSharedPtr( T *obj = 0 )
> >                {
> >                        KSharedData *x = new KSharedData;
> >                        x = qAtomicSetPtr( &d, x );
> >                        d->ref = 1;
> >                        obj = qAtomicSetPtr( &d->obj, obj );
> >                }
>
> I think you're overkilling here with qAtomicSetPtr. There's no
> thread-safety issue with the KSharedData variables d and x because you've
> just allocated it.

Ah okay, so 'd->obj = new KSharedData;' is okay?

> >                KSharedPtr( const KSharedPtr<T> &other )
> >                {
> >                        KSharedData *x = new KSharedData;
> >                        x = qAtomicSetPtr( &d, x );
> >                        *this = other;
> >                }
>
> Again the unnecessary calls. Also, you're allocating one KSharedData
> object only to deallocate it in operator=() when it calls deref(). Can't
> you optimise it to avoid allocating at all?
>
> For instance, make deref() detect if d == 0?

This is wrong. *this = other calls operator=( const KSharedPtr<T> & ), not 
operator=( T* ). Hence the newly allocated KSharedData won't be deallocated 
immediately (since the former assignment operator calls ref() on it's 
argument before deref()erencing).

> >                KSharedPtr<T> &operator=( T *rhs )
> >                {
> >                        deref();
> >                        if ( !d ) {
> >                                KSharedData *x = new KSharedData;
> >                                x = qAtomicSetPtr( &d, x );
> >                        }
> >                        rhs = qAtomicSetPtr( &d->obj, rhs );
> >                        d->ref = 1;
> >                        return *this;
> >                }
>
> I don't think this is correct.

It is.

> If the object is holding an object somewhere with refcount > 1, then
> deref() won't do anything and d != 0. Therefore, you won't create a new
> KSharedData and will overwrite the existing (and shared!) one with rhs.

This is wrong - rhs is a T*, not a KSharedData* - there is no write access to 
d itself at all, it doesn't get overwritten at all.

> >                T *get()
> >                {
> >                        return d->obj;
> >                }
>
> Can I suggest a const T *get() const function?

This doesn't make a difference, since get() is only a helper function which 
you should use if you're desperate, there's not much point in trying to try 
making this safer to use. What would make sense is to use 'T *get() const;' 
tho, so that you can do such evil things even on const KSharedPtr objects 
(there's not much point in restrictions for such things).

> May I also suggest that you don't use a pointer to QString in the class's
> apidox? QString is already implicitly-shared and pointers to it are
> almost always wrong, so we should not provide incentive to use them.
> (it's ok in the test code). Use a dummy class like FooBar.

I'm indifferent on this.

- Frerich

P.S.: You did overlook a much more grave problem (which I already fixed 
locally). Think about what happens when one does
'KSharedPtr<int> p; KSharedPtr<int> q = p.copy();'
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20050910/5c4d8e6a/attachment.sig>


More information about the kde-core-devel mailing list