Hi Scott!
Indeed move in XOTcl is copy+destroy and it is implemented in XOTcl itself.
%Object info instbody move if {[string compare [string trimleft $newName :] [string trimleft [::xotcl::self] :]]} { if {$newName != ""} { ::xotcl::my copy $newName} if {[::xotcl::my isclass [::xotcl::self]] && $newName != ""} { foreach subclass [::xotcl::my info subclass] { set scl [$subclass info superclass] if {[set index [lsearch -exact $scl [::xotcl::self]]] != -1} { set scl [lreplace $scl $index $index $newName] $subclass superclass $scl}} } ::xotcl::my destroy}
So move it not rename references. Is it anyway good idea to rename references? So reference (object name) is its identity (what about dangling pointers).
So time ago I wanted to program (movable) tree structures by using nested objects. Operation of moving tree items I have implented as move operation. After I have discovered, what indeed move is, I have changed the implementation. I think it is a little trap in XOTcl, because many user thinks it is magic fast and do not really destory objects. Indeed it is quite expensive.
Artur
mail@xdobry.de schrieb:
Hi Scott!
Indeed move in XOTcl is copy+destroy and it is implemented in XOTcl itself.
... After I have discovered, what indeed move is, I have changed the implementation. I think it is a little trap in XOTcl, because many user thinks it is magic fast and do not really destory objects. Indeed it is quite expensive.
note, that there is no "namespace rename" command in tcl as well. Since xotcl uses tcl namespaces, in the general case a rename command requires to handle all references (and pointers in C) to namesspaces (including traces, tcl-command names, aliases, namespace imports, nested namespaces, ...), when a namespace (with all its children) is renamed. Therefore in general, a "namespace rename" is much more expensive than a "command rename". note, that tcl has no "variable rename" command as well. So, adding such a functionality would require some amount of C hacking and quite a strong coupleing with the tcl internals.
The implementation of move as copy+destroy is a compromise between simplicity and functionality. I can imagine cases, where one wants to have more or less the equivalent to a copy constructor when copy occurs and maybe something different when a move happens. However, since all methods are equal in xotcl, it is quite simple for a poweruser of xotcl to overload copy/move and add applicaton specific addtional behavior to it. if one does not like the side-effects of destroy in a move, a custom move operation can set in instance variable "__during_move__" and query this from the destroy method to change its behavior.
hope, this helps...
-gustaf neumann
Artur _______________________________________________ Xotcl mailing list Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
On 15 Mar 2006, at 12:17, Gustaf Neumann wrote:
The implementation of move as copy+destroy is a compromise between simplicity and functionality. I can imagine cases, where one wants to have more or less the equivalent to a copy constructor when copy occurs and maybe something different when a move happens. However, since all methods are equal in xotcl, it is quite simple for a poweruser of xotcl to overload copy/move and add applicaton specific addtional behavior to it. if one does not like the side- effects of destroy in a move, a custom move operation can set in instance variable "__during_move__" and query this from the destroy method to change its behavior.
I am actually quite surprised to find that the move operation calls the destructor. This is not mentioned on the reference manual and does, in fact, seem counter-intuitive. A move is a move, nothing is being destroyed, so why call the destructor? I understand that the operation is actually quite expensive, due to current Tcl internals, but is there any reason why a destructor should be called? If we want a method called for a move operation, surely it would be simple to define that a "beingMoved" method is then called.
xotcl-bounces@alice.wu-wien.ac.at wrote on 03/15/2006 04:23:28 AM:
On 15 Mar 2006, at 12:17, Gustaf Neumann wrote:
I am actually quite surprised to find that the move operation calls the destructor. This is not mentioned on the reference manual and does, in fact, seem counter-intuitive. A move is a move, nothing is being destroyed, so why call the destructor?
I agree. A move operation didn't imply object destruction to me, either.
I understand that the operation is actually quite expensive, due to current Tcl internals, but is there any reason why a destructor should be called? If we want a method called for a move operation, surely it would be simple to define that a "beingMoved" method is then called.
I'm guessing that xotcl::object's "destroy" method does all the heavy lifting (cleaning up the source of the move). What would happen if the default move implementation was to change the source object's class to xotcl::object before invoking destroy? This way it would continue to use the xotcl::object's "destroy" implementation for cleanup purposes without invoking all of the subclass destroy methods, and derived classes wouldn't perceive move as a destroy operation. Would this have bad side-effects?
it is quite simple for a poweruser of xotcl to overload copy/move and add applicaton specific addtional behavior to it. if one does not like the side- effects of destroy in a move, a custom move operation can set in instance variable "__during_move__" and query this from the destroy method to change its behavior.
While I'm no poweruser, I did get the guard mechanism to work. Here it is for completeness sake. (Is there an easy way to search the mail archives? Maybe this will help someone else...)
# move doesn't do what I expect. It's not simply a move, it's # actually a deep copy followed by a destroy. I want to reclaim the # object on destroy, but not the imputed destroy from the move # operation. So flag that the destroy is happening because of a move # so the destroy reclamation doesn't happen, and then reset the flag # in the new copy. TrackingMixin instproc move {dest} { my set _ismoving_ 1 next $dest unset _ismoving_ } TrackingMixin instproc destroy {args} { if {[my info vars _ismoving_] eq ""} { # true destroy, do true destroy things... } else { next } }
Scott
On 16 Mar 2006, at 14:15, Scott Gargash wrote:
I understand that the operation is actually quite expensive, due to current Tcl internals, but is there any reason why a destructor should be called? If we
want
a method called for a move operation, surely it would be simple to define that a "beingMoved" method is then called.
I'm guessing that xotcl::object's "destroy" method does all the heavy lifting (cleaning up the source of the move). What would happen if the default move implementation was to change the source object's class to xotcl::object before invoking destroy? This way it would continue to use the xotcl::object's "destroy" implementation for cleanup purposes without invoking all of the subclass destroy methods, and derived classes wouldn't perceive move as a destroy operation. Would this have bad side-effects?
But I am guessing even this is unnecessary. Why call the destroy at all? I am confident, without looking at the actual code, that deallocation of the resources for the 'original' object could be deallocated without going through the whole destruction procedure.
Kristoffer Lawson schrieb:
But I am guessing even this is unnecessary. Why call the destroy at all? I am confident, without looking at the actual code, that deallocation of the resources for the 'original' object could be deallocated without going through the whole destruction procedure.
as pointed out earlier, move is a copy + destroy. If you want a copy alone, use copy and not move.
As Artur pointed out, command names are the references to objects. if such a reference should be made invalid and the unneeded storage should be reclaimed at this time, destroy is the correct thing.
Note, that move does not refer to a single object, but to an object tree, all subobjects, classes, commands, etc. are affected as well.
-gustaf neumann
On 17 Mar 2006, at 16:33, Gustaf Neumann wrote:
as pointed out earlier, move is a copy + destroy. If you want a copy alone, use copy and not move.
No, I do not want copy alone. It is just counter-intuitive that the destructor is called on a move as movement is not generally considered to be an act of desctruction. This would be the norm for most things. Consider files for example. When a file is moved at no point does
As Artur pointed out, command names are the references to objects. if such a reference should be made invalid and the unneeded storage should be reclaimed at this time, destroy is the correct thing.
The matter of references is problematic. I am thinking that in fact this reveals a downside to the namespace-tied model as handles do not point to the object itself, but to the object's location within the namespace universe. A move is not actually a matter of transferring the ownership of an object to a new location and this slightly limits the ways you can use XOTcl move functionality for data structures.
Of course one can set variables to detect this, as mentioned, but this seems like a bit of a hack and fighting against what XOTcl is doing. Perhaps the question should be asked: how is object movement actually supposed to be used in XOTcl?
A double-reference would solve this. In that way the handle returned by [new] and [self] would always be a valid command for the object, throughout its whole lifetime. If it is moved to be a child of another object the handle remains the same (or at least can be used), but the ownership is changed. Whether this is workable in XOTcl or not is, of course, something you would be better at deciding.
In any case, the destruction should be clearly mentioned in the documentation as there seems to be a number of people who are surprised by that.
xotcl-bounces@alice.wu-wien.ac.at wrote on 03/17/2006 08:25:37 AM:
A double-reference would solve this. In that way the handle returned by [new] and [self] would always be a valid command for the object, throughout its whole lifetime. If it is moved to be a child of another object the handle remains the same (or at least can be used), but the ownership is changed. Whether this is workable in XOTcl or not is, of course, something you would be better at deciding.
I've been thinking along somewhat different lines, the classic "extra level of indirection" that solves all problems. What about using interpreter aliases as an indirection? What would happen if all objects were created as anonymous commands inside (say) the xotcl namespace, and the object name was just an alias to the anonymous object?
This would let move be straightforward, drop the old alias and create a new one. From what I've inferred of xotcl's implementation, I think xotcl would be (mostly) unaffected by the change. The one thing that I think might be busted would be is parent/child relationships. Rather than introspecting into the commands, you'd have to introspect the aliases (relationships would be inferred by alias location instead of command location). That might be difficult, Tcl aliases are surprisingly hard to introspect.
I also don't know what the performance implications would be (I think an alias introduces some overhead). But if objects didn't ever move, there might be some potential optimizations available too.
Just a thought...
Scott
Scott Gargash schrieb:
xotcl-bounces@alice.wu-wien.ac.at wrote on 03/15/2006 04:23:28 AM:
On 15 Mar 2006, at 12:17, Gustaf Neumann wrote:
I am actually quite surprised to find that the move operation calls the destructor. This is not mentioned on the reference manual and does, in fact, seem counter-intuitive. A move is a move, nothing is being destroyed, so why call the destructor?
I agree. A move operation didn't imply object destruction to me, either.
i would not expect this either, but it seems as a reasonable compomise. It has been like this since implemented more than five years ago and has not caused any trouble. maybe, it would have been better to provide only a copy operation, and delay move, until it can be made properly in c with a namespace rename operations. anyhow, for now, i have documented the copy+destroy operation in the manual.
I'm guessing that xotcl::object's "destroy" method does all the heavy lifting (cleaning up the source of the move). What would happen if the default move implementation was to change the source object's class to xotcl::object before invoking destroy? This way it would continue to use the xotcl::object's "destroy" implementation for cleanup purposes without invoking all of the subclass destroy methods, and derived classes wouldn't perceive move as a destroy operation. Would this have bad side-effects?
for some applications, it might be the right things, for others not.
While I'm no poweruser, I did get the guard mechanism to work. Here it is for completeness sake. (Is there an easy way to search the mail archives? Maybe this will help someone else...)
This qualifies you at least as a candidate for a power user :). you might place this on the tcl wiki (http://mini.net/tcl/XOTcl)
mailman has no nice search interface, maybe we will switch at some time to something better.... best regards -gustaf neumann