2018-07-07 22:46 GMT+08:00 huck : > > Yes, as we saw when code disposal was introduced , even existing > applications can be ruined if care is not properly taken. Maybe if > create_tcl_sub() had been documented as part of the api this problem would > not have been created in the first place. >
I think it had not been because create_tcl_sub() was created for internal use only and not intended to be an API. > >> >> My idea is to apply a prefix to identify if first argument of call() is a >> DESCRNAME. If the first arg call() is '%' , then it is a DESCRNAME. (Let's >> forget previous AT sign '@' example, which might confuse you). Otherwise the >> first arg is a tcl verb. For example the following code: >> >> call('%button1', ..., $sub1, sub{}) >> call('%button1', ..., $sub2, $sub3) >> call('if', '1', $sub3) >> : >> code_dispose('button1'); >> >> Then inline sub{}, $sub1 and $sub2 would get disposed while #sub3 is kept. >> The code looks much cleaner compared to annoying TCLNAME/GENCODE/EVENT >> dealing and storing. Here one DESCRNAME maps to multiple $subs, which is not >> allowed in current implementation. Just share an idea for a better disposal >> interface. > > > > And how would you implement this via Tkx? > for instance how do you modify a $menu>add_command(%args); call? > or $button =$in->new_ttk__button(-text=>$args{text}, -command=>$args{sub} ); > It's not for Tkx user. It's for Tcl user (such as Tkx). Tkx can associate a unique DESCRNAME 'menu1' with an object $menu and call code_dispose('menu1') on destroyer of $button1. In previous example, $sub1, inline sub{}, $sub2 get disposed when code_dispose('button1') is called. They get disposed because they are associated with DESCRNAME 'button1' via call('%button1'). $sub3 is also associated with 'button1', it does not get disposed because it has also been call()'ed once without DESCRNAME. > like you said before if you dont know what to do with EVENT it can be > defined as undef, and then TCLNAME is the same as GENCODE (as the doc says) > and only that one item needs to be saved, just like you need to save the > CMDNAME passed to CreateCommand () > > Changing the existing and working interface to call() seems to be much more > error prone than documenting the interface to create_tcl_sub(), just making > things more complex. > > As i already mentioned by using create_tcl_sub() to manage code disposal, i > can just add one call to create_tcl_sub() to lock down a sub from code > disposal, and add another call to _code_destroy() when i want to release > that coderef. Your proposed method requires every call with a coderef to be > modified which was one thing i was trying to avoid. > > And you say "would get disposed", but when? the only time code may get > automagicly disposed is when something has the same DESCRNAME, but here you > propose allowing DESCRNAME ot have the same value over multiple calls, are > you proposing that inside the second call $sub1 and sub{}) get disposed? > or are you proposing that $sub3 gets added to that list for disposal later? > > And a DESCRNAME can have more than one sub attached to it since v1.06 What > it is is that when the same DESCRNAME is seen again, the prior code calls > are now eligible for code destruction. One change i made is to delay code > destuction untill after the entire command is parsed, so as not to have to > destroy/recreate a coderef that already exists in both the current and the > prior call with the same DESCRNAME This wasnt a problem at v1.02 because > %anon_refs was only assigned to if the TCLNAME did not exist already > >> BTW, I found _code_dispose() has to be called in the form >> 'Tcl::_code_dispose(...)' rather than '$interp->_code_dispose(...)'. It is >> documented, but it is counter-intuitive. Programmers can hardly find their >> incorrect calling via $interp object. I suggest to check input parameter and >> provide some warning at least. IMO, %anon_refs{} would be better an object >> instance variable instead of global one. > > > > but it isnt an object instance now, as far as i can tell never has been, So > the change you are proposing here is not trivial. What should it be an > instance of? > > While $interp can be considered an object all it is really is a blessed > scalar. So where do you propose you store this new object instance? If we > make $interp be the first key to %anon_refs that will cause a lot of code to > need to be changed. > > And as i pointed out while delete_ref() is called with an $interp for the > most part that doesnt matter, since the $interp stored in the Tcl::Code > object is used for the deletion, and while there could be many different > interpreters, there is only one %anon_refs, so that on a single TCLNAME can > exist, there cannot be one for each interpreter. I mean %anon_refs shall be better to be something like $interp->{anon_refs}. Different interpreters shall be better have separated TCLNAME/CMDNAME/DESCRNAME naming space. It does not make sense that TCLNAME/DESCRNAME have to be unique across different interpreters. > Again, maybe the solution is to make a RFP asking for input on code > disposal, what it should do, how it should be called and what modification > will be needed to existing code. Without that my intentions were to make it > so existing v1.02 code still worked, and there was a mechanism to control > code disposal. I think my patches have met both of those goals. (and as i > watched code disposal in action i realized it was destroying/recreating tcl > subs over and over and i wanted to prevent that too) > > and i also realized that a deep bug in the xs code was leading to a massive > memory leak and fixed that as well. Yes I believe v1.06 got quite some bugs fixed. Here just some discussion for any possibility to make interface more clean. SJ