atomic_count::operator++ return type

Hi, Some of the implementations of boost::detail::atomic_count::operator++ return a long (vg. Win32) while for others the return type is void. Is it feasible to change this so that a long (i.e. the value of the atomic count after incrementing) is returned always? As it happens, I have a usage case for this in Boost.Flyweight. Thanks in advance. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN M. LOPEZ MUÑOZ:
Hi,
Some of the implementations of boost::detail::atomic_count::operator++ return a long (vg. Win32) while for others the return type is void. Is it feasible to change this so that a long (i.e. the value of the atomic count after incrementing) is returned always? As it happens, I have a usage case for this in Boost.Flyweight.
What memory visibility guarantees does your use case need? op++ returns no value because it currently promises no visibility guarantees.

________________________________________ De: boost-bounces@lists.boost.org [boost-bounces@lists.boost.org] En nombre de Peter Dimov [pdimov@pdimov.com] Enviado el: viernes, 10 de abril de 2009 19:21 Para: boost@lists.boost.org Asunto: Re: [boost] atomic_count::operator++ return type JOAQUIN M. LOPEZ MUÑOZ:
Hi,
Some of the implementations of boost::detail::atomic_count::operator++ return a long (vg. Win32) while for others the return type is void. Is it feasible to change this so that a long (i.e. the value of the atomic count after incrementing) is returned always? As it happens, I have a usage case for this in Boost.Flyweight.
What memory visibility guarantees does your use case need? op++ returns no value because it currently promises no visibility guarantees.
I'm afraid I don't quite get what you mean exactly by memory visibility in this context: I guess I need the same behavior (mutatis mutandis) as given by op--. In case it sheds some light, the usage case I talk about can be taken a a look at https://svn.boost.org/trac/boost/browser/trunk/boost/flyweight/refcounted.hp... The protocol is a classical refcounting mechanism with a twist due to the possiblity that values are retrieved even if their recount drops to zero. There code's rationale is commented, but don't hesitate to ask if something's not clear. Of course I wouldn't need the extension to op++ if there's an alternative manner to implement the protocol . Thank you, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN M. LOPEZ MUÑOZ:
I'm afraid I don't quite get what you mean exactly by memory visibility in this context: I guess I need the same behavior (mutatis mutandis) as given by op--. In case it sheds some light, the usage case I talk about can be taken a a look at
https://svn.boost.org/trac/boost/browser/trunk/boost/flyweight/refcounted.hp...
The protocol is a classical refcounting mechanism with a twist due to the possiblity that values are retrieved even if their recount drops to zero.
I'm not sure how this works... what is TrackingEntry? How do you handle the possibility of - thread A detaches the last reference, calls erase, erase calls check_erase, gets true, and is preempted; - thread B attaches a reference; - thread A resumes and deletes the object.

________________________________________ De: boost-bounces@lists.boost.org [boost-bounces@lists.boost.org] En nombre de Peter Dimov [pdimov@pdimov.com] Enviado el: sábado, 11 de abril de 2009 2:15 Para: boost@lists.boost.org Asunto: Re: [boost] atomic_count::operator++ return type
JOAQUIN M. LOPEZ MUÑOZ:
I'm afraid I don't quite get what you mean exactly by memory visibility in this context: I guess I need the same behavior (mutatis mutandis) as given by op--. In case it sheds some light, the usage case I talk about can be taken a a look at
https://svn.boost.org/trac/boost/browser/trunk/boost/flyweight/refcounted.hp...
The protocol is a classical refcounting mechanism with a twist due to the possiblity that values are retrieved even if their recount drops to zero.
I'm not sure how this works... what is TrackingEntry?
It is a façade to the functionality provided by the rest of Boost.Flyweight for the use of the refcounting mechanism: http://www.boost.org/libs/flyweight/doc/reference/tracking.html#tracking * TrackingHelper::entry(h) returns the value to which the refcounted_handle h refers (which is implicitly convertible to a refcounted_value). Think of it as a dereference operator. * TrackingHelper::erase(h,check_erase) deletes the value refered to by h iff check_erase(h) returns true. The execution of this routine happens in a locked context (including the call to check_erase and erasure itself). * Though it may not be apparent, the execution of explicit refcounted_handle(const Handle&) also happens in a locked context (this is important to the implementation of the refcounting protocol).
How do you handle the possibility of
- thread A detaches the last reference, calls erase, erase calls check_erase, gets true, and is preempted;
This cannot happen as check_erase is invoked in a locked context. The critical point where preemption can occur is between detaching of the last reference and execution of erase, which is precisely what the del_ref member variable keeps tracks of; if A resumes after preemption and the value has acquired a new reference the count of deleters will be >0 and check_delete will return false. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN M. LOPEZ MUÑOZ: ...
https://svn.boost.org/trac/boost/browser/trunk/boost/flyweight/refcounted.hp...
* TrackingHelper::entry(h) returns the value to which the refcounted_handle h refers (which is implicitly convertible to a refcounted_value). Think of it as a dereference operator.
* TrackingHelper::erase(h,check_erase) deletes the value refered to by h iff check_erase(h) returns true. The execution of this routine happens in a locked context (including the call to check_erase and erasure itself).
* Though it may not be apparent, the execution of explicit refcounted_handle(const Handle&) also happens in a locked context (this is important to the implementation of the refcounting protocol).
Thanks. I think I see it now. Although... I may be missing something, but why doesn't the simple explicit refcounted_handle(const Handle& h_):h(h_) { TrackingHelper::entry(*this).add_ref(); } static bool check_erase(const refcounted_handle& x) { return TrackingHelper::entry(x).count() == 0; } work?

