Nice, thanks!!
 
You can probably guess which one, showing threads, that I prefer :-))
 
Mike
 


  _____  

From: Rony G. Flatscher [mailto:rony.flatsc...@wu.ac.at] 
Sent: 06 February 2024 10:47
To: oorexx-devel@lists.sourceforge.net
Subject: [Oorexx-devel] Brief explanations on ooRexx' multithreading
capabilities and the desired sample outputs (Re: Mike's suggestion added
(Re: Another updated version for testing (Re: An updated version available
(Re: Ad debugging multithreaded programs, a wor


On 05.02.2024 17:07, Mike Cowlishaw wrote:


There is a new version to  

*       

         incorporate Mike's suggestion of inserting the thread number into
the trace prefix after the second character, the option is 'T' (for thread),

*       

        a new (artificial) program that creates many threads such that the
different formats can be compared ("docpgm.rex") by supplying the option
(defaults to N, possible in addition T[hread], S[tandard], F[ull]) and the
number of objects (defaults to 1) to create, 


Any sample outputs?  Curious to see how it looks, even though I don't really
have a use for it :-).

Here we go. 

First a few remarks on multithreading in ooRexx: 

*       to use multithreading is very easy in ooRexx, it is realized via
messages that can be sent 




*       synchroneously (the default, the sender waits until the message got
processed in full, i.e. the invoked method routine ends and returns) or



*       asynchroneously (the message gets sent on a new thread, the sender
continues immediately),



*       the ooRexx root class .Object has a "send" and "start" method that
allows to submit the name of a message as a string (e.g. from a variable)
from which a message object gets created and the message dispatched using
"send" or "start" respectively, 



*       there is a REPLY keyword statement available in method routines that
will return to the sender/caller, but the remaining statements of that
method routine will continue to get executed on a separate thread,



*       messages in ooRexx are represented with the .Message class which
defines a method "send" for synchroneously and "start" for asynchroneously
(on a separate thread) sending messages. The message object can be used to
see whether e.g. an asynchroneous message is still running, but also what
result a message delivered (cf. rexxref.pdf, "5.1.2. Message Class"),



*       there is an .Alarm class (cf. rexxref.pdf, "5.4.1. Alarm Class")
that can be used to send a message at a later time on a separate thread,



*       if a method routine is guarded (the default) then it can only
execute if it possesses the object lock, 



*       if a method routine is unguarded it can always execute,



*       there is a "GUARD" keyword statement that can be used on
synchronizing different method routines on different threads, controlling
whether an object lock needs to be acquired (GUARD ON, GUARD ON WHEN ...) or
whether an object lock gets released (GUARD OFF, GUARD OFF WHEN ...) such
that other, currently blocked method routines can gain the object lock and
continue to execute.


The following test program is written such that it creates many threads on
which Rexx code executes (to simulate as much as possible real world,
complex multithreaded programs, e.g. in the context of powerful GUIs
especially in the Java world, like JavaFX). The test program uses all of the
above possibilities to also allow tracing their effects and demonstrating
how the different formats help gain insight.

Here an edited (updated) version of the program named "docpgm.rex", which
can be invoked with the trace option and a number indicating how many
objects should be created (the more objects the more threads):

/* this is an artificial program that creates many threads */

parse upper arg option rounds

if option<>"" then .traceObject~option=option

say ".traceObject~option:" .traceObject~option

if rounds="" then rounds=1



do counter c rounds

   say "round #" c"/"rounds

   obj=.demoMT~new

      -- from now on send messages asynchroneously (on separate threads)

   obj~~start("mg")~~start("mu")~~start("bumpCtlAttribute")

   msg=.message~new(obj,"bumpCtlAttribute")  -- message to send later

   waitTime=.timeSpan~fromLongTime("00:00:0" || random(15,25)/1000)  -- wait
a few msecs

      -- commenting the following two statements will cause deadlocks

   .alarm~new(waitTime, msg)  -- send message after waitTime, will unblock

   .alarm~new(waitTime, msg)  -- send message after waitTime, will unblock

end



::class "demoMT"        -- a class for experimenting with threads



::method init           -- guarded method

  expose ctlAttribute

  ctlAttribute=random(0,125)/1000   -- add some randomness



::method bumpCtlAttribute unguarded -- unguarded method

  expose ctlAttribute

  TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

  do 50                 -- change value of ctlAttribute 50 times

     ctlAttribute=random(100,250)/1000 -- add some randomness

  end

  ctlAttribute=1        -- make sure a value that unblocks

  say .line "ctlAttribute="ctlAttribute



::method mg             -- guarded method

  expose ctlAttribute

  guard off                         -- guard off

  reply           -- return, remainder on new thread

  guard on  when ctlAttribute>0.250 -- guard on

  ctlAttribute=random(0,125)/1000   -- add some randomness

  call sysSleep random(1,10)/1000   -- add some randomness

  guard off when ctlAttribute>0.250 -- guard off

  ctlAttribute=random(0,125)/1000   -- add some randomness

  say .context~name": returning ..."



::method mu unguarded   -- unguarded method

  expose ctlAttribute

  guard on                          -- guard on

  reply           -- return, remainder on new thread

  guard off when ctlAttribute>0.250 -- guard off

  ctlAttribute=random(0,125)/1000   -- add some randomness

  guard on  when ctlAttribute>0.250 -- guard on

  call sysSleep random(1,10)/1000   -- add some randomness

  say .context~name": returning ..."



::options trace r


Here the output of running the program as: "rexx docpgm.rex"

     2 *-* parse upper arg option rounds

       >>>   ""

       >>>   ""

       >>>   ""

     3 *-* if option<>""

       >>>   "0"

     4 *-* say ".traceObject~option:" .traceObject~option

       >>>   ".traceObject~option: N"

.traceObject~option: N

     5 *-* if rounds=""

       >>>   "1"

     5 *-*   then

     5 *-*     rounds=1

       >>>       "1"

     7 *-* do counter c rounds

       >K>   "COUNTER" => "0"

       >K>   "FOR" => "1"

       >K>     "COUNTER" => "1"

     8 *-*   say "round #" c"/"rounds

       >>>     "round # 1/1"

round # 1/1

     9 *-*   obj=.demoMT~new

       >I> Method "INIT" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

    22 *-* expose ctlAttribute

    23 *-* ctlAttribute=random(0,125)/1000   -- add some randomness

       >>>   "0.014"

       >>>     "a demoMT"

    11 *-*   obj~~start("mg")~~start("mu")~~start("bumpCtlAttribute")

    12 *-*   msg=.message~new(obj,"bumpCtlAttribute")  -- message to send
later

       >I> Method "BUMPCTLATTRIBUTE" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I> Method "MG" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I> Method "MU" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >>>     "a Message"

    26 *-* expose ctlAttribute

    35 *-* expose ctlAttribute

    46 *-* expose ctlAttribute

    13 *-*   waitTime=.timeSpan~fromLongTime("00:00:0" ||
random(15,25)/1000)  -- wait a few msecs

    27 *-* TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

32 ctlAttribute=1

    36 *-* guard off                         -- guard off

    47 *-* guard on                          -- guard on

       >>>     "a TimeSpan"

    37 *-* reply           -- return, remainder on new thread

    48 *-* reply           -- return, remainder on new thread

    15 *-*   .alarm~new(waitTime, msg)  -- send message after waitTime, will
unblock

       >I> Method "MG" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I> Method "MU" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

    16 *-*   .alarm~new(waitTime, msg)  -- send message after waitTime, will
unblock

    38 *-* guard on  when ctlAttribute>0.250 -- guard on

    49 *-* guard off when ctlAttribute>0.250 -- guard off

    17 *-* end

       >K>   "WHEN" => "1"

       >K>   "WHEN" => "1"

     7 *-* do counter c rounds

    50 *-* ctlAttribute=random(0,125)/1000   -- add some randomness

    39 *-* ctlAttribute=random(0,125)/1000   -- add some randomness

       >>>   "0.088"

       >>>   "0.056"

    51 *-* guard on  when ctlAttribute>0.250 -- guard on

    40 *-* call sysSleep random(1,10)/1000   -- add some randomness

       >I> Method "BUMPCTLATTRIBUTE" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I> Method "BUMPCTLATTRIBUTE" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

    26 *-* expose ctlAttribute

    26 *-* expose ctlAttribute

    27 *-* TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

    27 *-* TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

32 ctlAttribute=1       >K>   "WHEN" => "0"



32 ctlAttribute=1       >K>   "WHEN" => "1"



    52 *-* call sysSleep random(1,10)/1000   -- add some randomness

       >>>   "0"

    41 *-* guard off when ctlAttribute>0.250 -- guard off

       >K>   "WHEN" => "1"

    42 *-* ctlAttribute=random(0,125)/1000   -- add some randomness

       >>>   "0.003"

    43 *-* say .context~name": returning ..."

       >>>   "MG: returning ..."

MG: returning ...

       >>>   "0"

    53 *-* say .context~name": returning ..."

       >>>   "MU: returning ..."

MU: returning ...

Clearly, the threads on which each statement executes would become
interesting and in case of a deadlock important.

---


Here Mike's minimal change to the trace prefix available in the portable
debug version of ooRexx  for Windows at
<https://wi.wu.ac.at/rgf/rex/tmp/20240128_mt/>
<https://wi.wu.ac.at/rgf/rex/tmp/20240128_mt/>. The command in this case is
"rexx "rexx docpgm.rex t" (the argument "t" stands for thread):

     2 *-* parse upper arg option rounds

       >>>   "T"

       >>>   "T"

       >>>   ""

     3 *-* if option<>""

       >>>   "1"

     3 *-*   then

     3 *-*     .traceObject~option=option

     4 *-1* say ".traceObject~option:" .traceObject~option

       >>1>   ".traceObject~option: T"

.traceObject~option: T

     5 *-1* if rounds=""

       >>1>   "1"

     5 *-1*   then

     5 *-1*     rounds=1

       >>1>       "1"

     7 *-1* do counter c rounds

       >K1>   "COUNTER" => "0"

       >K1>   "FOR" => "1"

       >K1>     "COUNTER" => "1"

     8 *-1*   say "round #" c"/"rounds

       >>1>     "round # 1/1"

round # 1/1

     9 *-1*   obj=.demoMT~new

       >I1> Method "INIT" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

    22 *-1* expose ctlAttribute

    23 *-1* ctlAttribute=random(0,125)/1000   -- add some randomness

       >>1>   "0.095"

       >>1>     "a demoMT"

    11 *-1*   obj~~start("mg")~~start("mu")~~start("bumpCtlAttribute")

    12 *-1*   msg=.message~new(obj,"bumpCtlAttribute")  -- message to send
later

       >I2> Method "BUMPCTLATTRIBUTE" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I3> Method "MG" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I4> Method "MU" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >>1>     "a Message"

    26 *-2* expose ctlAttribute

    35 *-3* expose ctlAttribute

    46 *-4* expose ctlAttribute

    13 *-1*   waitTime=.timeSpan~fromLongTime("00:00:0" ||
random(15,25)/1000)  -- wait a few msecs

    27 *-2* TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

32 ctlAttribute=1

    36 *-3* guard off                         -- guard off

    47 *-4* guard on                          -- guard on

       >>1>     "a TimeSpan"

    37 *-3* reply           -- return, remainder on new thread

    48 *-4* reply           -- return, remainder on new thread

    15 *-1*   .alarm~new(waitTime, msg)  -- send message after waitTime,
will unblock

       >I2> Method "MG" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I3> Method "MU" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

    16 *-1*   .alarm~new(waitTime, msg)  -- send message after waitTime,
will unblock

    38 *-2* guard on  when ctlAttribute>0.250 -- guard on

    49 *-3* guard off when ctlAttribute>0.250 -- guard off

    17 *-1* end

       >K3>   "WHEN" => "1"

       >K2>   "WHEN" => "1"

     7 *-1* do counter c rounds

    50 *-3* ctlAttribute=random(0,125)/1000   -- add some randomness

    39 *-2* ctlAttribute=random(0,125)/1000   -- add some randomness

       >>3>   "0.07"

       >>2>   "0.079"

    51 *-3* guard on  when ctlAttribute>0.250 -- guard on

    40 *-2* call sysSleep random(1,10)/1000   -- add some randomness

       >>2>   "0"

       >I4> Method "BUMPCTLATTRIBUTE" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

       >I5> Method "BUMPCTLATTRIBUTE" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

    41 *-2* guard off when ctlAttribute>0.250 -- guard off

    26 *-4* expose ctlAttribute

    26 *-5* expose ctlAttribute

       >K2>   "WHEN" => "0"

       >K3>   "WHEN" => "0"

    27 *-4* TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

    27 *-5* TRACE n               -- set trace to normal (in method
"bumpCtlAttribute")

32 ctlAttribute=1       >K2>   "WHEN" => "0"



32 ctlAttribute=1       >K3>   "WHEN" => "0"



       >K2>   "WHEN" => "1"

       >K3>   "WHEN" => "1"

    42 *-2* ctlAttribute=random(0,125)/1000   -- add some randomness

    52 *-3* call sysSleep random(1,10)/1000   -- add some randomness

       >>2>   "0.086"

    43 *-2* say .context~name": returning ..."

       >>2>   "MG: returning ..."

MG: returning ...

       >>3>   "0"

    53 *-3* say .context~name": returning ..."

       >>3>   "MU: returning ..."

MU: returning ...

---

Here the "S"tandard multithreaded trace prefix version, running "rexx "rexx
docpgm.rex s" (the argument "s" stands for standard): 

     2 *-* parse upper arg option rounds

       >>>   "S"

       >>>   "S"

       >>>   ""

     3 *-* if option<>""

       >>>   "1"

     3 *-*   then

     3 *-*     .traceObject~option=option

[T1   I1   ]               4 *-* say ".traceObject~option:"
.traceObject~option

[T1   I1   ]                 >>>   ".traceObject~option: S"

.traceObject~option: S

[T1   I1   ]               5 *-* if rounds=""

[T1   I1   ]                 >>>   "1"

[T1   I1   ]               5 *-*   then

[T1   I1   ]               5 *-*     rounds=1

[T1   I1   ]                 >>>       "1"

[T1   I1   ]               7 *-* do counter c rounds

[T1   I1   ]                 >K>   "COUNTER" => "0"

[T1   I1   ]                 >K>   "FOR" => "1"

[T1   I1   ]                 >K>     "COUNTER" => "1"

[T1   I1   ]               8 *-*   say "round #" c"/"rounds

[T1   I1   ]                 >>>     "round # 1/1"

round # 1/1

[T1   I1   ]               9 *-*   obj=.demoMT~new

[T1   I2    G L0    ]        >I> Method "INIT" with scope "demoMT" in
package "G:\test\orx\trace\docpgm.rex".

[T1   I2    G L1   *]     22 *-* expose ctlAttribute

[T1   I2    G L1   *]     23 *-* ctlAttribute=random(0,125)/1000   -- add
some randomness

[T1   I2    G L1   *]        >>>   "0.104"

[T1   I1   ]                 >>>     "a demoMT"

[T1   I1   ]              11 *-*
obj~~start("mg")~~start("mu")~~start("bumpCtlAttribute")

[T1   I1   ]              12 *-*   msg=.message~new(obj,"bumpCtlAttribute")
-- message to send later

[T2   I3    G L0    ]        >I> Method "MG" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

[T3   I4    U L0    ]        >I> Method "MU" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

[T4   I5    U L0    ]        >I> Method "BUMPCTLATTRIBUTE" with scope
"demoMT" in package "G:\test\orx\trace\docpgm.rex".

[T1   I1   ]                 >>>     "a Message"

[T2   I3    G L1   *]     35 *-* expose ctlAttribute

[T3   I4    U L1    ]     46 *-* expose ctlAttribute

[T4   I5    U L1    ]     26 *-* expose ctlAttribute

[T1   I1   ]              13 *-*   waitTime=.timeSpan~fromLongTime("00:00:0"
|| random(15,25)/1000)  -- wait a few msecs

[T2   I3    G L1   *]     36 *-* guard off                         -- guard
off

[T3   I4    U L1    ]     47 *-* guard on                          -- guard
on

[T4   I5    U L1    ]     27 *-* TRACE n               -- set trace to
normal (in method "bumpCtlAttribute")

32 ctlAttribute=1

[T1   I1   ]                 >>>     "a TimeSpan"

[T2   I3    G L0    ]     37 *-* reply           -- return, remainder on new
thread

[T3   I4    U L1   *]     48 *-* reply           -- return, remainder on new
thread

[T1   I1   ]              15 *-*   .alarm~new(waitTime, msg)  -- send
message after waitTime, will unblock

[T4   I3    G L1    ]        >I> Method "MG" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

[T2   I4    U L1   *]        >I> Method "MU" with scope "demoMT" in package
"G:\test\orx\trace\docpgm.rex".

[T1   I1   ]              16 *-*   .alarm~new(waitTime, msg)  -- send
message after waitTime, will unblock

[T4   I3    G L1    ]     38 *-* guard on  when ctlAttribute>0.250 -- guard
on

[T2   I4    U L1   *]     49 *-* guard off when ctlAttribute>0.250 -- guard
off

[T1   I1   ]              17 *-* end

[T2   I4    U L1    ]        >K>   "WHEN" => "1"

[T4   I3    G L1   *]        >K>   "WHEN" => "1"

[T1   I1   ]               7 *-* do counter c rounds

[T2   I4    U L1    ]     50 *-* ctlAttribute=random(0,125)/1000   -- add
some randomness

[T4   I3    G L1   *]     39 *-* ctlAttribute=random(0,125)/1000   -- add
some randomness

[T2   I4    U L1    ]        >>>   "0.072"

[T4   I3    G L1   *]        >>>   "0.051"

[T2   I4    U L1    ]     51 *-* guard on  when ctlAttribute>0.250 -- guard
on

[T5   I6    U L1    ]        >I> Method "BUMPCTLATTRIBUTE" with scope
"demoMT" in package "G:\test\orx\trace\docpgm.rex".

[T3   I7    U L1    ]        >I> Method "BUMPCTLATTRIBUTE" with scope
"demoMT" in package "G:\test\orx\trace\docpgm.rex".

[T4   I3    G L1   *]     40 *-* call sysSleep random(1,10)/1000   -- add
some randomness

[T5   I6    U L1    ]     26 *-* expose ctlAttribute

[T3   I7    U L1    ]     26 *-* expose ctlAttribute

[T5   I6    U L1    ]     27 *-* TRACE n               -- set trace to
normal (in method "bumpCtlAttribute")

[T3   I7    U L1    ]     27 *-* TRACE n               -- set trace to
normal (in method "bumpCtlAttribute")

[T2   I4    U L1   *]        >K>   "WHEN" => "0"32 ctlAttribute=1



[T2   I4    U L2   *]        >K>   "WHEN" => "1"

32 ctlAttribute=1

[T2   I4    U L2   *]     52 *-* call sysSleep random(1,10)/1000   -- add
some randomness

[T4   I3    G L2   *]        >>>   "0"

[T4   I3    G L2   *]     41 *-* guard off when ctlAttribute>0.250 -- guard
off

[T4   I3    G L1    ]        >K>   "WHEN" => "1"

[T4   I3    G L1    ]     42 *-* ctlAttribute=random(0,125)/1000   -- add
some randomness

[T4   I3    G L1    ]        >>>   "0.024"

[T4   I3    G L1    ]     43 *-* say .context~name": returning ..."

[T4   I3    G L1    ]        >>>   "MG: returning ..."

MG: returning ...

[T2   I4    U L1   *]        >>>   "0"

[T2   I4    U L1   *]     53 *-* say .context~name": returning ..."

[T2   I4    U L1   *]        >>>   "MU: returning ..."

MU: returning ...

The legend in the bracketed part: "T" ... thread, "I" ... invocation, "G" or
"U" method was defined as guarded or unguarded, "L" ... object Lock count,
"*" possessing the object's lock.

---


Here the "F"ull multithreaded trace prefix version, running "rexx "rexx
docpgm.rex f" (the argument "f" stands for full): 

     2 *-* parse upper arg option rounds

       >>>   "F"

       >>>   "F"

       >>>   ""

     3 *-* if option<>""

       >>>   "1"

     3 *-*   then

     3 *-*     .traceObject~option=option

[R1   T1   I1   ]                     4 *-* say ".traceObject~option:"
.traceObject~option

[R1   T1   I1   ]                       >>>   ".traceObject~option: F"

.traceObject~option: F

[R1   T1   I1   ]                     5 *-* if rounds=""

[R1   T1   I1   ]                       >>>   "1"

[R1   T1   I1   ]                     5 *-*   then

[R1   T1   I1   ]                     5 *-*     rounds=1

[R1   T1   I1   ]                       >>>       "1"

[R1   T1   I1   ]                     7 *-* do counter c rounds

[R1   T1   I1   ]                       >K>   "COUNTER" => "0"

[R1   T1   I1   ]                       >K>   "FOR" => "1"

[R1   T1   I1   ]                       >K>     "COUNTER" => "1"

[R1   T1   I1   ]                     8 *-*   say "round #" c"/"rounds

[R1   T1   I1   ]                       >>>     "round # 1/1"

round # 1/1

[R1   T1   I1   ]                     9 *-*   obj=.demoMT~new

[R1   T1   I2    G A1    L0    ]        >I> Method "INIT" with scope
"demoMT" in package "G:\test\orx\trace\docpgm.rex".

[R1   T1   I2    G A1    L1   *]     22 *-* expose ctlAttribute

[R1   T1   I2    G A1    L1   *]     23 *-* ctlAttribute=random(0,125)/1000
-- add some randomness

[R1   T1   I2    G A1    L1   *]        >>>   "0.089"

[R1   T1   I1   ]                       >>>     "a demoMT"

[R1   T1   I1   ]                    11 *-*
obj~~start("mg")~~start("mu")~~start("bumpCtlAttribute")

[R1   T1   I1   ]                    12 *-*
msg=.message~new(obj,"bumpCtlAttribute")  -- message to send later

[R1   T2   I3    G A1    L0    ]        >I> Method "MG" with scope "demoMT"
in package "G:\test\orx\trace\docpgm.rex".

[R1   T3   I4    U A1    L0    ]        >I> Method "MU" with scope "demoMT"
in package "G:\test\orx\trace\docpgm.rex".

[R1   T4   I5    U A1    L0    ]        >I> Method "BUMPCTLATTRIBUTE" with
scope "demoMT" in package "G:\test\orx\trace\docpgm.rex".

[R1   T1   I1   ]                       >>>     "a Message"

[R1   T2   I3    G A1    L1   *]     35 *-* expose ctlAttribute

[R1   T3   I4    U A1    L1    ]     46 *-* expose ctlAttribute

[R1   T4   I5    U A1    L1    ]     26 *-* expose ctlAttribute

[R1   T1   I1   ]                    13 *-*
waitTime=.timeSpan~fromLongTime("00:00:0" || random(15,25)/1000)  -- wait a
few msecs

[R1   T2   I3    G A1    L1   *]     36 *-* guard off
-- guard off

[R1   T3   I4    U A1    L1    ]     47 *-* guard on
-- guard on

[R1   T4   I5    U A1    L1    ]     27 *-* TRACE n               -- set
trace to normal (in method "bumpCtlAttribute")

32 ctlAttribute=1

[R1   T1   I1   ]                       >>>     "a TimeSpan"

[R1   T2   I3    G A1    L0    ]     37 *-* reply           -- return,
remainder on new thread

[R1   T3   I4    U A1    L1   *]     48 *-* reply           -- return,
remainder on new thread

[R1   T1   I1   ]                    15 *-*   .alarm~new(waitTime, msg)  --
send message after waitTime, will unblock

[R1   T4   I3    G A1    L1    ]        >I> Method "MG" with scope "demoMT"
in package "G:\test\orx\trace\docpgm.rex".

[R1   T2   I4    U A1    L1   *]        >I> Method "MU" with scope "demoMT"
in package "G:\test\orx\trace\docpgm.rex".

[R1   T1   I1   ]                    16 *-*   .alarm~new(waitTime, msg)  --
send message after waitTime, will unblock

[R1   T4   I3    G A1    L1    ]     38 *-* guard on  when
ctlAttribute>0.250 -- guard on

[R1   T2   I4    U A1    L1   *]     49 *-* guard off when
ctlAttribute>0.250 -- guard off

[R1   T1   I1   ]                    17 *-* end

[R1   T3   I6    U A1    L1    ]        >I> Method "BUMPCTLATTRIBUTE" with
scope "demoMT" in package "G:\test\orx\trace\docpgm.rex".

[R1   T2   I4    U A1    L1    ]        >K>   "WHEN" => "1"

[R1   T4   I3    G A1    L1   *]        >K>   "WHEN" => "1"

[R1   T1   I1   ]                     7 *-* do counter c rounds

[R1   T3   I6    U A1    L1    ]     26 *-* expose ctlAttribute

[R1   T2   I4    U A1    L1    ]     50 *-* ctlAttribute=random(0,125)/1000
-- add some randomness

[R1   T4   I3    G A1    L1   *]     39 *-* ctlAttribute=random(0,125)/1000
-- add some randomness

[R1   T3   I6    U A1    L1    ]     27 *-* TRACE n               -- set
trace to normal (in method "bumpCtlAttribute")

[R1   T2   I4    U A1    L1    ]        >>>   "0.12"

32 ctlAttribute=1

[R1   T4   I3    G A1    L1   *]        >>>   "0.075"

[R1   T2   I4    U A1    L1    ]     51 *-* guard on  when
ctlAttribute>0.250 -- guard on

[R1   T4   I3    G A1    L1   *]     40 *-* call sysSleep random(1,10)/1000
-- add some randomness

[R1   T5   I7    U A1    L1    ]        >I> Method "BUMPCTLATTRIBUTE" with
scope "demoMT" in package "G:\test\orx\trace\docpgm.rex".

[R1   T5   I7    U A1    L1    ]     26 *-* expose ctlAttribute

[R1   T5   I7    U A1    L1    ]     27 *-* TRACE n               -- set
trace to normal (in method "bumpCtlAttribute")

[R1   T2   I4    U A1    L1   *]        >K>   "WHEN" => "0"

32 ctlAttribute=1

[R1   T2   I4    U A1    L2   *]        >K>   "WHEN" => "1"

[R1   T2   I4    U A1    L2   *]     52 *-* call sysSleep random(1,10)/1000
-- add some randomness

[R1   T4   I3    G A1    L2   *]        >>>   "0"

[R1   T4   I3    G A1    L2   *]     41 *-* guard off when
ctlAttribute>0.250 -- guard off

[R1   T4   I3    G A1    L1    ]        >K>   "WHEN" => "1"

[R1   T4   I3    G A1    L1    ]     42 *-* ctlAttribute=random(0,125)/1000
-- add some randomness

[R1   T4   I3    G A1    L1    ]        >>>   "0.04"

[R1   T4   I3    G A1    L1    ]     43 *-* say .context~name": returning
..."

[R1   T4   I3    G A1    L1    ]        >>>   "MG: returning ..."

MG: returning ...

[R1   T2   I4    U A1    L1   *]        >>>   "0"

[R1   T2   I4    U A1    L1   *]     53 *-* say .context~name": returning
..."

[R1   T2   I4    U A1    L1   *]        >>>   "MU: returning ..."

MU: returning ...

The legend in the bracketed part: "R" ... interpreter instance (needed in
complex deployments like ooRexx JavaFX programs or in ooRexx JSP - Java
Server Pages - deployments), "T" ... thread, "I" ... invocation, "G" or "U"
method was defined as guarded or unguarded, "A" attribute pool (each object
has a different one), "L" ... object Lock count, "*" possessing the object's
lock.

In this relatively simple run only one object gets used such that we only
see a single attribute pool ("A1").

Once one uses more (and in complex multithreaded applications there may be
even hundred of hundreds such objects) objects, the attribute pool becomes
extremely helpful to quickly identify the traces of a specific object (which
may play a role in a deadlock situation). 


---






To illustrate I created the four standard formats for a test run of the
above program using three objects, i.e. "rexx docpgm.rex n 3", "rexx
docpgm.rex t 3", "rexx docpgm.rex s 3", and "rexx docpgm.rex f 3" and attach
them to this message. 


---


The current .TraceObject implementation allows in addition to easily define
one owns trace format and e.g. use the TIMESTAMP- and NR-entries in them
(for sorting, analyzing timings, etc.).

Also, the tracutil.cls package includes routines to save traces as json and
cvs files (and recreate traceobject collections from such json and csv
files) such that they can be analyzed with (Rexx) programs or loaded into
Excel and analyze the trace there with the available means, and much more.


HTH,

---rony











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

Reply via email to