I hardly ever use EXPOSE when oo-ing, I am almost always declaring attributes and accessing them via self~attribute _name in the methods within the class and its subclasses.

Ruurd

On 8/7/21 7:59 PM, Sahananda Sahananda wrote:
Hi Guys,

This is awkward, I think this change was made in response to my expressing surprise that the guard made a difference to methods which have no variables exposed - something that I still don't understand, but have no need to understand.  However, if you think it should go, then I'm content for it to go.

BTW, and just for correctness sake, I think the default guard state was changed before, sometime in version 3.x I think.  I remember that I had to change all my oodialog message handling methods to be explicitly unguarded.

Jon

On Sat, 7 Aug 2021, 18:36 Jean Louis Faucher, <jfaucher...@gmail.com <mailto:jfaucher...@gmail.com>> wrote:

    +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 <mailto: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 &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?

    ---rony


    _______________________________________________
    Oorexx-devel mailing list
    Oorexx-devel@lists.sourceforge.net
    <mailto:Oorexx-devel@lists.sourceforge.net>
    https://lists.sourceforge.net/lists/listinfo/oorexx-devel
    <https://lists.sourceforge.net/lists/listinfo/oorexx-devel>

    _______________________________________________
    Oorexx-devel mailing list
    Oorexx-devel@lists.sourceforge.net
    <mailto:Oorexx-devel@lists.sourceforge.net>
    https://lists.sourceforge.net/lists/listinfo/oorexx-devel
    <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
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel

Reply via email to