On 2010-09-06 20:55:16 -0400, dsimcha <dsim...@yahoo.com> said:

== Quote from Michel Fortin (michel.for...@michelf.com)'s article
I'm under the impression that a too permissive generic implementation
of cloning is going to break things in various scenarios.

In general you raise some very good issues, but IMHO the right way to do cloning
is to have permissive generic cloning that works in the 90% of cases and can be
easily overridden in the 10% of cases, not to require writing tons of boilerplate in the 90% of cases just to make sure it doesn't do the wrong thing by default in
the 10% of cases.

To me automatic cloning of everything (physical cloning in your parlance) looks more like 50/50 work/doesn't-work ratio. I can only guess, but I'm probably used to different use cases than you are.


A second point is that the thing that brought this whole cloning issue to my mind
was making std.concurrency's message passing model less obtuse.  Right now it's
hard to use for non-trivial things because there's no safe way to pass complex
state between threads. If we start allowing all kinds of exceptions to the "clone the **entire** object graph" rule, cloning will rapidly become useless for safely
passing complex object graphs between threads.

This I agree with. I'm not arguing against automatic cloning per-see, I'm just trying to show cases where it doesn't work well.

Personally, I'm rather skeptical that we can make it safe and efficient at the same time without better support from the language, something akin the mythical "unique" type modifier representing a reference with no aliasing.


What if your
object or structure is part of a huge hierarchy where things contains
pointers to their parent (and indirectly to the whole hierarchy), will
the whole hierarchy be cloned?

Isn't that kind of the point?

Well, that depends. If you send each leaves of a tree as a message to various threads presumably to perform something concurrently with the data in that leaf, then you may want only the leaf to be copied. You may not want every parent down to the root and then up to every other leaf to be copied alongside with each message just because the leaf you send has a pointer to the parent.

In fact, it depends on the situation. If what you want to do with the leaf in the other thread requires the leaf to know its parent and everything else, then sure you need to copy the whole hierarchy. But otherwise it's a horrible waste of memory and CPU to clone the whole object graph for each message, even though it won't affect the program's correctness.

And it's basically the same thing with observers. If your observer is a controller in charge of updating a window when something changes, you don't want to clone the observer, then clone the window and everything in it just because you're sending some piece of data to another thread. Perhaps the program architecture is just wrong, or perhaps that observer is a synchronized class capable of handling function calls from multiple threads so it doesn't really need to be copied.


What happens if your object or structure
maintains a reference to a singleton, will we get two instances of a
singleton?

Very good point.  I guess the reasonable use case for holding a reference to a
singleton (instead of just using the globally accessible one) would be if it's
polymorphic with some other object type?  If you're using message passing
concurrency, most of your mutable singletons are probably thread-local, and what
you probably really want to do is use the thread-local singleton of the thread
you're passing to.

What intrigues me is how such a mechanism would work... although in my mind it's probably not even worth supporting at all, singletons be damned!


My understanding is that a data structure containing a pointer cannot
be cloned safely unless it contains some specific code to perform the
cloning. That's because the type system can't tell you which pointers
point to things owned by the struct/class and which one need to be
discarded when cloning (such as a list of observers, or the parents of
a hierarchy).

This discussion is making me think we really need two kinds of cloning: Physical cloning would clone the entire object graph no matter what, such that the cloned object could be safely passed to another thread via std.concurrency and be given a unique type. Logical cloning would be more like what you describe. In general,
this discussion has been incredibly useful because I had previously only
considered physical cloning.

This is an interesting and valid observation. But I think you need to leave a door open to customization of the "physical cloning" case too. The ability to avoid cloning unnecessary data is as necessary as the ability to easily copying an entire object graph.


--
Michel Fortin
michel.for...@michelf.com
http://michelf.com/

Reply via email to