Re: Garbage Collection - The Trash Begins To Pile Up
Andreas Huber wrote:
Peter Dimov wrote:
Andreas Huber wrote:
Moreover, Hans Boehm has shown that under certain circumstances
shared_ptr is unable to release resources correctly even if there
are no cycles ...
<http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html> (see
Appendix B)
.... due to the fact that the release takes place in the thread that
held the last reference to the resource. IIUC, then certain
circumstances *require* non-deterministic release. In other words,
RAII coupled with reference-counting is no silver bullet either.
The problem with this code:
void C::update(boost::shared_ptr<has_foo> other) {
boost::mutex::scoped_lock scoped_lock(mutex);
int count = impl_use_count[my_index];
long new_val = combine(impls[my_index] -> get_data(),
X::messy_fn(other));
if (count > 1) {
// Clone my C_impl.
int new_index = first_available();
impl_use_count[new_index] = 1;
impls[new_index] = new C_impl(new_val);
--impl_use_count[my_index];
my_index = new_index;
} else {
impls[my_index]->set_data(new_val);
}
}
is that it calls a "messy function" while holding a lock.
Right, but under the given circumstances I can see why a programmer
would go the path of least resistance and just lock before the call to
combine. From Hans's description the programmer is not aware that
messy_fn might acquire a lock (for what we know that could not have been
known by messy_fn's programmer himself). The programmer might also not
know that messy_fn is expensive.
It is a well-known property of locks that they don't tolerate this kind
of thinking. You _have_ to know what happens while you are holding a
lock (and if you don't - as can happen when you invoke a callback - the
outside code must know that you are calling it under a lock and not
call you back). (Herb Sutter argues that this makes lock-based
programming inherently non-scalable.)
As the author acknowledges, there are ways around the problem, no doubt
about that. But these only become apparent when you have a look at
messy_fn's implementation. That is, it seems you need to break the
abstraction created by messy_fn, although messy_fn does not do anything
unreasonable.
The original code implicitly depends on implementation details of
messy_fn: it being quick and not acquiring the C lock. This breaks the
abstraction layer.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]