Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Thread-safe reference counts.

Reply
Thread Tools

Thread-safe reference counts.

 
 
Chris Thomasson
Guest
Posts: n/a
 
      03-28-2008

"David Schwartz" <> wrote in message
news:9ee8ea51-7f0e-4733-801e-...
>
>> This just means, that you are making a copy of an object where the
>> destructor is in progress. That's simply a bug and should be avoided
>>
>> best regards,
>> Torsten

>
> I agree. I would put it simply -- you cannot call 'AddRef' unless you
> have an explicit or implicit reference to an object. The 'AddRef'
> function is not special, it must be called with a reference just like
> every other function.
>
> The puzzle is this -- how did you get a pointer to object to call
> 'AddRef' on anyway?


This paper explains the puzzle, and a soultion:

http://citeseer.ist.psu.edu/cache/pa...01lockfree.pdf




> I've heard a lot of talk about strong thread safety and the like, but
> I have to admit, I don't get it. In order to call 'AddRef' on an
> object, you need a pointer to it, and how could you possibly have
> gotten that pointer without something that already had a reference?


Think of the following scenario:
__________________________________________________
static atomic_ptr<foo> g_foo;

void writers() {
for(; {
local_ptr<foo> l_foo(new foo);
g_foo = l_foo;
}
}


void readers() {
for(; {
local_ptr<foo> l_foo(g_foo);
if (l_foo) {
l_foo->do_something();
}
}
}
__________________________________________________




Notice how the reader thread can grab a reference from 'g_foo' without
having a previous reference to an object contained within it? You can
download the sourcecode of atomic_ptr from:

http://sourceforge.net/project/showf...roup_id=127837
(atomic-ptr-plus package)


Also, you can take a look at the source code for my proxy garbage collector:

http://appcore.home.comcast.net/misc...mple_h_v1.html

The function that allows any thread to grab a reference to the current
region is 'pc_acquire()':
__________________________________________________
pc_region*
pc_acquire(
pc_master* const _this
) {
pc_sys_anchor cmp = _this->head, xchg;
do {
xchg.refcnt = cmp.refcnt + 2;
xchg.region = cmp.region;
} while (! DWCASPTR(&_this->head, &cmp, &xchg));
return cmp.region;
}
__________________________________________________




Notice how it updates the counter and grabs a pointer to the current region
in a single atomic operation (e.g., DWCAS-loop)? This is another solution to
your puzzle.




> The existence of a pointer should mean the existence of a reference --
> otherwise how can you know that pointer remains valid, whether a call
> for AddRef or for any other purpose?


You need to load a pointer and increment the reference count in a single
atomic operation.

 
Reply With Quote
 
 
 
 
Chris Thomasson
Guest
Posts: n/a
 
      03-28-2008

"Alexander Terekhov" <> wrote in message
news:...
>
> David Schwartz wrote:
>>
>> > This just means, that you are making a copy of an object where the
>> > destructor is in progress. That's simply a bug and should be avoided
>> >
>> >
>> > best regards,
>> > Torsten

>>
>> I agree. I would put it simply -- you cannot call 'AddRef' unless you
>> have an explicit or implicit reference to an object. The 'AddRef'
>> function is not special, it must be called with a reference just like
>> every other function.
>>
>> The puzzle is this -- how did you get a pointer to object to call
>> 'AddRef' on anyway?
>>
>> I've heard a lot of talk about strong thread safety and the like, but
>> I have to admit, I don't get it. In order to call 'AddRef' on an
>> object, you need a pointer to it, and how could you possibly have
>> gotten that pointer without something that already had a reference?
>>
>> The existence of a pointer should mean the existence of a reference --
>> otherwise how can you know that pointer remains valid, whether a call
>> for AddRef or for any other purpose?

>
> See
>
> http://www.open-std.org/JTC1/SC22/WG...97.html#atomic


AFAICT, it seems like they are seriously considering making shared_ptr
strongly thread-safe. Well, IMVHO, that would greatly enhance its
functionality. Nice!

Thanks for pointing this out.

 
Reply With Quote
 
 
 
 
Chris Thomasson
Guest
Posts: n/a
 
      03-28-2008
"David Schwartz" <> wrote in message
news:9ee8ea51-7f0e-4733-801e-...
>
>> This just means, that you are making a copy of an object where the
>> destructor is in progress. That's simply a bug and should be avoided
>>
>> best regards,
>> Torsten

>
> I agree. I would put it simply -- you cannot call 'AddRef' unless you
> have an explicit or implicit reference to an object. The 'AddRef'
> function is not special, it must be called with a reference just like
> every other function.
>
> The puzzle is this -- how did you get a pointer to object to call
> 'AddRef' on anyway?
>
> I've heard a lot of talk about strong thread safety and the like, but
> I have to admit, I don't get it. In order to call 'AddRef' on an
> object, you need a pointer to it, and how could you possibly have
> gotten that pointer without something that already had a reference?
>
> The existence of a pointer should mean the existence of a reference --
> otherwise how can you know that pointer remains valid, whether a call
> for AddRef or for any other purpose?


Here is some code you can look at which implements strongly thread-safe
reference counting:


http://groups.google.com/group/comp....0ad3154c08d9dd


The 'foo_obj_acquire/release()' functions is where all the magic take place:
__________________________________________________ ____________________
foo_obj* foo_obj_acquire(foo_obj** psrc) {
foo_obj* _this;
pc_region* const pcr = pc_acquire(&g_pcm);
if (_this = LOADPTR(psrc)) {
atomicword cmp = _this->refcnt;
do {
if (! cmp) {
_this = NULL;
break;
}
} while(! CASWORD(&_this->refcnt, &cmp, cmp + 1));
}
pc_release(pcr);
return _this;
}


void foo_obj_release(foo_obj* _this) {
if (XADDWORD(&_this->refcnt, -1) == 1) {
pc_mutate(&g_pcm, &_this->pcn);
}
}
__________________________________________________ ____________________




Any thread can call 'foo_obj_acquire()' to grab a reference from a pointer
to a 'foo_obj*'. The following setup is perfectly legal:
__________________________________________________ ___________________
static foo_obj* g_foo = NULL;


void reader_threads(void) {
for (; {
foo_obj* const _this = foo_obj_acquire(&g_foo);
if (_this) {
foo_obj_release(_this);
}
}
}


void writer_threads(void) {
for (; {
foo_obj* const _this = foo_obj_ctor();
if (_this) {
foo_obj* prev = foo_obj_swap(&g_foo, _this);
if (prev) {
foo_obj_release(prev);
}
}
}
}
__________________________________________________ ___________________



reader threads can acquire reference's to 'foo_obj' objects on the fly,
without having to own a previous reference to them.

 
Reply With Quote
 
coal@mailvault.com
Guest
Posts: n/a
 
      03-28-2008
On Mar 27, 3:14*pm, gpderetta <gpdere...@gmail.com> wrote:
> On Mar 27, 9:42 pm, c...@mailvault.com wrote:


> > I think some Boost libraries are better than others though.http://www.webEbenezer.net/comparison.html

>
> Use an std::vector (or boost::array) instead of std::deque or
> std::list for applications where serialization performance is
> critical.
>


If it is vector of non POD I think the test results would be
simlar to the list<> results. I can test that if need be.
Both Boost (1.35 if I'm not mistaken) and Ebenezer (since
2006) have optimizations wrt vectors of built-in types like
vector<int>. I disagree with advice that says avoid deques
and lists if they would be used in a serialization context
where performance is important. Serialization is just one
factor that should be considered in choosing the best container for a
given context.

I'm glad you mentioned boost::array. It had slipped off my
radar and I want to investigate the possibility of supporting
it.

Brian
 
Reply With Quote
 
Chris Thomasson
Guest
Posts: n/a
 
      03-28-2008
"Chris Thomasson" <> wrote in message
news:. ..
>
> "Alexander Terekhov" <> wrote in message
> news:...
>>
>> David Schwartz wrote:
>>>
>>> > This just means, that you are making a copy of an object where the
>>> > destructor is in progress. That's simply a bug and should be avoided
>>> >
>>> >
>>> > best regards,
>>> > Torsten
>>>
>>> I agree. I would put it simply -- you cannot call 'AddRef' unless you
>>> have an explicit or implicit reference to an object. The 'AddRef'
>>> function is not special, it must be called with a reference just like
>>> every other function.
>>>
>>> The puzzle is this -- how did you get a pointer to object to call
>>> 'AddRef' on anyway?
>>>
>>> I've heard a lot of talk about strong thread safety and the like, but
>>> I have to admit, I don't get it. In order to call 'AddRef' on an
>>> object, you need a pointer to it, and how could you possibly have
>>> gotten that pointer without something that already had a reference?
>>>
>>> The existence of a pointer should mean the existence of a reference --
>>> otherwise how can you know that pointer remains valid, whether a call
>>> for AddRef or for any other purpose?

>>
>> See
>>
>> http://www.open-std.org/JTC1/SC22/WG...97.html#atomic

>
> AFAICT, it seems like they are seriously considering making shared_ptr
> strongly thread-safe. Well, IMVHO, that would greatly enhance its
> functionality. Nice!
>
> Thanks for pointing this out.


I seems like they are going for something that is analogous to Java
references. Finally, strong thread-safety is being taken seriously.

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      03-28-2008
On Mar 27, 9:42 pm, c...@mailvault.com wrote:
> On Mar 27, 8:12 am, gpderetta <gpdere...@gmail.com> wrote:


> > On Mar 27, 12:13 pm, Sam <s...@email-scan.com> wrote:


> > > Yannick Tremblay writes:
> > > > Sam <s...@email-scan.com> wrote:


> > > >>That's whatBoost'sshared_ptr does. Although -- much like
> > > >>the rest of Boost'scode -- it is horribly inefficient,
> > > >>and suffers from certain design flaws -- it is often a
> > > >>good starting point for your own reference-counted
> > > >>pointers.


> > Like the rest ofBoost'scode? That's not my experience.


> I think some Boost libraries are better than others though.


Certainly. And none of them (no more than any other code
written by human beings) are perfect. In general, though, the
more intensely used the library, the better the chances are that
it is pretty good, or even better. The Boost smart pointers are
amongst the most widely used Boost library, and should certainly
be your first choice if you need smart pointers. (I think that
smart pointers are often overused, but that's a different
issue.) After that, as with any library, you may find that they
don't exactly meet your needs, and you need a custom component.
But writing one yourself until you're sure that it's necessary
is just stupid. (Especially if you're looking for something
very difficult to get right, like a reference counted pointer
which works in a multi-threaded environment.)

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
coal@mailvault.com
Guest
Posts: n/a
 
      03-28-2008
On Mar 28, 5:19*am, James Kanze <james.ka...@gmail.com> wrote:
> On Mar 27, 9:42 pm, c...@mailvault.com wrote:
>
> > On Mar 27, 8:12 am, gpderetta <gpdere...@gmail.com> wrote:
> > > Like the rest ofBoost'scode? That's not my experience.

> > I think some Boost libraries are better than others though.

>
> Certainly. *And none of them (no more than any other code
> written by human beings) are perfect. *In general, though, the
> more intensely used the library, the better the chances are that
> it is pretty good, or even better. *The Boost smart pointers are
> amongst the most widely used Boost library, and should certainly
> be your first choice if you need smart pointers. *


OK, but auto_ptr should be mentioned and considered before
the Boost options.

> (I think that
> smart pointers are often overused, but that's a different
> issue.)


I agree that they're used too much.


Brian
 
Reply With Quote
 
Jon Harrop
Guest
Posts: n/a
 
      03-28-2008
wrote:
> I have some code where objects are dynamically allocated by some
> thread, and then used by multiple threads and freed when they are no
> longer needed. I think that reference counting is the most appropriate
> way to handle this in my situation.


A concurrent garbage collector is the appropriate way to handle that
situation.

--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/products/?u
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      03-28-2008
Jon Harrop wrote:
> wrote:
>> I have some code where objects are dynamically allocated by some
>> thread, and then used by multiple threads and freed when they are no
>> longer needed. I think that reference counting is the most appropriate
>> way to handle this in my situation.

>
> A concurrent garbage collector is the appropriate way to handle that
> situation.
>

One possible way, reference counted objects work just as well.

--
Ian Collins.
 
Reply With Quote
 
Chris Thomasson
Guest
Posts: n/a
 
      03-28-2008

"Jon Harrop" <> wrote in message
news:...
> wrote:
>> I have some code where objects are dynamically allocated by some
>> thread, and then used by multiple threads and freed when they are no
>> longer needed. I think that reference counting is the most appropriate
>> way to handle this in my situation.

>
> A concurrent garbage collector is the appropriate way to handle that
> situation.


Why? There are many different ways to handle lifetime management.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ASP.NET 2.0: master pages and web user controls: reference to a non-shared member requires an object reference bminder ASP .Net 0 06-24-2005 12:22 AM
asp.net 2005 question re: "reference to a non-shared member requires an object reference" ce ASP .Net 1 06-23-2005 09:15 PM
web reference interfering with reference to component Dude ASP .Net 0 11-09-2004 11:53 AM
How to tell if a reference is project or file reference from within the IDE? Darren ASP .Net 0 10-11-2004 12:51 AM
Passing the value by reference is same as pointer by reference sam pal C++ 3 07-16-2003 09:14 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57