On 22.01.2024 22:46, Rick McGuire wrote:
The part about the variable dictionary doesn't make any sense at all. The context where the line
is being traced doesn't really provide any useful information. The guard start is a combination of
the guard state of all the stack frames for a given activity. Since methods are guarded by
default, for any call stack, there are going to be many frames in a guarded state on
potentially many objects and scopes, including nesting. This does NOT belong as part of tracing.
It seriously clutters stuff up and doesn't really provide information that is needed on a
statement-by-statement basis.
The scenario where this information becomes helpful, if not important is in debugging complex, large
multithreaded applications. The variable dictionary number will allow for filtering all traces of a
specific object in that scope. Also, for scenarios where many instances of the same class exist and
get dispatched (maybe partially depending on context) on different threads, then one can study (by
writing a program for analyzing and filtering the produced trace log ex post) the behaviour (the
sequence of executing methods where context may influence that sequence) of specific instances of a
specific scope, attempting to find out whether irregularities exist and if so analyze how they
became to be going up the mtPrefix'ed trace log.
This information may not be so important for rather simple multithreaded traces, but in complex
situations this should serve as a big time saver for humans and for the programs they write for
analyzing huge mtPrefix trace logs ex post.
---
One idea that came up while thinking about your comment (not wanting to clutter which is important)
would be the following: define the class attribute mtPrefix to allow for the following values
instead of .true/.false as suggested so far (only the option's first letter mandatory):
* "None" ... no mtPrefix gets generated (default)
* "Full" ... the full mtPrefix will be generated by makeString, i.e. "[R1 T1 I5
G V1 L2 *] "
* "Standard" ... an mtPrefix will be generated by makeString, that leaves out
the Rexx interpreter
instance and the variable dictionary number, i.e. "[T1 I5 G L2 *] "
The default value would be "None", no mtPrefix gets created in the trace message. Otherwise the
programmer can chose whether he wishes a full or a standard mtPrefix to be created by LogObject.
This might cover most use cases.
In addition the programmer will be free to use the LogObject information freely to create whatever
he thinks will be helpful for debugging the multithreaded program in hand. Therefore if any
information in mtPrefix is seen as clutter or uninteresting for a programmer he can easily change
that for his mtPrefix trace logs. The same if he wishes to add additional information, e.g. adding
timestamps (maybe for profiling) to mtPrefix etc.
---
It would be most helpful if it became possible to indicate in the last character a blocking/waiting
state, such that '*' (indicating method is currently guarded and has the object lock) and ' ' (then
only if the method is currently unguarded) indicate executing, 'B' (or 'W') indicate
blocking/waiting (indicating a method currently guarded and waiting on the object's lock). This
would ease analyzing the trace log considerably, if interested to find the blocked statements in a
multithreaded program in case of deadlocks.
---rony
On Mon, Jan 22, 2024 at 11:32 AM Rony G. Flatscher <rony.flatsc...@wu.ac.at>
wrote:
Here an ooRexx implementation of the proposed TraceObject class in today's
"Proposal for
multithreaded trace prefix" class:
/*
========================================================================= */
::class
"TraceObject" subclass StringTable public /*
------------------------------------------------------------------------- */
::attribute
mtPrefix class -- if .true causes the mtPrefix to be created /*
------------------------------------------------------------------------- */
::method
MAKESTRING if self~class~mtPrefix<>.true then -- do not show
multithreaded prefix return
self["TRACELINE"] -- return standard trace line mb = .MutableBuffer~new
-- for performance
reasons mb~append("[") mb~append("R", adjLeft(self["INSTANCE"] ,3), "
") -- R_exx
interpreter instance mb~append("T", adjLeft(self["THREAD"] ,3), " ") --
T_hread/activity
mb~append("I", adjLeft(self["INVOCATION"],3) ) -- I_nvocation/activation
vd=self["VARIABLEDICTIONARY"] if vd<>0 then -- an object's variable
dictionary in hand, we
are in a method do mb~append(" ") mb~append(self["ISGUARDED"]~?("G","U") , "
") --
G_uarded or U_unguarded mb~append("V", adjLeft(vd ,3), " ") --
V_ariable dictionary pool
mb~append("L", adjLeft(self["LOCKCOUNT"],3), " ") -- L ... lock reserve
count
mb~append(self["ISLOCKED"]~?("*"," ")) -- asterisk to indicate holding
object lock (can
execute) end mb~append("] ", self["TRACELINE"]) return mb~string --
return trace line with
mtPrefix adjLeft: procedure -- left adjust, but make sure we show all
chars use arg value,
width if value~length>=width then -- no left adjustment return value
return
value~left(width) -- left adjust with given width
---rony
_______________________________________________
Oorexx-devel mailing list
Oorexx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/oorexx-devel