Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Object access synchronization using Reference Counting

1 view
Skip to first unread message

Banibrata Dutta

unread,
Jun 1, 2002, 12:59:55 AM6/1/02
to
hi:

can someone please clarify why do we need to do reference counting on
objects, especially when same object's reference / pointer is used
within multiple threads ? why can't a mutext suffice ? any thread that
needs to read/write the object first locks the mutex, and that way we
are always sure that the object is being read or written only by the
thread that could lock it ?

to me looks like the only reason to keep reference count associated
with such a shared object is to check/control it's life-time, i.e. if
a thread creates it, and other threads access it, only given that the
object is alive, then the reference count can help. especially if the
ref-count variable itself is part of the Object in question, since in
that case deleting the object by one thread, would cause another
thread trying to get a lock on the mutex, itself would cause a SEGV as
the Object itself (containing this mutex) is dead.

is this the only use ? or does it assist in some other way ? is there
any standard design-pattern for this type of use ?

thanks,
banibrata dutta.

Alexander Terekhov

unread,
Jun 1, 2002, 9:18:42 AM6/1/02
to

Banibrata Dutta wrote:
>
> hi:
>
> can someone please clarify why do we need to do reference counting on
> objects, especially when same object's reference / pointer is used
> within multiple threads ? why can't a mutext suffice ? any thread that
> needs to read/write the object first locks the mutex, and that way we
> are always sure that the object is being read or written only by the
> thread that could lock it ?

Well, you don't really need a 'mutex' (in the sense of a sync.device
for mutual exclusion AND memory coherency/visibility protocol via
lock/unlock) for the objects that are IMMUTABLE -- only the ref.count
itself needs to be made 'atomic' w.r.t. '++' and '--'. More 'info'
on this can be found here:

http://groups.google.com/groups?threadm=3BC8463D.6E23002A%40web.de
("Subject: Lockless/non-blocking ref.counting?"; note that unref()
needs to inject write/"release" mem.bars too... IF threads could
unref() mutable objects INSIDE synchronized regions for mutation/
updates)

> to me looks like the only reason to keep reference count associated
> with such a shared object is to check/control it's life-time, i.e. if
> a thread creates it, and other threads access it, only given that the
> object is alive, then the reference count can help. especially if the
> ref-count variable itself is part of the Object in question, since in
> that case deleting the object by one thread, would cause another
> thread trying to get a lock on the mutex, itself would cause a SEGV as
> the Object itself (containing this mutex) is dead.
>
> is this the only use ?

I think so; 'automatic' lifetime management; that's it.

> or does it assist in some other way ?

I don't think so. Well, The only possibly useful scenario I could think
of is that some thread which passes some ref.counted object to another
thread(s) would want to wait for ref.count to come back to ONE again
(indicating that other thread(s) has unref-ed the object and that waiting
thread is the only one thread who is left holding the reference to the
object). But having some predicate(s) and >>signaling<< over the ref.count
would have a rather undesirable performance impact w.r.t. usual/'normal'
usage pattern/purpose, I think.

> is there any standard design-pattern for this type of use ?

Uhmm. Probably something along the lines of (locking granularity
aside):

class RefCounted {
protected:

RefCounted() : m_mutex(), m_count( 1 )
{ }

~RefCounted()
{ assert( 0 == m_count ); }

private:

friend class SOME_SMART_PTR; // <- calls ref/unref

typedef int Count;

void ref()
{ Guard guard( m_mutex ); assert( m_count < s_max ); ++m_count; }

int unref()
{ Guard guard( m_mutex ); assert( m_count > 0 ); return --m_count; }

Mutex m_mutex;
Count m_count;

static const Count s_max; // INT_MAX or something similar

};

and for your ref.counting 'smart pointer':

ChunkPtr::ChunkPtr() : m_pChunk( 0 )
{ }

ChunkPtr::ChunkPtr(size_t size) : m_pChunk( new Chunk( size ) )
{ }

ChunkPtr::ChunkPtr(const ChunkPtr& c) : m_pChunk( c.m_pChunk )
{ if ( 0 != m_pChunk ) m_pChunk->ref(); }

ChunkPtr::~ChunkPtr()
{ if ( 0 != m_pChunk && 0 == m_pChunk->unref() ) delete m_pChunk; }

void ChunkPtr::swap(ChunkPtr& c) throw()
{ Chunk* p = m_pChunk; m_pChunk = c.m_pChunk; c.m_pChunk = p; }

ChunkPtr& ChunkPtr::operator=(ChunkPtr temp)
{ temp.swap( *this ); return *this; }

You may also want to check out boost.org's and Loki's
smart/'shared' pointers...

regards,
alexander.

Mark Johnson

unread,
Jun 3, 2002, 9:41:37 AM6/3/02
to
Banibrata Dutta wrote:
>
> hi:
>
> can someone please clarify why do we need to do reference counting on
> objects, especially when same object's reference / pointer is used
> within multiple threads ? why can't a mutext suffice ? any thread that
> needs to read/write the object first locks the mutex, and that way we
> are always sure that the object is being read or written only by the
> thread that could lock it ?
>
I'll try a slightly simpler answer.
- You do not need to do reference counting of objects.
From what you say here [and in the next paragraph - snipped] is you DO
want to create an object, use the object, and destroy [or in your words
delete] the object after all use is complete. There are several ways you
can do this including...
- create the object & never destroy it
- use reference counters
- use garbage collection
- follow a coding style where the object is created, used, and
destroyed in sequence
As well as a variety of other methods.

There are obvious benefits and drawbacks from each approach I described.
I am not sure what "threads" has to do with this though. You could have
asked this same question in comp.programming.c++ or another language
specific news group and received a good answer there as well.
--Mark
PS: The classical reason reference counting is not "good enough" to
recover storage after use is a circular list.

0 new messages