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

Reply via email to