Thanks Mark,  I think that helps me, at least it gives me
some more reading and ideas of how to relate the usage
to my specific situation.  I am assuming that any action
from a button or from a menu selection, along with the
items like LostFocus/GotFocus/Update, etc are all events
and should all be unGuarded.  Methods that are invoked
from any of these “action generating” methods may not
need to be guarded unless there is a method that can be
invoked from multiple of the other events.  Am I close to
understanding it so far?  Thanks again..
  Art

From: Mark Miesfeld 
Sent: Sunday, August 18, 2013 3:58 PM
To: Open Object Rexx Users 
Subject: Re: [Oorexx-users] unGuarded vs Guarded

On Sun, Aug 18, 2013 at 10:59 AM, Art Heimsoth <artst...@artheimsoth.com> wrote:

  Is there an explanation on when unguarded should be used on a method,
  or when it should not be used?  

Hi Art,

First, I'll give you some areas to read in the ooRexx reference manual and in 
ooDialog, then I'll try to add a little explanation.

To understand guarded / unguarded you need to know it is related to 
concurrency.  So, you should read the section Chapter 12 Concurrency to get an 
idea of how ooRexx implements concurrency.

Guarded / UnGuarded is explained in Chapter 3 Directives, section 3.4 Methods, 
where guarded/ungurarded is briefly explained in the notes at the end of the 
section.

To understand how concurrency relates to ooDialog you need to understand events 
and event handlers in ooDialog.  You should read 3.6 Event Notification Mixin 
Class, 3.6.1 Connecting Event Handlers, and 3.6.2 Coding Event Handlers.  

In addtion, in Chapter 1 Brief Overview, some basic concepts are explained.  
Reading section 1.3.3 Events and section 1.3.14 Window Messages should help.


  Or alternatively what it does vs what is
  done without it?  It doesn’t appear to be a blocking protection on the 
  method if not present, but does appear to do some sort of serialization
  if not present

Basically when a method of an object is guarded no other guarded method of that 
object can run.  When a method is unguarded it can run even if some other 
method in the object is executing.  

Nothing is ever as simple as "basically ..."  One exception to the above is 
that a guarded method can invoke another guarded method in the object and that 
method will execute.  I.e.:

::class 'example'
::method a 

  -- do stuff
  self~b()
  -- do more stuff

::method b
  -- do stuff
  return

So, even though both methods a and b are guarded, when b() is invoked from 
method a() it executes.

  – but I am confused on how to figure out when to and
  when not to use it on a method.  


Concurrency is not simple, so there are no simplistic statements that will make 
everything crystal clear.

In general, one use of guarded is to prevent non-deterministic access to the 
object's variables.  In general I make every method guarded until I see that a 
method needs to be unguarded.

In ooDialog, I have a general statement: make every event handler unguarded.

To understand this, you need to understand the window processing loop.  The OS 
sends a message to a window, the window's message processing loop does 
something in response to the message and returns a value to the OS.  The 
message processing loop then processes the next message.

The OS stacks the messages up in a queue, the processing loop pulls them out of 
the queue one by one.

Let's say the user clicks on a button in a dialog, then uses the mouse to move 
the dialog up 1 pixel.

If, in the window processing loop, the application sleeps for 40 seconds when 
it processes the button click and then returns a value to the OS.  For 40 
seconds, the message to move the dialog up 1 pixel sits in the queue 
unprocessed.  To the user, it appears that she can not move the dialog with the 
mouse.

Back to ooDialog specific.   The ooDialog framework starts a window message 
processing loop, in a separate thread, for every dialog you the programmer 
create.  Within that processing loop, for every message, the ooDialog framework 
returns a value to the OS that essentially means: 'do the default for this 
message', *unless*, you the programmer have connected that message to an event 
handler.

In the message processing loop, when the ooDialog framework sees a message that 
has been "connected", the framework invokes the method in the dialog that the 
programmer connected.

Take this simple dialog:

/* Simple User Dialog to produce a dialog that will appear hung */

  .application~useGlobalConstDir('O')
  .constDir[IDC_PB_ONE] = 100
  .constDir[IDC_PB_TWO] = 110

  dlg = .SimpleDialog~new
  dlg~execute("SHOWTOP", IDI_DLG_OOREXX)

::requires "ooDialog.cls"

::class 'SimpleDialog' subclass UserDialog

::method init
  forward class (super) continue

  self~create(30, 30, 257, 123, "Simple Dialog", "CENTER")

::method defineDialog

  self~createPushButton(IDC_PB_ONE, 10, 10, 50, 14, "", "Push Me Now", 
'buttonClick1')
  self~createPushButton(IDC_PB_TWO, 10, 30, 75, 14, "", "Push Me Now Also", 
'buttonClick2')
  self~createPushButton(IDOK, 142, 99, 50, 14, "DEFAULT", "Ok")
  self~createPushButton(IDCANCEL, 197, 99, 50, 14, , "Cancel")


::method buttonClick1
  say 'in buttonClick1()'
  j = SysSleep(40)
  say 'leaving buttonClick1()'


::method buttonClick2
  say 'in buttonClick2()'
  j = SysSleep(40)
  say 'leaving buttonClick2()'


::method ok
  say 'in ok()'
  j = SysSleep(40)
  say 'leaving ok()'
  self~ok:super

::method cancel
  say 'in cancel()'
  j = SysSleep(40)
  say 'leaving cancel()'
  self~cancel:super