________________________________________ De: boost-bounces@lists.boost.org [boost-bounces@lists.boost.org] En nombre de Peter Dimov [pdimov@pdimov.com] Enviado el: domingo, 12 de abril de 2009 0:58 Para: boost@lists.boost.org Asunto: Re: [boost] atomic_count::operator++ return type
Thanks. I think I see it now.
Although... I may be missing something, but why doesn't the simple
explicit refcounted_handle(const Handle& h_):h(h_) { TrackingHelper::entry(*this).add_ref(); }
static bool check_erase(const refcounted_handle& x) { return TrackingHelper::entry(x).count() == 0; }
work?
This does not work because of scenarios like the following: 1. Thread A detaches the last reference to x and is preempted when it's about to enter erase. 2. Thread B retrieves x so that its refcount is now 1. After some work with x, thread B detaches the reference to x, whose refcount drops again to zero, enters erase and eliminates x. 3. Thread A resumes, but erase now attempts to work with a nonexistent x. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN M. LOPEZ MUÑOZ:
This does not work because of scenarios like the following:
1. Thread A detaches the last reference to x and is preempted when it's about to enter erase. 2. Thread B retrieves x so that its refcount is now 1. After some work with x, thread B detaches the reference to x, whose refcount drops again to zero, enters erase and eliminates x. 3. Thread A resumes, but erase now attempts to work with a nonexistent x.
Here by x you mean the refcounted_value, I guess. Yes, this doesn't work if 'Handle' is a raw pointer, for example. I think, however, that it does work if erase doesn't need to dereference the handle in order to see that it's already been removed.

________________________________________ De: boost-bounces@lists.boost.org [boost-bounces@lists.boost.org] En nombre de Peter Dimov [pdimov@pdimov.com] Enviado el: domingo, 12 de abril de 2009 15:24 Para: boost@lists.boost.org Asunto: Re: [boost] atomic_count::operator++ return type JOAQUIN M. LOPEZ MUÑOZ:
This does not work because of scenarios like the following:
1. Thread A detaches the last reference to x and is preempted when it's about to enter erase. 2. Thread B retrieves x so that its refcount is now 1. After some work with x, thread B detaches the reference to x, whose refcount drops again to zero, enters erase and eliminates x. 3. Thread A resumes, but erase now attempts to work with a nonexistent x.
Here by x you mean the refcounted_value, I guess. Yes, this doesn't work if 'Handle' is a raw pointer, for example. I think, however, that it does work if erase doesn't need to dereference the handle in order to see that it's already been removed.
I don't see a way that erase can know that in a reasonably efficient way --Handle is usually an iterator, you know. But maybe we're diverting off a bit. Given the current constraints, I've got a protocol that could be implemented with an extension to the interface of atomic_count::op++. Is this a reasonable thing to ask, or are there unavoidable obstacles to have it? Rereading the internal documentation of atomic_count, I see that op-- returns 0 if the new value is zero and something else otherwise. In the same fashion, it'll probably suffice with an op++ that returns 0 if *the value before incrementing* was zero, and something else otherwise, so it'd behave like a post increment, not exactly what we have now. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

JOAQUIN M. LOPEZ MUÑOZ:
But maybe we're diverting off a bit. Given the current constraints, I've got a protocol that could be implemented with an extension to the interface of atomic_count::op++. Is this a reasonable thing to ask, or are there unavoidable obstacles to have it?
It is reasonable.

Peter Dimov escribió:
JOAQUIN M. LOPEZ MUÑOZ:
But maybe we're diverting off a bit. Given the current constraints, I've got a protocol that could be implemented with an extension to the interface of atomic_count::op++. Is this a reasonable thing to ask, or are there unavoidable obstacles to have it?
It is reasonable.
Great! Thank you for your consideration. Shall I put a ticket for this? Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
participants (3)
-
JOAQUIN M. LOPEZ MUÑOZ
-
joaquin@tid.es
-
Peter Dimov