Reputation: 3731
The following is a code excerpt written by a colleague that is no longer working with us. I have questions as to why this code was written in this way and not any other. My impression of the colleague is a very good one, he was one of the few people capable of compiling C++ code in his head.
#include <boost/smart_ptr.hpp>
namespace boost
{
/*****************************************
class RefCounter
{
protected:
RefCounter() : m_refCount(0) {}
virtual ~RefCounter() { }
private:
friend void intrusive_ptr_release(RefCounter * p);
friend void intrusive_ptr_add_ref(RefCounter * p);
volatile long m_refCount;
virtual void incRef() {__sync_add_and_fetch(&m_refCount, 1);}
virtual void decRef() {if (__sync_sub_and_fetch(&m_refCount, 1) == 0) delete this;}
};
inline void intrusive_ptr_add_ref(RefCounter * p)
{
p->incRef();
}
inline void intrusive_ptr_release(RefCounter * p)
{
p->decRef();
}
************************************************/
class RefCounter
{
protected:
RefCounter() : m_refCount(0) {}
RefCounter(const RefCounter&) : m_refCount(0) {}
virtual ~RefCounter() {}
long getRefCount() const {return m_refCount;}
private:
friend void intrusive_ptr_release(RefCounter * p);
friend void intrusive_ptr_add_ref(RefCounter * p);
volatile long m_refCount;
};
inline void intrusive_ptr_add_ref(RefCounter * p)
{
__sync_add_and_fetch(&p->m_refCount, 1);
}
inline void intrusive_ptr_release(RefCounter * p)
{
if (__sync_sub_and_fetch(&p->m_refCount, 1) == 0) delete p;
}
} // namespace boost
Example of use:
struct Foo : public boost::RefCounter
{
int a;
};
typedef boost::intrusive_ptr<Foo> FooIntrusivePtr;
FooIntrusivePtr fooPtr;
My questions are the following:
Why use friend
keywords? Why not declare the functions public?
Why use volative
keyword? Where and why could the compiler aggressively optimize this value? Or was this keyword merely used as a precaution?
And as a bonus, why was the previous approach (commented out) replaced with the existing code? Was something wrong with the previous approach, a bug or special scenario which did not work as intended?
Much appreciated.
Upvotes: 1
Views: 281
Reputation: 4034
The functions are marked friend
so that they can edit the m_refCount
member variable of the class even though it's private and the functions are not part of the class itself.
The volatile
keyword as well as why it's using the __sync_
functions is to allow this implementation to work in a multi-threaded environment without using a mutex.
Upvotes: 3