Page 2 of 3
Posted: Fri Jan 23, 2009 3:29 am
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
Posted: Fri Jan 23, 2009 4:56 am
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.
Posted: Fri Jan 23, 2009 6:44 am
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
Posted: Fri Jan 23, 2009 10:55 pm
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!
Posted: Sat Jan 24, 2009 2:38 am
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.
Posted: Sat Jan 24, 2009 4:04 am
by Acki
rogerborg wrote:vitek has 16 feet, and no ass.
:lmao: I'm trying to imagine what he looks like !!!

Posted: Sat Jan 24, 2009 9:12 am
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!
Posted: Sat Jan 24, 2009 9:36 am
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
Posted: Sat Jan 24, 2009 5:02 pm
by Dorth
Bwahahah, my new favorite borg's quote

Posted: Sat Jan 24, 2009 6:38 pm
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

!! one of the best quotes I've ever seen here..
P.S
Virion - Awesome forum avatar. (You drew that yourself didn't you?)
Posted: Thu Mar 19, 2009 11:01 am
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
Posted: Thu Mar 19, 2009 12:31 pm
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.
Posted: Thu Mar 19, 2009 6:53 pm
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.
Posted: Thu Mar 19, 2009 11:25 pm
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
Posted: Fri Mar 20, 2009 12:12 am
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.