Topic: Implicit reference count for shared_future?


Author: Scott Meyers <usenet@aristeia.com>
Date: Fri, 3 Jul 2009 09:15:21 CST
Raw View
  From what I can tell, the value referenced by a shared_future must exist as
long as at least one shared_future object refers to it.  These values take up
space somewhere, presumably on the heap or in memory for objects of static
storage duration (which, now that I think of it, even then would probably have
to be managed dynamically for values referred to by shared_futures).
Presumably, an implementation would like to release the memory occupied by
values to which no shared_futures refer, and that suggests that such values are
reference-counted.  Further, such reference counts would be shared across
threads and thus have to be protected against simultaneous access, presumably
via use of atomic types manipulated by atomic machine instructions.

None of this would be visible to users (i.e., part of the abstract machine
specified by C++), but if my analysis above is correct, it suggests that use of
shared_futures can be much more expensive than use of unique_futures.  Am I
correct?  Is it reasonable to assume that use of shared_future implies use of an
implicit thread-safe reference count for each object referred to by a
shared_future?

Thanks,

Scott

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Anthony Williams <anthony.ajw@gmail.com>
Date: Fri, 3 Jul 2009 14:00:38 CST
Raw View
Scott Meyers <usenet@aristeia.com> writes:

>  From what I can tell, the value referenced by a shared_future must exist as
> long as at least one shared_future object refers to it.  These values take up
> space somewhere, presumably on the heap or in memory for objects of static
> storage duration (which, now that I think of it, even then would probably have
> to be managed dynamically for values referred to by shared_futures).
> Presumably, an implementation would like to release the memory occupied by
> values to which no shared_futures refer, and that suggests that such values are
> reference-counted.  Further, such reference counts would be shared across
> threads and thus have to be protected against simultaneous access, presumably
> via use of atomic types manipulated by atomic machine instructions.

That is correct.

> None of this would be visible to users (i.e., part of the abstract machine
> specified by C++), but if my analysis above is correct, it suggests that use of
> shared_futures can be much more expensive than use of unique_futures.  Am I
> correct?  Is it reasonable to assume that use of shared_future implies use of an
> implicit thread-safe reference count for each object referred to by a
> shared_future?

I don't see that it follows that shared_future is "much more expensive"
than unique_future. For one thing, the data structure referenced by a
unique_future is also referenced by the promise or packaged_task that is
used to set the value, which may be in another thread. You want the
internal data structure to be destroyed when the last of the
unique_future and promise/packaged_task is destroyed. There are
basically the same requirements here, so the cost of the atomic
reference count is already paid and shared_future is no more expensive
than unique_future.

Note that this is different to unique_ptr/shared_ptr where the reference
count for the shared_ptr has to be allocated separately from the
pointed-to object in the general case --- this is an internal data
structure so the reference count can be allocated alongside the buffer
for the value.

Anthony
--
Author of C++ Concurrency in Action | http://www.manning.com/williams
just::thread C++0x thread library   | http://www.stdthread.co.uk
Just Software Solutions Ltd         | http://www.justsoftwaresolutions.co.uk
15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK. Company No. 5478976

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 3 Jul 2009 14:01:09 CST
Raw View
On Jul 3, 11:15 am, Scott Meyers <use...@aristeia.com> wrote:

> ... but if my analysis above is correct, it suggests that use of
> shared_futures can be much more expensive than use of unique_futures.  Am I
> correct?  Is it reasonable to assume that use of shared_future implies use of an
> implicit thread-safe reference count for each object referred to by a
> shared_future?

It is reasonable to assume the refcount.  However I do not believe
that this refcount will be a significant cost.  Indeed, you can
probably expect one under unique_future as well, which must coordinate
one thread setting a value with another thread getting the value (or
abandoning it).  In this latter case, the refcount is restricted to
counts of 0, 1 or 2, so it may also be that an implementation could
specialize for that.  However that specialization may not buy you much
as you still must be able to convert an rvalue unique_future to a
shared_future (the underlying refcount can then grow above 2).

But you are headed in the right direction.  unique_future exists for
performance reasons.

See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2094.html
and search for "The resulting timings are".

This small test looks at the overhead of returning a vector<int>
(100000) from a factory function.  The test tries returning it from an
ordinary function, from a unique_future (called "task" in this paper)
and from shared_future (called "future" in this paper).  All of the
runs are on a single processor machine.  The only thing being measured
is overhead.  The gold standard is the ordinary function call which
returns the vector via RVO.  Had the RVO failed, the vector would have
been returned via a move, which would be nearly as fast (possibly not
a measurable difference).

The unique_future (task) allows for the vector to be returned via a
move.  The shared_future (future) requires that the vector be returned
via a copy.  If you only need the vector in one place, one time, then
obtaining it via a move is significantly faster (as the numbers in the
paper show).

The cost of the use of atomics is significant and should not be
discarded.  But the cost of atomics pales in comparison to the cost of
allocating and deallocating memory.  Move semantics (unique_future) is
about avoiding the heap altogether.

And (indirectly referencing another current thread on comp.std.c++),
perfect forwarding is about ensuring that move semantics happens in as
many places as possible.  The two work together synergistically.  If
you can't perfectly forward an rvalue (as an rvalue), then you can't
move from it in the forwarded-to context, and you'll subsequently make
unnecessary accesses to the heap for types like vector and string.

-Howard


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Mathias Gaunard <loufoque@gmail.com>
Date: Sun, 5 Jul 2009 00:26:30 CST
Raw View
On 3 juil, 17:15, Scott Meyers <use...@aristeia.com> wrote:

> None of this would be visible to users (i.e., part of the abstract machine
> specified by C++), but if my analysis above is correct, it suggests that use of
> shared_futures can be much more expensive than use of unique_futures.  Am I
> correct?  Is it reasonable to assume that use of shared_future implies use of an
> implicit thread-safe reference count for each object referred to by a
> shared_future?

shared_future is to unique_future what shared_ptr is to unique_ptr.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]