Backed out and as a reslut rejecting RFE 720, cf. <https://sourceforge.net/p/oorexx/feature-requests/720/>.
---rony On 11.08.2021 13:21, Rony G. Flatscher wrote: > On 10.08.2021 18:07, Rick McGuire wrote: >> No, this is way too complicated to add. It would be better to just back out >> the feature, which >> was only added under the assumption that there was no detectable effect in >> doing so. The >> guarded/nonguarded state clearly protects more than just the variable state >> of the object, it >> also synchronizes the order of invocations of any methods called from within >> the method. > > +1 > > So would revert the changes applied as recorded in > <https://sourceforge.net/p/oorexx/feature-requests/720/> in reverse order > from the svn root, like: > > svn merge -r 12141:12140 . > svn ci -m "Backed out r12141." > > svn merge -r 12006:12005 . > svn ci -m "Backed out r12006." > > Would that be the correct sequence? > > Anything to watch out, any suggestions otherwise? > > ---rony > >> >> On Tue, Aug 10, 2021 at 11:30 AM Rony G. Flatscher <rony.flatsc...@wu.ac.at >> <mailto:rony.flatsc...@wu.ac.at>> wrote: >> >> To keep the best of both worlds I propose to allow to activate this >> particular feature >> (defaulting methods to unguarded if the first statement neither starts >> with EXPOSE nor with >> USE LOCAL) with a new option "unguarded" on the options directive, i.e.: >> >> ::options unguarded >> >> Enclosed please find the intended patch (tested) with request for >> comment. >> >> Will update the documentation (rexxref) and the method directive test >> unit accordingly. >> >> ---rony >> >> P.S.: With the patch applied the following program: >> >> say 'OPTIONS UNGUARDED set ...' >> >> do i=1 to 5 >> m=.Test1~method("M"i) >> say "m"i"~isGuarded:" m~isGuarded >> end >> >> ::options unguarded >> >> ::class Test1 >> >> ::method m1 >> say 'm1' >> >> ::method m2 >> expose a >> >> ::method m3 >> use local >> >> ::method m4 guarded >> >> ::method m5 unguarded >> >> will yield the following (expected) output: >> >> OPTIONS UNGUARDED set ... >> m1~isGuarded: 0 >> m2~isGuarded: 1 >> m3~isGuarded: 1 >> m4~isGuarded: 1 >> m5~isGuarded: 0 >> >> Without the new "unguarded" subdirective of the options directive in >> effect method m1 will be >> guarded by default (the original behavior). >> >> >> On 07.08.2021 18:28, Rony G. Flatscher wrote: >>> >>> Sleeping and thinking more over it I would suggest to remove this >>> feature altogether! The >>> major reasing being that the Rexx philosophy (and ooRexx by extension) >>> should make coding as >>> easy as possible for programmers. >>> >>> The default for methods (and related) has always been "guarded" such >>> that one would not have >>> to write "guarded" to the method directive. With that default only in >>> very rare cases (in >>> multithreaded scenarios) would one have to write "unguarded" to a >>> method directive. And if >>> doing so one must have an understanding of multithreading and the >>> ramifications if someone >>> would want a method to run unguarded. >>> >>> Compare this to the current situation with this new feature on: in >>> order to fix BSF.CLS all >>> of a sudden I had to add the keyword "guarded" to every method to gain >>> the default behaviour >>> for ooRexx < 5.0 and thereby re-enabling correct execution of GUI >>> nutshell examples. >>> >>> Ad feature: originally it was thought to be helpful to programmers by >>> saving the programmers >>> to write "unguarded" to a method directive for a method that is known >>> to be safe in >>> unguarded mode thinking that methods that have no direct access to the >>> attribute pool (i.e. >>> the method routine would not start with "expose" or "use local") >>> qualify for unguarded >>> execution not thinking about scenarios where this is not enough. >>> >>> To make it easy for the programmer (i.e. not having to know additional, >>> sometimes quite >>> subtle, concepts that play a role in this context) I would be in a >>> strong favor to leave the >>> default "guarded" in place. Then either remove this new feature >>> altogether or make it an >>> explicit option a programmer has to state ("::OPTIONS" with a new pair >>> "guarded|unguarded"). >>> >>> What opinions have others? Do you concur? >>> >>> ---rony >>> >>> >>> On 06.08.2021 15:09, Rony G. Flatscher wrote: >>>> >>>> Background: In order for ooRexx programmers getting acquainted with >>>> BSF4ooRexx/Java quickly >>>> there are numerous nutshell examples in "bsf4rexx/samples". Most of >>>> these nutshell examples >>>> stem from observations of students over time who should get help by >>>> demonstrating them how >>>> to achieve something of interest with these (mostly brief) nutshell >>>> examples. >>>> >>>> One interesting problem has been the interaction from ooRexx with GUI >>>> objects which must be >>>> carried out on the GUI threads in Java (the "awt thread" or the >>>> "JavaFX Application >>>> thread"). Although they got the necessary information about the >>>> architecture and what to do >>>> in ordert to become able to send messages on GUI threads, they kept >>>> running into problems, >>>> losing a lot of time (even months because they could not get it >>>> working in more complex >>>> programs). >>>> >>>> To make a long story short, I came up with a message based solution, >>>> that was very easy to >>>> understand and to employ for them. None of the students ran into the >>>> GUI thread problems >>>> since then. >>>> >>>> The solution is an ooRexx class for awt (the Java "abstract windows >>>> toolkit") named >>>> .AwtGuiThread and for JavaFX (a powerful GUI system) .FxGuiThread, >>>> both subclassing a >>>> common superclass .AbstractGuiThread. These classes allow one to send >>>> the ooRexx message >>>> runLater[Latest](GUIreceiver, messageName, arguments) which get queued >>>> and dispatched on >>>> the GUI thread later. >>>> >>>> The nutshell examples >>>> "bsf4rexx/samples/3-090_update_awtSwing_GUI-from-non-GUI-thread.rxj" >>>> and >>>> "bsf4rexx/samples/JavaFX/javafx_update_GUI-from-non-GUI-thread.rxj" >>>> demonstrate how to >>>> employ this infrastructure. They have been working for years without a >>>> problem. >>>> >>>> While working on BSF4ooRexx I stumbled over an error (not having run >>>> those two examples for >>>> quite some time) which seems to indicate that ooRexx now creates an >>>> error when being used >>>> from different threads: >>>> >>>> >>>> F:\work\svn\bsf4oorexx\trunk\bsf4oorexx\samples>3-090_update_awtSwing_GUI-from-non-GUI-thread.rxj >>>> screenSize: [java.awt.Dimension[width=1920,height=1080]] >>>> winSize : [java.awt.Dimension[width=800,height=200]] >>>> xPos=[560] yPos=[440] >>>> a REXXEVENTHANDLER::actionPerformed - starting Rexx thread >>>> The SOME_REXX_CLASS class::updateGuiFromRexxThread - just arrived, >>>> GUI thread: 23808 >>>> The SOME_REXX_CLASS class::updateGuiFromRexxThread - now running >>>> on thread: 7428 >>>> *-* Compiled method "DELETE" with scope "Queue". >>>> 5727 *-* msgQueue~delete(idx) -- delete the guiMsg object >>>> 5637 *-* forward message "REMOVEMESSAGE" continue -- remove all >>>> GUI messages of the same name targeted to the same object >>>> 207 *-* .AwtGuiThread~runLaterLatest(label, "setText", "i", >>>> str) >>>> Error 93 running >>>> F:\work\svn\bsf4oorexx\trunk\bsf4oorexx\samples\3-090_update_awtSwing_GUI-from-non-GUI-thread.rxj >>>> line 207: Incorrect >>>> call to method. >>>> Error 93.966: Incorrect queue index "1". >>>> a REXXEVENTHANDLER::windowClosing - release lock >>>> ('closeApp=.true') which will allow a blocked 'waitForExit' method to >>>> resume and return >>>> >>>> F:\work\svn\bsf4oorexx\trunk\bsf4oorexx\samples> >>>> >>>> and >>>> >>>> >>>> F:\work\svn\bsf4oorexx\trunk\bsf4oorexx\samples\JavaFX>javafx_update_GUI-from-non-GUI-thread.rxj >>>> a REXXBUTTONHANDLER::handle - starting Rexx thread >>>> The SOME_REXX_CLASS class::updateGuiFromRexxThread - just arrived, >>>> GUI thread: 24244 >>>> The SOME_REXX_CLASS class::updateGuiFromRexxThread - now running >>>> on thread: 14124 >>>> *-* Compiled method "DELETE" with scope "Queue". >>>> 5727 *-* msgQueue~delete(idx) -- delete the guiMsg object >>>> 5637 *-* forward message "REMOVEMESSAGE" continue -- remove all >>>> GUI messages of the same name targeted to the same object >>>> 194 *-* .FxGuiThread~runLaterLatest(label, "setText", "i", >>>> str) >>>> Error 93 running >>>> F:\work\svn\bsf4oorexx\trunk\bsf4oorexx\samples\JavaFX\javafx_update_GUI-from-non-GUI-thread.rxj >>>> line 194: Incorrect call to method. >>>> Error 93.966: Incorrect queue index "1". >>>> >>>> The ooRexx code where the error occurs looks like, lines # 5637 and # >>>> 5727 are highlighted >>>> in green and bold: >>>> >>>> /* >>>> ------------------------------------------------------------------------------------------------- >>>> */ >>>> -- method replaces existing target: this way only the latest >>>> sent message will get executed! >>>> /** This class method allows to define a Rexx message with its >>>> arguments that should >>>> * be processed on the GUI thread. Each invocation will create a >>>> new <code>GUIMessage</code> >>>> * from the supplied arguments and returns it for further >>>> inspection in addition to queueing >>>> * it for later execution on the GUI thread. Unlike >>>> <code>runLater</code> this method will >>>> * first remove any queued messages with the same target and the >>>> same message name, before >>>> * queueing this message. >>>> * >>>> * @param target the target object to receive a message on the >>>> GUI thread >>>> * @param messageName the message name to send to the target on >>>> the GUI thread >>>> * @param indicator optional; indicates with "I" >>>> (Indivdual) that the arguments >>>> * are listed individually, "A" >>>> (Array) indicates that the fourth >>>> * argument is an array containing the >>>> arguments to supply with the >>>> * message on the GUI thread >>>> * >>>> * @return GUIMessage a GUI message object (modelled after >>>> ooRexx' <code>Message</code> class >>>> * that allows one to inspect the state of the >>>> message (process completed, >>>> * fetching a possible result, determining >>>> whether an error occurred and >>>> * inspecting it) >>>> */ >>>> ::method runLaterLatest class >>>> use strict arg target, messageName, ... >>>> >>>> signal on syntax >>>> if self~JavaGuiUtilityClz=.nil then self~setup -- make sure >>>> attributes are initialized >>>> >>>> *forward message "REMOVEMESSAGE" continue -- remove all GUI >>>> messages of the same name >>>> targeted to the same object* >>>> guiMsg=result -- fetch returned GUIMessage object >>>> msgQueue=self~msgQueue -- get message queue >>>> msgQueue~queue(guiMsg) -- now enqueue current (latest) >>>> guiMsg >>>> >>>> if self~waitingToRun=.false then -- "runLater" not invoked yet? >>>> do >>>> self~waitingToRun=.true >>>> self~invokeOnGuiThread -- make sure Java will dispatch Rexx >>>> message on GUI thread >>>> end >>>> return guiMsg -- allows caller to get a hold of a >>>> possible return value >>>> >>>> syntax: >>>> raise propagate >>>> >>>> ... cut ... >>>> >>>> /* >>>> ------------------------------------------------------------------------------------------------- >>>> */ >>>> -- method removes all GUI message objects >>>> /** This private class method removes all GUIMessage objects from >>>> the message queue that will be processed >>>> * later when Java call backs on the GUI thread, that have the >>>> supplied target and the supplied >>>> * message name. >>>> * >>>> * @param target the target object to receive a message on the >>>> GUI thread >>>> * @param messageName the message name to send to the target on >>>> the GUI thread >>>> * @param indicator optional; indicates with "I" >>>> (Indivdual) that the arguments >>>> * are listed individually, "A" >>>> (Array) indicates that the fourth >>>> * argument is an array containing the >>>> arguments to supply with the >>>> * message on the GUI thread >>>> * >>>> * @return GUIMessage a GUI message object (modelled after >>>> ooRexx' <code>Message</code> class >>>> * that allows one to inspect the state of the >>>> message (process completed, >>>> * fetching a possible result, determining >>>> whether an error occurred and >>>> * inspecting it) >>>> */ >>>> ::method removeMessage class private >>>> use strict arg target, messageName, ... >>>> >>>> signal on syntax >>>> if self~JavaGuiUtilityClz=.nil then self~setup -- make sure >>>> attributes are initialized >>>> >>>> -- remove all occurrences of messages with the same >>>> messagename and the same target >>>> msgQueue=self~msgQueue -- get message queue >>>> idx=msgQueue~first -- get index of the first item in >>>> the queue, if any >>>> do while idx<>.nil -- a valid index in hand ? >>>> tmpItem=msgQueue~at(idx) -- fetch item, a GuiMessage >>>> -- same target, same messagename? >>>> if tmpItem~target=target, >>>> tmpItem~messageName~caselessEquals(messagename) then >>>> *msgQueue~delete(idx) -- delete the guiMsg object*** >>>> idx=msgQueue~next(idx) -- get index of next item in the >>>> queue >>>> end >>>> >>>> guiMsg=self~createGuiMessage(arg(1,"array")) -- create and >>>> return GUI message object >>>> return guiMsg -- allows caller to get a hold of a >>>> possible return value >>>> >>>> syntax: >>>> raise propagate >>>> >>>> None of the methods of these three classes are marked as unguarded >>>> such that in the past if >>>> one method executes no other can do so in parallel, inhibiting >>>> concurrent access of the queue. >>>> >>>> However, I recall that there was a change in ooRexx 5.0 that if >>>> methods do not have an >>>> expose keyword statement than unlike earlier versions of ooRexx such >>>> expose-less methods >>>> will be made unguarded. >>>> >>>> Yet, as in this real use case this change may bring incompatibilities >>>> for existing programs >>>> (BSF4ooRexx has been around for more than 10 years). The problem lies >>>> in getting and using >>>> the queue in different threads because of this (at the time of >>>> devising the solution >>>> unforeseen) as no default blocking of methods takes place. >>>> >>>> To double-check I added manually "guarded" to all methods of the >>>> classes that play together >>>> here and doing so, made the nutshell programs work again. >>>> >>>> --- >>>> >>>> The reason I bring this forward is twofold: >>>> >>>> * the change may break existing programs and programmers may be >>>> clueless as to why that >>>> happens and therefore not know how to solve it, >>>> * it should be discussed whether keeping this change, but if so it >>>> needs to be >>>> prominently communicated as the cause may be too subtle for many, >>>> especially if using >>>> ooRexx code for which they do not have the source: >>>> o one solution may be to have a new OPTION unguared|guarded >>>> determining how >>>> expose-less methods should be treated; this way this default >>>> to unguarded behavior >>>> needs to be activated explicitly making the programmer aware >>>> of it, yet older >>>> programs still would function with the default to guarded >>>> behavior that was in >>>> place in erarlier versions of ooRexx, >>>> o another solution would be to not only analyze whether the >>>> expose statement exists, >>>> but in the case where it does not exist also analyze whether >>>> messages to self occur >>>> and if so leave the method guarded; however this bears the >>>> problem that one could >>>> use an object that refers to self such that the problem might >>>> surface nevertheless. >>>> >>>> Any thoughts, ideas, suggestions, conclusions? >>>> >>>> ---ron >>>>
_______________________________________________ Oorexx-devel mailing list Oorexx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/oorexx-devel