+1 If you run the example 12.4 of rexxref, you will see that it breaks the rule written just above.
Regards > On 7 Aug 2021, at 18:28, Rony G. Flatscher <rony.flatsc...@wu.ac.at> 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: >> 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, >> 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? >> >> ---rony >> > > _______________________________________________ > Oorexx-devel mailing list > Oorexx-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/oorexx-devel
_______________________________________________ Oorexx-devel mailing list Oorexx-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/oorexx-devel