|
Boost : |
From: William Kempf (sirwillard_at_[hidden])
Date: 2000-11-27 17:01:37
--- In boost_at_[hidden], Douglas Gregor <gregod_at_r...> wrote:
> On Thu, 23 Nov 2000 14:45:57 -0000
> "William Kempf" <sirwillard_at_m...> wrote:
>
> [snip]
> > *shrug*
> >
> > I'm *slightly* leaning towards cloning instead of ref-counting at
> > this point. In general it's safer, and as pointed out, when this
>
> In general cloning is safer, but statics, pointers, references, and
data members are all unsafe even with cloning. My general fear is
that we are guaranteeing too much by calling cloning safe in
multithreaded environments (and then listing all of the exceptions).
Instead, I would suggest that we use reference-counting and
explicitly state that the function object must itself be thread-safe
to guarantee thread safety. I also expect that any Boost threads
library would contain a function object adaptor to mutex any function
object. This makes it the user's responsibility to make a function
object thread-safe, but at least it is stated that it is never safe
to assume thread-safety.
Obviously the function object itself must be thread safe, regardless
of copying semantics. I wasn't discussing such things, however, only
the act of copying. Copying using ref-counting is problematic, while
cloning is generally safer (provided the "clone" routine is thread
safe... which may be an argument yet again in favor of ref-counting,
where the thread safety can be externalized).
> Also, I've been trying to consider how often cloning would be more
thread-safe than ref-counting, and as far as I can see these are the
most common uses of function objects:
> 1) Wrapping free and member functions (e.g., ptr_fun)
> 2) Performing some operation on the arguments and returning
the result (e.g., negate, plus)
> 3) Binding arguments (e.g., bind1st, bind2nd, lambda)
4) Maintaining state across calls, but specific to the function
object's instance (something which can not be done with true
functions).
> #1 and #2 won't be more safe using cloning. #3 is safe because the
bound arguments are immutable anyway. Other function object types may
be safer with cloning, but I doubt these occur with great frequency.
(4) is very common, and is in general often safer using cloning.
However, it also changes some semantics and is not usable in a lot of
cases (where the function object is passed by value, thus cloning
with every pass and therefor messing with the state).
I'm still on the fence. I see problems with both sides, but not
clear cut instances where one would be preferred over the other.
> > implementation becomes detrimental you can wrap it in a ref-
counting
> > proxy (whether it be shared_ptr or some other proxy). Going the
> > other way, for example if it's deemed too dangerous for threading
> > use, is not really possible.
>
> This is case where the desire to support multithreaded code is
detrimental to single-threaded code.
I don't think the two issues parallel. This particular issue has
several work arounds that won't work as nicely for the choice between
ref-counting or cloning.
> Either the degradation is in performance, or the degradation is in
the remedy to the performance problem - using shared_ptrs makes for
ugly usage of the callback code.
Not necessarily. Especially if the "proxy" supports operator().
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk