Been thinking if this would make sense:
while {$stuff} { tie myVar [MyClass new] ... }
And the instance created from MyClass would be automagically collected on each iteration. Ie. [tie] would tie an object to a variable: when the variable's value is changed, or when the variable is destroyed, the object is too -- or at least the refcount decreased. I often have Message objects which are used once (after some data is read from somewhere) and then destroyed. Quite often I forget the latter part ;-)
nice idea, I've played a bit with var traces to make some tie functionality work; is this what you were thinking of?
--Uwe
####################################################### TIE code
Object instproc tie {varname objname} { my set $varname $objname my trace variable $varname wu "Object tie_cb $objname [self]" } Object proc tie_cb {tieobj obj n1 n2 mode} { ## delete the tieobj if {[my isobject $tieobj]} { $tieobj destroy } ## delete the trace for this tieobj if {$mode == "w" && [my isobject $obj]} { foreach t [$obj trace vinfo $n1] { set mode [lindex $t 0] set cmd [lindex $t 1] if {[string equal $cmd "Object tie_cb $tieobj $obj"]} { $obj trace vdelete $n1 $mode $cmd } } } }
####################################################### Test
Object x x proc test {} { set n 0 while {$n < 10} { my tie myVar [Object new] incr n } } x test
### test unset #x unset myVar #x set myVar abc
### only one should have survived puts [Object info instances]
### it gets killed when the obj gets killed x destroy puts [Object info instances]
###############################################################
On Friday 24 January 2003 04:32, Kristoffer Lawson wrote:
Been thinking if this would make sense:
while {$stuff} { tie myVar [MyClass new] ... }
And the instance created from MyClass would be automagically collected on each iteration. Ie. [tie] would tie an object to a variable: when the variable's value is changed, or when the variable is destroyed, the object is too -- or at least the refcount decreased. I often have Message objects which are used once (after some data is read from somewhere) and then destroyed. Quite often I forget the latter part ;-)
/ http://www.fishpool.com/~setok/
Xotcl mailing list - Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
On Fri, 24 Jan 2003, Uwe Zdun wrote:
nice idea, I've played a bit with var traces to make some tie functionality work; is this what you were thinking of?
Yeah, nice going. Looks like exactly what I had in mind (I reckoned you could probably do it with Tcl traces). I thinking that I might almost prefer if [tie] was not an object command as it's not really related to any specific object (f.ex. using it from outside an object would be funny). Or what do you think?
On Friday 24 January 2003 15:09, Kristoffer Lawson wrote:
On Fri, 24 Jan 2003, Uwe Zdun wrote:
nice idea, I've played a bit with var traces to make some tie functionality work; is this what you were thinking of?
Yeah, nice going. Looks like exactly what I had in mind (I reckoned you could probably do it with Tcl traces). I thinking that I might almost prefer if [tie] was not an object command as it's not really related to any specific object (f.ex. using it from outside an object would be funny). Or what do you think?
its no big deal to do that: for instance see the code below; the problem with this code sample is you have to be sure that the variable is defined one level above the trace; if you are not, you'll have to use global variables only for ties; or you store all tie variables in a special namespace; such as the xotcl namespace.
proc tie {varname objname} { upvar $varname v set v $objname trace variable v wu "tie_cb $objname" } proc tie_cb {tieobj n1 n2 mode} { upvar $n1 name ## delete the tieobj if {[xotcl::Object isobject $tieobj]} { $tieobj destroy } ## delete the trace for this tieobj if {$mode == "w"} { foreach t [trace vinfo name] { set mode [lindex $t 0] set cmd [lindex $t 1] if {[string equal $cmd "tie_cb $tieobj"]} { #puts "delete: $mode $cmd" trace vdelete name $mode $cmd #puts [trace vinfo name] } } } }
####################################################### Test
set n 0 while {$n < 10} { tie myVar [Object new] incr n }
### only one should have survived puts [Object info instances]
### test unset unset myVar
puts [Object info instances]
On Friday 24 January 2003 04:32, Kristoffer Lawson wrote:
Been thinking if this would make sense:
while {$stuff} { tie myVar [MyClass new] ... }
And the instance created from MyClass would be automagically collected on each iteration. Ie. [tie] would tie an object to a variable: when the variable's value is changed, or when the variable is destroyed, the object is too -- or at least the refcount decreased. I often have Message objects which are used once (after some data is read from somewhere) and then destroyed. Quite often I forget the latter part ;-)
/ http://www.fishpool.com/~setok/
there are already many approaches for destroying object automatically. look at the following code (hope there are not to many typos)
Class C C instproc destroy {} {puts "[self] destroy"; next}
C c1 c1 proc t1 {} { for {set i 0} {$i < 10} {incr i} { O new -volatile } } c1 proc t2 {} { for {set i 0} {$i < 10} {incr i} { O new -childof [self] } } c1 proc t3 {} { for {set i 0} {$i < 10} {incr i} { O [self]::$i } } c1 proc t4 {} { for {set i 0} {$i < 10} {incr i} { O [self]::i } }
-t1: after the loop, all objects exist, the automatically destroyed, when t1 is left. -t2: all objects survive t2, they are deleted, when c1 is destroyed -t3: same as t2, but the programmer has more control over object names (see also t4) -t4: on each iteration an object is created and destroys a potentially same-named object. after t4, c1 contains one sub-object, which is destroyed, when c1 is destroyed (this is somewhat similar in the behavior to the code that uwe posted).
we could provide an option -bind <varname> to the new instproc to allow the user to specify a local or a per-object or global variable name, but this does not provide reference counting at all. i have started some time ago to work on reference counting, and xotcl has some good prerequirements for this: we have tcl_objs for xotcl objects, they maintain already a reference count. the obvious idea is to destroy the object, when the reference count reaches 0. however, practically this showed to be quite tricky in the current implementation since the refcount = 0 condition happens in some unvonveniant situations... i have not given up on this, but it needs a bigger chunk of time to devote to this...
best regards -gustaf
Xotcl mailing list - Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
we could provide an option -bind <varname> to the new instproc to allow the user to specify a local or a per-object or global variable name, but this does not provide reference counting at all. i have started some time ago to work on reference counting, and xotcl has some good prerequirements for this: we have tcl_objs for xotcl objects, they maintain already a reference count. the obvious idea is to destroy the object, when the reference count reaches 0. however, practically this showed to be quite tricky in the current implementation since the refcount = 0 condition happens in some unvonveniant situations... i have not given up on this, but it needs a bigger chunk of time to devote to this...
Yes, exactly. Obviously it's all just steps to make some things easier while refcount based destruction is the absolute solution. However, as you may have noticed from c.l.t, ref-count -based systems are really nasty to get done properly. How would you propose to deal with the situation where a reference is lost, because the object just happens to be made into a string (ie. some command or procedure does not keep the Tcl_Obj but just uses the data as a command). F.ex. when building callback scripts and containing the object handle there, or as an array key (I think array keys are still just considered to be strings and the Tcl_Obj form is not retained).
I would absolutely love to see a solution to the above problems. Many issues would just vanish in an instance.
On Friday 24 January 2003 15:16, Kristoffer Lawson wrote:
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
we could provide an option -bind <varname> to the new instproc to allow the user to specify a local or a per-object or global variable name, but this does not provide reference counting at all. i have started some time ago to work on reference counting, and xotcl has some good prerequirements for this: we have tcl_objs for xotcl objects, they maintain already a reference count. the obvious idea is to destroy the object, when the reference count reaches 0. however, practically this showed to be quite tricky in the current implementation since the refcount = 0 condition happens in some unvonveniant situations... i have not given up on this, but it needs a bigger chunk of time to devote to this...
Yes, exactly. Obviously it's all just steps to make some things easier while refcount based destruction is the absolute solution. However, as you may have noticed from c.l.t, ref-count -based systems are really nasty to get done properly. How would you propose to deal with the situation where a reference is lost, because the object just happens to be made into a string (ie. some command or procedure does not keep the Tcl_Obj but just uses the data as a command). F.ex. when building callback scripts and containing the object handle there, or as an array key (I think array keys are still just considered to be strings and the Tcl_Obj form is not retained).
sure, in general, this is an intrinsic problem. what i have implemented already in 0.94 was a double refcounting, that allows multiple tcl_objs to point to a single xotcl-object (or class), having therefore refcounts on the tcl_objs and separate refcounts on the xotcl-structures (classes and objects). therfore it is possible to convert for example the string "Object" with little effort to he class Object, as long it exists. For example after the statement
Class C -superclass Object
Object is a TclObj pointing to the appropriate xotcl-structure. So, this is not exactly the same situation as the general case, where the string to object mapping is not possible or leads to a new structure not representing the old state.
Certainly, when all references are gone (stringified, only string callbacks point to an object) the object will be destroyed.... still, we would have the choice btwn traditional objects (that can be used safely in callbacks) and refcounted objects, there are many cases, where this might be useful ... i my code, i have not experienced the problem with unneeded objects (people that grew up with Java rather than C might thing differently)
-gusaf
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
Certainly, when all references are gone (stringified, only string callbacks point to an object) the object will be destroyed.... still, we would have the choice btwn traditional objects (that can be used safely in callbacks) and refcounted objects, there are many cases, where this might be useful ... i my code, i have not experienced the problem with unneeded objects (people that grew up with Java rather than C might thing differently)
I've actually experienced fewer problems with manual destruction than I imagined, but I do still stumble across problems every now and then and in a way it is an extra headache to have to work out the proper destruction point. I think it is a good idea to do what you're doing with the refcounts and to have all the facilities there for auto-destruction -- at least for when and if Tcl is ever able to provide a way to be sure that references last for as long as needed.
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
we could provide an option -bind <varname> to the new instproc to allow the user to specify a local or a per-object or global variable name, but this does not provide reference counting at all. i have started some time ago
Oh, I meant to say that an option to [new] is not necessarily the best. Often (at least in my case) it is a method of an object which creates an instance and returns it, like:
set msg [$cmdReader getNewMessage]
So at the level where I want the automisation I don't directly call new. Naturally this could be changed to accommodate the use of new, but then my interface wouldn't be as cleanly split up.
This is why I thought of [tie] as a separate thing, not tied to [new].
Anyway, I don't know if it makes sense to add yet another automatic destruction system, but it did pop into my mind when doing things like the above :-)
On Friday 24 January 2003 15:44, Kristoffer Lawson wrote:
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
we could provide an option -bind <varname> to the new instproc to allow the user to specify a local or a per-object or global variable name, but this does not provide reference counting at all. i have started some time ago
Oh, I meant to say that an option to [new] is not necessarily the best. Often (at least in my case) it is a method of an object which creates an instance and returns it, like:
set msg [$cmdReader getNewMessage]
So at the level where I want the automisation I don't directly call new. Naturally this could be changed to accommodate the use of new, but then my interface wouldn't be as cleanly split up.
i don't get your point: getNewMessage has to create the Object, so it can use certainly new (with all variants). is your argument: the caller of newmessage should decide, whether the created object should be dynamically reclaimed or not?
anyhow, it is not hard to do it one or the other way....
-gustaf
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
Oh, I meant to say that an option to [new] is not necessarily the best. Often (at least in my case) it is a method of an object which creates an instance and returns it, like:
set msg [$cmdReader getNewMessage]
So at the level where I want the automisation I don't directly call new. Naturally this could be changed to accommodate the use of new, but then my interface wouldn't be as cleanly split up.
i don't get your point: getNewMessage has to create the Object, so it can use certainly new (with all variants). is your argument: the caller of newmessage should decide, whether the created object should be dynamically reclaimed or not?
Yes, obviously getNewMessage will use [new], but it wont be using [new -bind] for obvious reasons! The caller is the one that wants to bind it to a variable, so yes my argument is that the caller should decide. In fact, it could be argued that the same applies to -volatile. That there are cases when a new object should be returned by some method other than [new] but the caller is generally the one that wants to decide the dynamics of the object.
On Friday 24 January 2003 17:03, Kristoffer Lawson wrote:
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
Oh, I meant to say that an option to [new] is not necessarily the best. Often (at least in my case) it is a method of an object which creates an instance and returns it, like:
set msg [$cmdReader getNewMessage]
So at the level where I want the automisation I don't directly call new. Naturally this could be changed to accommodate the use of new, but then my interface wouldn't be as cleanly split up.
i don't get your point: getNewMessage has to create the Object, so it can use certainly new (with all variants). is your argument: the caller of newmessage should decide, whether the created object should be dynamically reclaimed or not?
Yes, obviously getNewMessage will use [new], but it wont be using [new -bind] for obvious reasons! The caller is the one that wants to bind it to a variable, so yes my argument is that the caller should decide. In fact, it could be argued that the same applies to -volatile. That there are cases when a new object should be returned by some method other than [new] but the caller is generally the one that wants to decide the dynamics of the object.
The caller can certainly do with the object whatever she wants. if these are properties needed in the creation method they have to be passed somehow there, or the object can be altered, or one can put a mechanism on top of the creation to handle this. I personally would not have a problem in using two different method names for the different cases, like set msg [$cmdReader getMessage] set msg [$cmdReader getNewMessage] or to use an option like in set msg [$cmdReader getMessage -volatile]
i agree, using -bind here with an explicit variable name is not syntactically pleasing...
-gustaf
/ http://www.fishpool.com/~setok/
Xotcl mailing list - Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
The caller can certainly do with the object whatever she wants. if these are properties needed in the creation method they have to be passed somehow there, or the object can be altered, or one can put a mechanism on top of the creation to handle this. I personally would not have a problem in using two different method names for the different cases, like set msg [$cmdReader getMessage] set msg [$cmdReader getNewMessage] or to use an option like in set msg [$cmdReader getMessage -volatile]
But that doesn't solve the issue. $cmdReader cannot create the object itself as volatile or bound to a variable as it will then be destroyed the minute getNewMessage returns! Or, of course it could always use uplevel and upvar but then every method that wants to return an object that may or may not be bound to a variable has to provide this extra functionality and argument checking. Ie. the methods need to be concerned with what the caller wants, and I don't believe this is necessary a good thing.
Again, I'm not saying this feature is absolutely essential, but if one decides to add it I believe it should be done in the best possible way ;-)
On Friday 24 January 2003 17:48, Kristoffer Lawson wrote:
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
The caller can certainly do with the object whatever she wants. if these are properties needed in the creation method they have to be passed somehow there, or the object can be altered, or one can put a mechanism on top of the creation to handle this. I personally would not have a problem in using two different method names for the different cases, like set msg [$cmdReader getMessage] set msg [$cmdReader getNewMessage] or to use an option like in set msg [$cmdReader getMessage -volatile]
But that doesn't solve the issue. $cmdReader cannot create the object itself as volatile or bound to a variable as it will then be destroyed the minute getNewMessage returns! Or, of course it could always use uplevel and upvar but then every method that wants to return an object that may or may not be bound to a variable has to provide this extra functionality and argument checking. Ie. the methods need to be concerned with what the caller wants, and I don't believe this is necessary a good thing.
well, completely without uplevel/upvar or the like it is hard to find a solution. also tie needs it. passing the options via args is not painful. "uplevel" is only used for -volatile, which is scope-dependent.
============================================ Class Msg
Class CmdReader CmdReader instproc getMessage args { uplevel [concat [list Msg new] $args] }
Class Client -parameter reader Client instproc read {} { my instvar reader set msg [$reader getMessage -volatile] }
Client c1 -reader [CmdReader new] ============================================
The instvar "reader" is btw. a good example, where i prefer control in the new command rather than in the calling environment. "tie" is here no good solution either. "new -refcount" would be much nicer ....
Again, I'm not saying this feature is absolutely essential, but if one decides to add it I believe it should be done in the best possible way ;-)
these discussions are great. we have a young language/extension, where we can try to find "the right" way (whatever this is) and we can implement it with not to much hassle...
-gustaf
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
But that doesn't solve the issue. $cmdReader cannot create the object itself as volatile or bound to a variable as it will then be destroyed the minute getNewMessage returns! Or, of course it could always use uplevel and upvar but then every method that wants to return an object that may or may not be bound to a variable has to provide this extra functionality and argument checking. Ie. the methods need to be concerned with what the caller wants, and I don't believe this is necessary a good thing.
well, completely without uplevel/upvar or the like it is hard to find a solution. also tie needs it. passing the options via args is not painful. "uplevel" is only used for -volatile, which is scope-dependent.
[tie] needs it too, yes. The point is that is just one command which will handle all cases like that, instead of each case having to deal with it separately.
============================================ Class Msg
Class CmdReader CmdReader instproc getMessage args { uplevel [concat [list Msg new] $args] }
Class Client -parameter reader Client instproc read {} { my instvar reader set msg [$reader getMessage -volatile] }
Client c1 -reader [CmdReader new]
The instvar "reader" is btw. a good example, where i prefer control in the new command rather than in the calling environment. "tie" is here no good solution either. "new -refcount" would be much nicer ....
[tie] doesn't cover everything and is not the best for everything. For the specific case I demonstrated it is useful. In your [read] method, I would probably prefer to do this:
Client instproc read {} { my instvar reader tie msg [$reader getMessage] }
And thus the reader would not have to care what happens to the object after it returns it. I think [tie] sort of works neatly in that way as it's not realy to do with object creation but more of a statement "destroy the ob when the variable changes", whereas volatile feels more like something related to creation.
I haven't really thought of volatile much, the following doesn't seem "right" somehow:
Client instproc read {} { my instvar reader volatile msg [$reader getMessage] }
Perhaps your system is best for that, I don't know... -refcount can help in many situations but even then I feel that in [getMessage] I shouldn't care how destruction is handled.
What if you could specify after creation what happens to the object? Like:
Client instproc read {} { my instvar reader set msg [$reader getMessage] $msg memmanagement refcount }
I mean, in addition to the "-refcount" option with [new]. That way methods that should not know about the dynamics (like [getMessage]) can use normal [new] and let the caller decide what it wants to do with the object.
these discussions are great. we have a young language/extension, where we can try to find "the right" way (whatever this is) and we can implement it with not to much hassle...
Yeah. Great to be back on the mailing list participating :-) I have some strong sentimentality for XOTcl: I feel it's my kind of OO extension and I have great interest in seeing it succeed.
I haven't really thought of volatile much, the following doesn't seem "right" somehow:
Client instproc read {} { my instvar reader volatile msg [$reader getMessage] }
funny enough, i was rather thinking on something like: =================== Object instproc objectref varname { uplevel [list trace variable $varname wu [list [self] objectref_cb]] } Object instproc objectref_cb {n1 n2 mode} { upvar $n1 name my instvar [list __last($n1,$n2) old] if {[info exists old]} { if {[my isobject $old]} { $old destroy } } if {[info exists name] && [string equal $mode "w"]} { set old $name } } ===================== where one can use it like: ===================== Client instproc read {} { my instvar reader my objectref msg set msg [$reader getMessage] } ==================== or combined to what the tie did before... this leads to some variable-declarations, where we could also define parameters as references.... Class C -parameter {{a ""} {b -default "....."} {c -objectref} ...}
What if you could specify after creation what happens to the object? Like:
Client instproc read {} { my instvar reader set msg [$reader getMessage] $msg memmanagement refcount }
I mean, in addition to the "-refcount" option with [new]. That way methods that should not know about the dynamics (like [getMessage]) can use normal [new] and let the caller decide what it wants to do with the object.
this is a good idea, except in cases, where the characteristics have to be known at creation time. i will think about it....
-gustaf
On Fri, 24 Jan 2003, Gustaf Neumann wrote:
===================== where one can use it like: ===================== Client instproc read {} { my instvar reader my objectref msg set msg [$reader getMessage] } ==================== or combined to what the tie did before... this leads to some variable-declarations, where we could also define parameters as references....
I think that would work very nicely with [tie]. I'm not sure about object reference counts, though. While the object destruction with [tie] can be thought of as a link to a variable (ie. the variable could be declared to do that) but I see auto-destruction of an object when refs are lost to be an attribute of the object, not of the variable which it is assigned to. I mean, with ref counting, that variable could easily disappear, but the object would still exist if there are references.