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

Reply via email to