irr_ptr

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Nice try. Your code doesn't work, so you defer to something that does. Unfortunately, it still won't work...

Code: Select all

boost::shared_ptr<ISceneNode> a = smgr->addCubeSceneNode(10); 
This won't work because the boost shared_ptr doesn't know to call grab() or drop(). This would cause problems because the Irrlicht reference count is seperate from the shared_ptr reference count. If the above line would even compile (it won't because the required constructor is explicit), it would result in the node being deleted without removing it from the scene graph. Boom!

Code: Select all

boost::shared_ptr<IReferenceCounted> a(new DerivedReferenceCounted); 
a = a; 
a = a; 
a = a;
The self assignment problem is now fixed, and the initialization syntax is correct, but the previously mentioned problem is not fixed.

Regardless, no matter what you do, there are problems. The pointer needs to know if it is allowed to call drop() or not. Actually, it needs to know if it should grab() the pointer on construction or not.

Code: Select all

// this pointer should not be dropped unless it is grabbed
special_ptr<ISceneNode> a(smgr->addCubeSceneNode(10.f));

// this pointer should be dropped
special_ptr<ISceneNodeAnimator> b(smgr->createFlyCircleAnimator());
Sure, you could call a->grab() in this case and that would work just fine. Unfortunately this doesn't work well when trying to write code that takes special_ptr objects as parameters to functions.

The closest thing that would work correctly that is supplied by boost is the boost::intrusive_ptr implementation.

Travis
SSG
Posts: 33
Joined: Sun Jan 11, 2009 1:16 pm

Post by SSG »

Well it's not perfect. The point I was making in the previous post is not to wrap objects with irr_ptr if you wouldn't normally call drop. Of course this still requires you to remember on which objects to call drop (which is generally anything created with createXXXX(...). Perhaps irr_ptr could be extended by adding a constructor that takes an initial reference count, or perhaps a bool flag that says whether or not to grab() the object.

irr_ptr can still be useful if you just stick to some simple rules. But of course it's no substitute for the benefit of replacing irrlicht's IReferenceCounted with boost::shared_ptr.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

SSG wrote:irr_ptr can still be useful if you just stick to some simple rules.
Yes, but it is dangerous as it doesn't prevent you from misusing it.
SSG wrote:But of course it's no substitute for the benefit of replacing irrlicht's IReferenceCounted with boost::shared_ptr.
I don't know why you'd want to replace Irrlicht's existing reference counting with an external reference counter that is used by the boost::shared_ptr implementation (except for boost::weak_ptr support).

As I said, it would be much simpler to use boost::intrusive_ptr. That would at least take advantage of the reference count that every IReferenceCounted derived class already has. It still has one of the problems I mentioned above, but it more closely models what you'd need a smart pointer type to do to work with Irrlicht.

Travis
SSG
Posts: 33
Joined: Sun Jan 11, 2009 1:16 pm

Post by SSG »

I don't know why you'd want to replace Irrlicht's existing reference counting with an external reference counter that is used by the boost::shared_ptr implementation (except for boost::weak_ptr support).
Obviously IReferenceCounted is superior to boost::shared_ptr. After all, why would you want automatic reference counting when you can do it manually? There would be no fun in it!
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

If your goal is to persuade people to use either a boost pointer or your... uh... work in progress, then technical arguments and worked examples might be the way to inspire us.

On the other hand, if you're just looking for an ass kicking contest, I should warn you that vitek has 16 feet, and no ass.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

rogerborg wrote:vitek has 16 feet, and no ass.
:lmao: I'm trying to imagine what he looks like !!! :lol:
Last edited by Acki on Sat Jan 24, 2009 4:41 pm, edited 1 time in total.
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

rogerborg wrote:On the other hand, if you're just looking for an ass kicking contest, I should warn you that vitek has 16 feet, and no ass.
My new favorite quote!
Virion
Competition winner
Posts: 2149
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

rogerborg wrote:On the other hand, if you're just looking for an ass kicking contest, I should warn you that vitek has 16 feet, and no ass.
LOL FTW
My company: https://kloena.com
My profile: https://zhieng.com
My co-working space: https://deskspace.info
My game engine: https://kemena3d.com
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Bwahahah, my new favorite borg's quote :P
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

rogerborg wrote:On the other hand, if you're just looking for an ass kicking contest, I should warn you that vitek has 16 feet, and no ass.
Lol :lol: !! one of the best quotes I've ever seen here..

P.S
Virion - Awesome forum avatar. (You drew that yourself didn't you?)
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Well, actually I am too lazy to call grab() and drop() all the time, so I revived the idea. Not much tested and coded after being way too long awake before I even started with it ... should work perfect :-). I'm going to use it a few times the next days - if I find any problems I'll post 'em here. If you find any problems then just shoot me.

Code: Select all

#ifndef IRR_PTR_H
#define IRR_PTR_H

//! Save wrapper around the the reference counted pointers with an interface like irr::IReferenceCounted
//! NOTE: IrrPtr is made to mostly look like boost::shared_ptr. Differences are mostly because it has not the exact same job.
template <typename T>
class IrrPtr
{
public:

    //! Default constructor for empty IrrPtr
    IrrPtr()
    : mRefCounted(0)
    {
    }

    //! constructor
    /** \param ptr A reference counted pointer
        \param grab When true the reference count for the pointer is increased.
                    When false it is expected that the ptr has already an increased reference counter, for example because
                    it was returned by one of the Irrlicht create functions */
    explicit IrrPtr(T * ptr, bool grab=true)
    : mRefCounted(ptr)
    {
        if ( mRefCounted && grab )
            mRefCounted->grab();
    }

    //! copy constructor
    IrrPtr(const IrrPtr& other)
    : mRefCounted(0)
    {
        *this = other;
    }

    //! destructor
    ~IrrPtr()
    {
        if ( mRefCounted )
            mRefCounted->drop();
    }

    //! assign operator
    IrrPtr& operator=(const IrrPtr& other)
    {
        if ( this == &other )   // currently not needed due to set implementation, I just feel bad removing it.
            return *this;

        set(other.mRefCounted);

        return *this;
    }

    //! Dereference can use the managed pointer directly
    T & operator*() const
    {
        return *mRefCounted;
    }

    //! Memberaccess can use the managed pointer directly
    T * operator->() const
    {
        return mRefCounted;
    }

    //! Allows using bool operations for IrrPtr
    /** Like: IrrPtr<SomeType> instance; if ( instance ) { // do }; if ( !instance) { // do not } */
    typedef T * (IrrPtr::*unspecified_bool_type)() const;
    operator unspecified_bool_type () const
    {
        return mRefCounted ? &IrrPtr<T>::get : 0;
    }

    bool operator==(const IrrPtr<T>& other) const
    {
        return mRefCounted == other.mRefCounted;
    }

    bool operator!=(const IrrPtr<T>& other) const
    {
        return mRefCounted != other.mRefCounted;
    }

    bool operator<(const IrrPtr<T>& other) const
    {
        return mRefCounted < other.mRefCounted;
    }

    //! Access pointer directly
    T * get() const
    {
        return mRefCounted;
    }

    //! set a new pointer.
    /** The old pointer will be released unless it's identical with the new one.
        If old and new pointer are identical then nothing is done.
        \param ptr A reference counted pointer
        \param grab When true the reference count for the pointer is increased.
                    When false it is expected that the ptr has already an increased reference counter, for example because
                    it was returned by one of the Irrlicht create functions */
    void set(T * ptr, bool grab=true)
    {
        if ( mRefCounted != ptr )
        {
            if ( mRefCounted )
                mRefCounted->drop();
            mRefCounted = ptr;
            if ( mRefCounted )
                mRefCounted->grab();
        }
    }

    //! After a reset the class contains no longer a pointer.
    void reset()
    {
        if ( mRefCounted )
        {
            mRefCounted->drop();
            mRefCounted = 0;
        }
    }

    //! Swap the content with that of another IrrPtr
    void swap(IrrPtr<T> & other)
    {
        T * dummy = mRefCounted;
        mRefCounted = other.mRefCounted;
        other.mRefCounted = dummy;
    }

private:
    T * mRefCounted;
};

#endif // IRR_PTR_H
edit 2009/03/20:
- removed valid() and replaced it by a safe bool operation
- added operator ==, operator !=, operator<
- added function swap
edit 2009/03/21:
-. removed operator= for direct pointer assignment (too dangerous)
- set_created replaced by general set function with parameter
- documentation updated
- operator= is now using set
Last edited by CuteAlien on Sat Mar 21, 2009 12:36 am, edited 4 times in total.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

I can't prove this, I don't have my compiler right now, so I'm a little iffy on it. Correct me if I'm wrong:

Code: Select all

IrrPtr<OriginalA> myPtr( new DerivedFromOriginalA );
Will cause problems, will it not? It's technically not of type T. But maybe I'm wrong, and it gets casted up to type T. If I am right and it does cause errors, then wouldn't this fix it:

Code: Select all

template <class O> IrrPtr(O* ptr, bool grab=true);
And also, I think the constructors should be made explicit, but that's just a personal preference.
TheQuestion = 2B || !2B
CuteAlien
Admin
Posts: 10021
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Halifax wrote:I can't prove this, I don't have my compiler right now, so I'm a little iffy on it. Correct me if I'm wrong:

Code: Select all

IrrPtr<OriginalA> myPtr( new DerivedFromOriginalA );
Will cause problems, will it not? It's technically not of type T.
No problem as the type is only used as pointer.
Halifax wrote: And also, I think the constructors should be made explicit, but that's just a personal preference.
Ok, changed.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

CuteAlien wrote:

Code: Select all

//       I don't know how boost made that unspecified-bool-type operator so I had to use valid() instead.
//       Also there is an operator to directly appoint pointers, as it would be harder to use otherwise.
The unspecified-bool-type trick is actually pretty simple. I'll show code and explain it inline...

Code: Select all

template <class T>
class IrrPtr
{
    // unspecified_bool_type is a typedef for pointer to member function
    // that takes no parameters, returns T*, and is const (i.e., the get function)
    // this is done to prevent accidental conversion problems
    typedef T* (IrrPtr<T>::*unspecified_bool_type)() const;

public:

    // ...

    // conversion to unspecified_bool_type. if the pointer is valid
    // the function returns the address of the get function, otherwise
    // it returns null.
    operator unspecified_bool_type () const
    {
        return mRefCounted ? &IrrPtr<T>::get : 0;
    }

private:

    T* mRefCounted;
};
As long as you're using a modern compiler, it should work just fine. Otherwise you may have to make tweaks to get it to work.

Travis
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

CuteAlien wrote:
Halifax wrote:I can't prove this, I don't have my compiler right now, so I'm a little iffy on it. Correct me if I'm wrong:

Code: Select all

IrrPtr<OriginalA> myPtr( new DerivedFromOriginalA );
Will cause problems, will it not? It's technically not of type T.
No problem as the type is only used as pointer.
Halifax wrote: And also, I think the constructors should be made explicit, but that's just a personal preference.
Ok, changed.
Ah, okay, thanks for the answer and fix CuteAlien.
TheQuestion = 2B || !2B
Post Reply