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 &quot;I&quot; 
>>> (Indivdual) that the arguments
>>>         *                     are listed individually, &quot;A&quot; 
>>> (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 &quot;I&quot; 
>>> (Indivdual) that the arguments
>>>         *                     are listed individually, &quot;A&quot; 
>>> (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

Reply via email to