Run the dialog and click the 'Push Me Now' button immediately.  Then push any 
other button, nothing will happen.  Typically a user will then start pushing 
other buttons.  Try to close the dialog by pushing ok or cancel, you won't be 
able to.  The more times you push the buttons or try to close the dialog, the 
longer it will be before the program finally ends.

What happens is:  you push the 'Push Me Now' button, the guarded buttonClick1() 
method starts executing.  You push the 'Push Me Now Also' button, the guarded 
buttonClick2() is invoked, but can not run until all other guarded methods are 
not running.

You, the user, get exasperated and push the cancel button.  The guarded 
cancel() method is invoked by the framework - but it can not run until all 
other guarded methods are not running.

At this point, the dialog is not going to end for 120 seconds.  The ooRexx 
interpreter is not going to end until all invoked methods have completed.  The 
more you try to close the dialog, the worse your situation gets.

Now make all the event handling methods unguarded.  Each time you click a 
button, you will immediately see the 'in methodName()' message.  This shows 
that all the event handlers are now running concurrently.

You still won't see the program end immediately when you push the ok or cancel 
program because you have started all these 40 second threads.  But, if you push 
5 buttons pretty quickly you will see the program end in about 40 seconds 
rather than 200 seconds.

Now, in the guarded version, after you push the first button, you will still be 
able to move the dialog around with the mouse.  This seems to contradict what I 
originally said.  The reason for this is that, for button clicks, the ooDialog 
framework actually invokes the event handler using start() and so the message 
processing loop immediately returns a value to the OS and continues processing 
messages.

But try this program:

/* Simple User Dialog to produce a dialog that will appear hung */

  .application~useGlobalConstDir('O')
  .constDir[IDC_PB_ONE] = 100
  .constDir[IDC_PB_TWO] = 110
  .constDir[IDC_EDIT] = 120
  .constDir[IDC_UPD] = 130

  dlg = .SimpleDialog~new
  dlg~execute("SHOWTOP", IDI_DLG_OOREXX)

::requires "ooDialog.cls"

::class 'SimpleDialog' subclass UserDialog

::method init
  forward class (super) continue

  self~create(30, 30, 257, 123, "Simple Dialog", "CENTER")

::method defineDialog

  self~createPushButton(IDC_PB_ONE, 10, 10, 50, 14, "", "Push Me Now", 
'buttonClick1')
  self~createPushButton(IDC_PB_TWO, 10, 30, 75, 14, "", "Push Me Now Also", 
'buttonClick2')
  self~createEdit(IDC_EDIT, 10, 60, 50, 14)
  self~createUpDown(IDC_UPD, 60, 60, 15, 15, 'WRAP ARROWKEYS AUTOBUDDY 
SETBUDDYINT')
  self~createPushButton(IDOK, 142, 99, 50, 14, "DEFAULT", "Ok")
  self~createPushButton(IDCANCEL, 197, 99, 50, 14, , "Cancel")

  self~connectUpDownEvent(IDC_UPD, "DELTAPOS", onUPD)

::method onUPD
  say 'in onUPD()'
  j = SysSleep(40)
  say 'leaving onUPD()'
  return .UpDown~deltaPosReply

::method buttonClick1
  say 'in buttonClick1()'
  j = SysSleep(40)
  say 'leaving buttonClick1()'


::method buttonClick2
  say 'in buttonClick2()'
  j = SysSleep(40)
  say 'leaving buttonClick2()'


::method ok
  say 'in ok()'
  j = SysSleep(40)
  say 'leaving ok()'
  self~ok:super

::method cancel
  say 'in cancel()'
  j = SysSleep(40)
  say 'leaving cancel()'
  self~cancel:super

For the UpDown DELTAPOS envent, the ooDialog framework waits for the reply from 
the event handler.

Run this program - click the 'Push Me Now' button, immediately click an arrow 
in the UpdDown control, and immediately use the mouse to try and move the 
window.  You won't be able to.

In Windows 7, the OS will detect that your dialog is not processing messages 
and start the special "Window is not responding" behavior after about 5 
seconds.  This allows the user to move the window and close it.  Without that 
special behavior things would be truly hung.  But, the way the user can close 
the dialog is through the Window is not responding dialog that the OS puts up.  
Not real user friendly.

Not sure how much help this has been.  But, at least you should be able to see 
why you usually need make your event handlers unguarded.

--
Mark Miesfeld







  If it is described somewhere, point me
  to it as I did not find it when searching.  Thanks,
    Art


  ------------------------------------------------------------------------------
  Get 100% visibility into Java/.NET code with AppDynamics Lite!
  It's a free troubleshooting tool designed for production.
  Get down to code-level detail for bottlenecks, with <2% overhead.
  Download for free and get started troubleshooting in minutes.
  http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
  _______________________________________________
  Oorexx-users mailing list
  Oorexx-users@lists.sourceforge.net
  https://lists.sourceforge.net/lists/listinfo/oorexx-users





--------------------------------------------------------------------------------
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead. 
Download for free and get started troubleshooting in minutes. 
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk 


--------------------------------------------------------------------------------
_______________________________________________
Oorexx-users mailing list
Oorexx-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-users
------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead. 
Download for free and get started troubleshooting in minutes. 
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
_______________________________________________
Oorexx-users mailing list
Oorexx-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-users

Reply via email to